diff --git a/src/main/java/com/drtshock/playervaults/Metrics.java b/src/main/java/com/drtshock/playervaults/Metrics.java
index caf9f92..82bd839 100644
--- a/src/main/java/com/drtshock/playervaults/Metrics.java
+++ b/src/main/java/com/drtshock/playervaults/Metrics.java
@@ -12,23 +12,12 @@
import org.bukkit.plugin.ServicePriority;
import javax.net.ssl.HttpsURLConnection;
-import java.io.BufferedReader;
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStreamReader;
+import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Timer;
-import java.util.TimerTask;
-import java.util.UUID;
+import java.util.*;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.zip.GZIPOutputStream;
diff --git a/src/main/java/com/drtshock/playervaults/PlayerVaults.java b/src/main/java/com/drtshock/playervaults/PlayerVaults.java
index cace052..11cd552 100644
--- a/src/main/java/com/drtshock/playervaults/PlayerVaults.java
+++ b/src/main/java/com/drtshock/playervaults/PlayerVaults.java
@@ -18,13 +18,7 @@
package com.drtshock.playervaults;
-import com.drtshock.playervaults.commands.ConsoleCommand;
-import com.drtshock.playervaults.commands.ConvertCommand;
-import com.drtshock.playervaults.commands.DeleteCommand;
-import com.drtshock.playervaults.commands.HelpMeCommand;
-import com.drtshock.playervaults.commands.SignCommand;
-import com.drtshock.playervaults.commands.SignSetInfo;
-import com.drtshock.playervaults.commands.VaultCommand;
+import com.drtshock.playervaults.commands.*;
import com.drtshock.playervaults.config.Loader;
import com.drtshock.playervaults.config.file.Config;
import com.drtshock.playervaults.config.file.Translation;
@@ -39,15 +33,11 @@
import com.drtshock.playervaults.vaultmanagement.VaultManager;
import com.drtshock.playervaults.vaultmanagement.VaultViewInfo;
import com.google.gson.Gson;
-import net.kyori.adventure.audience.Audience;
+import dev.kitteh.cardboardbox.CardboardBox;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.minimessage.MiniMessage;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.Material;
-import org.bukkit.OfflinePlayer;
-import org.bukkit.Registry;
+import org.bukkit.*;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.InvalidConfigurationException;
@@ -60,16 +50,9 @@
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
-import dev.kitteh.cardboardbox.CardboardBox;
import sun.misc.Unsafe;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.io.StringWriter;
+import java.io.*;
import java.lang.reflect.Field;
import java.net.HttpURLConnection;
import java.net.URL;
@@ -79,13 +62,7 @@
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
+import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Supplier;
@@ -198,6 +175,24 @@ public void run() {
}
}.runTaskTimer(this, 20, 20);
+ // Force save after an amount of time
+ new BukkitRunnable() {
+ @Override
+ public void run() {
+ long now = System.currentTimeMillis();
+ inVault.forEach((uuid, info) -> {
+ Player p = Bukkit.getPlayer(UUID.fromString(uuid));
+ if (p != null && p.isOnline()) {
+ Inventory inv = p.getOpenInventory().getTopInventory();
+ if (inv != null && inv.getViewers().size() >= 1) {
+ // Player is still in the vault, force save after a timeout
+ VaultManager.getInstance().saveVault(inv, p.getUniqueId().toString(), info.getNumber());
+ }
+ }
+ });
+ }
+ }.runTaskTimer(this, 6000, 6000);
+
this.metrics = new Metrics(this, 6905);
Plugin vault = getServer().getPluginManager().getPlugin("Vault");
this.metricsDrillPie("vault", () -> this.metricsPluginInfo(vault));
diff --git a/src/main/java/com/drtshock/playervaults/config/Loader.java b/src/main/java/com/drtshock/playervaults/config/Loader.java
index 0dd9759..6fbbf61 100644
--- a/src/main/java/com/drtshock/playervaults/config/Loader.java
+++ b/src/main/java/com/drtshock/playervaults/config/Loader.java
@@ -22,12 +22,7 @@
import com.drtshock.playervaults.config.annotation.ConfigName;
import com.drtshock.playervaults.config.annotation.WipeOnReload;
import com.drtshock.playervaults.config.file.Translation;
-import com.drtshock.playervaults.lib.com.typesafe.config.Config;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigFactory;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigRenderOptions;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValue;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValueFactory;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValueType;
+import com.drtshock.playervaults.lib.com.typesafe.config.*;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -38,14 +33,7 @@
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
public class Loader {
public static void loadAndSave(@NonNull String fileName, @NonNull Object config) throws IOException, IllegalAccessException {
diff --git a/src/main/java/com/drtshock/playervaults/config/file/Translation.java b/src/main/java/com/drtshock/playervaults/config/file/Translation.java
index 857b7de..2b3246b 100644
--- a/src/main/java/com/drtshock/playervaults/config/file/Translation.java
+++ b/src/main/java/com/drtshock/playervaults/config/file/Translation.java
@@ -16,13 +16,7 @@
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
import java.util.stream.Collectors;
@SuppressWarnings("FieldMayBeFinal")
diff --git a/src/main/java/com/drtshock/playervaults/converters/AxVaults2Converter.java b/src/main/java/com/drtshock/playervaults/converters/AxVaults2Converter.java
index 9a25212..68a5c1a 100644
--- a/src/main/java/com/drtshock/playervaults/converters/AxVaults2Converter.java
+++ b/src/main/java/com/drtshock/playervaults/converters/AxVaults2Converter.java
@@ -25,7 +25,6 @@
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
-import org.bukkit.util.io.BukkitObjectInputStream;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
diff --git a/src/main/java/com/drtshock/playervaults/converters/AxVaultsConverter.java b/src/main/java/com/drtshock/playervaults/converters/AxVaultsConverter.java
index 57b3b79..be7cb20 100644
--- a/src/main/java/com/drtshock/playervaults/converters/AxVaultsConverter.java
+++ b/src/main/java/com/drtshock/playervaults/converters/AxVaultsConverter.java
@@ -33,7 +33,8 @@
import java.lang.reflect.Field;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
-import java.util.*;
+import java.util.HashSet;
+import java.util.Set;
import java.util.logging.Level;
public class AxVaultsConverter implements Converter {
diff --git a/src/main/java/com/drtshock/playervaults/converters/FairyVaultsConverter.java b/src/main/java/com/drtshock/playervaults/converters/FairyVaultsConverter.java
index a5cef18..c5c636d 100644
--- a/src/main/java/com/drtshock/playervaults/converters/FairyVaultsConverter.java
+++ b/src/main/java/com/drtshock/playervaults/converters/FairyVaultsConverter.java
@@ -25,6 +25,7 @@
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
+
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Connection;
diff --git a/src/main/java/com/drtshock/playervaults/converters/UniVaultsConverter.java b/src/main/java/com/drtshock/playervaults/converters/UniVaultsConverter.java
index 29a788f..c6b3803 100644
--- a/src/main/java/com/drtshock/playervaults/converters/UniVaultsConverter.java
+++ b/src/main/java/com/drtshock/playervaults/converters/UniVaultsConverter.java
@@ -7,24 +7,14 @@
import org.bukkit.command.CommandSender;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
-import org.bukkit.plugin.Plugin;
import org.bukkit.util.io.BukkitObjectInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.lang.reflect.Field;
-import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
import java.util.Arrays;
import java.util.Base64;
-import java.util.HashSet;
-import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.regex.Matcher;
diff --git a/src/main/java/com/drtshock/playervaults/converters/XVaultsConverter.java b/src/main/java/com/drtshock/playervaults/converters/XVaultsConverter.java
index 444e7b4..b12238f 100644
--- a/src/main/java/com/drtshock/playervaults/converters/XVaultsConverter.java
+++ b/src/main/java/com/drtshock/playervaults/converters/XVaultsConverter.java
@@ -25,21 +25,13 @@
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
-import org.bukkit.plugin.Plugin;
import java.io.File;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
-import java.util.logging.Level;
public class XVaultsConverter implements Converter {
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/ConfigException.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/ConfigException.java
index d5feb6c..d15e020 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/ConfigException.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/ConfigException.java
@@ -3,12 +3,12 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config;
+import com.drtshock.playervaults.lib.com.typesafe.config.impl.ConfigImplUtil;
+
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Field;
-import com.drtshock.playervaults.lib.com.typesafe.config.impl.ConfigImplUtil;
-
/**
* All exceptions thrown by the library are subclasses of
* ConfigException.
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/ConfigOriginFactory.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/ConfigOriginFactory.java
index b1dd318..7327fa4 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/ConfigOriginFactory.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/ConfigOriginFactory.java
@@ -1,9 +1,9 @@
package com.drtshock.playervaults.lib.com.typesafe.config;
-import java.net.URL;
-
import com.drtshock.playervaults.lib.com.typesafe.config.impl.ConfigImpl;
+import java.net.URL;
+
/**
* This class contains some static factory methods for building a {@link
* ConfigOrigin}. {@code ConfigOrigin}s are automatically created when you
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/ConfigUtil.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/ConfigUtil.java
index 48c44c6..1aef3a7 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/ConfigUtil.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/ConfigUtil.java
@@ -1,9 +1,9 @@
package com.drtshock.playervaults.lib.com.typesafe.config;
-import java.util.List;
-
import com.drtshock.playervaults.lib.com.typesafe.config.impl.ConfigImplUtil;
+import java.util.List;
+
/**
* Contains static utility methods.
*
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/ConfigValueFactory.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/ConfigValueFactory.java
index 4f8d8ee..9e271d9 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/ConfigValueFactory.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/ConfigValueFactory.java
@@ -3,10 +3,10 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config;
-import java.util.Map;
-
import com.drtshock.playervaults.lib.com.typesafe.config.impl.ConfigImpl;
+import java.util.Map;
+
/**
* This class holds some static factory methods for building {@link ConfigValue}
* instances. See also {@link ConfigFactory} which has methods for parsing files
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/AbstractConfigNode.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/AbstractConfigNode.java
index 1de6857..0990d32 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/AbstractConfigNode.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/AbstractConfigNode.java
@@ -4,6 +4,7 @@
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
import com.drtshock.playervaults.lib.com.typesafe.config.parser.ConfigNode;
+
import java.util.Collection;
abstract class AbstractConfigNode implements ConfigNode {
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/AbstractConfigObject.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/AbstractConfigObject.java
index 948f2b6..aa2f212 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/AbstractConfigObject.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/AbstractConfigObject.java
@@ -3,19 +3,9 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigMergeable;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigObject;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigRenderOptions;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValue;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValueType;
+import com.drtshock.playervaults.lib.com.typesafe.config.*;
+
+import java.util.*;
abstract class AbstractConfigObject extends AbstractConfigValue implements ConfigObject, Container {
final private SimpleConfig config;
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/AbstractConfigValue.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/AbstractConfigValue.java
index a63f50d..d31c4c0 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/AbstractConfigValue.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/AbstractConfigValue.java
@@ -3,18 +3,9 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigMergeable;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigObject;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigRenderOptions;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValue;
+import com.drtshock.playervaults.lib.com.typesafe.config.*;
+
+import java.util.*;
/**
*
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigBeanImpl.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigBeanImpl.java
index 3a8c353..14cc6bc 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigBeanImpl.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigBeanImpl.java
@@ -1,30 +1,15 @@
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
+import com.drtshock.playervaults.lib.com.typesafe.config.*;
+import com.drtshock.playervaults.lib.com.typesafe.config.Optional;
+
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
+import java.lang.reflect.*;
import java.time.Duration;
-import java.util.Set;
-
-import com.drtshock.playervaults.lib.com.typesafe.config.Config;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigObject;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigList;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigMemorySize;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValue;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValueType;
-import com.drtshock.playervaults.lib.com.typesafe.config.Optional;
+import java.util.*;
/**
* Internal implementation detail, not ABI stable, do not touch.
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigBoolean.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigBoolean.java
index b121f45..a77a1f2 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigBoolean.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigBoolean.java
@@ -3,12 +3,12 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
-import java.io.ObjectStreamException;
-import java.io.Serializable;
-
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValueType;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+
final class ConfigBoolean extends AbstractConfigValue implements Serializable {
private static final long serialVersionUID = 2L;
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigConcatenation.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigConcatenation.java
index 82c4785..25e0820 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigConcatenation.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigConcatenation.java
@@ -1,16 +1,12 @@
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
+import com.drtshock.playervaults.lib.com.typesafe.config.*;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigObject;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigRenderOptions;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValueType;
-
/**
* A ConfigConcatenation represents a list of values to be concatenated (see the
* spec). It only has to exist if at least one value is an unresolved
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigDelayedMerge.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigDelayedMerge.java
index 19bbfb7..83ac300 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigDelayedMerge.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigDelayedMerge.java
@@ -3,16 +3,16 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigRenderOptions;
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValueType;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
/**
* The issue here is that we want to first merge our stack of config files, and
* then we want to evaluate substitutions. But if two substitutions both expand
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigDelayedMergeObject.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigDelayedMergeObject.java
index fb50805..6f92019 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigDelayedMergeObject.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigDelayedMergeObject.java
@@ -3,18 +3,9 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigList;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigMergeable;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigRenderOptions;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValue;
+import com.drtshock.playervaults.lib.com.typesafe.config.*;
+
+import java.util.*;
// This is just like ConfigDelayedMerge except we know statically
// that it will turn out to be an object.
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigDocumentParser.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigDocumentParser.java
index 3862796..678ec05 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigDocumentParser.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigDocumentParser.java
@@ -3,13 +3,9 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
-import java.util.*;
+import com.drtshock.playervaults.lib.com.typesafe.config.*;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigParseOptions;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigSyntax;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValueType;
+import java.util.*;
final class ConfigDocumentParser {
static ConfigNodeRoot parse(Iterator tokens, ConfigOrigin origin, ConfigParseOptions options) {
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigDouble.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigDouble.java
index 523106a..2998b27 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigDouble.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigDouble.java
@@ -3,12 +3,12 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
-import java.io.ObjectStreamException;
-import java.io.Serializable;
-
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValueType;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+
final class ConfigDouble extends ConfigNumber implements Serializable {
private static final long serialVersionUID = 2L;
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigImpl.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigImpl.java
index 291b476..c22767c 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigImpl.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigImpl.java
@@ -3,30 +3,16 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
+import com.drtshock.playervaults.lib.com.typesafe.config.*;
+import com.drtshock.playervaults.lib.com.typesafe.config.impl.SimpleIncluder.NameSource;
+
import java.io.File;
import java.lang.ref.WeakReference;
import java.net.URL;
import java.time.Duration;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
+import java.util.*;
import java.util.concurrent.Callable;
-import com.drtshock.playervaults.lib.com.typesafe.config.Config;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigIncluder;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigMemorySize;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigObject;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigParseOptions;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigParseable;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValue;
-import com.drtshock.playervaults.lib.com.typesafe.config.impl.SimpleIncluder.NameSource;
-
/**
* Internal implementation detail, not ABI stable, do not touch.
* For use only by the {@link com.typesafe.config} package.
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigImplUtil.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigImplUtil.java
index 139254b..b1c7adf 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigImplUtil.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigImplUtil.java
@@ -3,19 +3,15 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
+import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
+import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
+
+import java.io.*;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
-
/**
* Internal implementation detail, not ABI stable, do not touch.
* For use only by the {@link com.typesafe.config} package.
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigInt.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigInt.java
index ae3c69c..e3f8c63 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigInt.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigInt.java
@@ -3,12 +3,12 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
-import java.io.ObjectStreamException;
-import java.io.Serializable;
-
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValueType;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+
final class ConfigInt extends ConfigNumber implements Serializable {
private static final long serialVersionUID = 2L;
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigLong.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigLong.java
index 40736c2..6234543 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigLong.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigLong.java
@@ -3,12 +3,12 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
-import java.io.ObjectStreamException;
-import java.io.Serializable;
-
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValueType;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+
final class ConfigLong extends ConfigNumber implements Serializable {
private static final long serialVersionUID = 2L;
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigNodeComplexValue.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigNodeComplexValue.java
index 7191333..9cdfe37 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigNodeComplexValue.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigNodeComplexValue.java
@@ -3,7 +3,8 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
abstract class ConfigNodeComplexValue extends AbstractConfigNodeValue {
final protected ArrayList children;
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigNull.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigNull.java
index 50842df..90d92dd 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigNull.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigNull.java
@@ -3,13 +3,13 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
-import java.io.ObjectStreamException;
-import java.io.Serializable;
-
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigRenderOptions;
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValueType;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+
/**
* This exists because sometimes null is not the same as missing. Specifically,
* if a value is set to null we can give a better error message (indicating
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigNumber.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigNumber.java
index 1c5c380..3efb9f3 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigNumber.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigNumber.java
@@ -3,12 +3,12 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
-import java.io.ObjectStreamException;
-import java.io.Serializable;
-
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+
abstract class ConfigNumber extends AbstractConfigValue implements Serializable {
private static final long serialVersionUID = 2L;
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigParser.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigParser.java
index 19a4bc0..6da8752 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigParser.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigParser.java
@@ -3,22 +3,12 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
+import com.drtshock.playervaults.lib.com.typesafe.config.*;
+
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigIncludeContext;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigParseOptions;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigSyntax;
+import java.util.*;
final class ConfigParser {
static AbstractConfigValue parse(ConfigNodeRoot document,
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigReference.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigReference.java
index 762264c..8c2ebbe 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigReference.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigReference.java
@@ -1,14 +1,10 @@
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
+import com.drtshock.playervaults.lib.com.typesafe.config.*;
+
import java.util.Collection;
import java.util.Collections;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigRenderOptions;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValue;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValueType;
-
/**
* ConfigReference replaces ConfigReference (the older class kept for back
* compat) and represents the ${} substitution syntax. It can resolve to any
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigString.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigString.java
index 36e22e2..c77f0b2 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigString.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ConfigString.java
@@ -3,13 +3,13 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
-import java.io.ObjectStreamException;
-import java.io.Serializable;
-
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigRenderOptions;
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValueType;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+
abstract class ConfigString extends AbstractConfigValue implements Serializable {
private static final long serialVersionUID = 2L;
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/DefaultTransformer.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/DefaultTransformer.java
index f9987bc..83163f8 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/DefaultTransformer.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/DefaultTransformer.java
@@ -3,14 +3,10 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Map;
-
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValueType;
+import java.util.*;
+
/**
* Default automatic type transformations.
*/
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/Parseable.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/Parseable.java
index 4ab4a4b..ff5c74a 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/Parseable.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/Parseable.java
@@ -3,34 +3,13 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FilterReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.UnsupportedEncodingException;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.*;
-
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigIncludeContext;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigObject;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigParseOptions;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigParseable;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigSyntax;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValue;
+import com.drtshock.playervaults.lib.com.typesafe.config.*;
import com.drtshock.playervaults.lib.com.typesafe.config.parser.ConfigDocument;
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
/**
* Internal implementation detail, not ABI stable, do not touch.
* For use only by the {@link com.typesafe.config} package.
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/Path.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/Path.java
index d833f09..0402759 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/Path.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/Path.java
@@ -3,10 +3,11 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
-import java.util.*;
-
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
+import java.util.Iterator;
+import java.util.List;
+
final class Path {
final private String first;
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/PathBuilder.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/PathBuilder.java
index 7a33f8b..6c08f24 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/PathBuilder.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/PathBuilder.java
@@ -3,10 +3,10 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
-import java.util.Stack;
-
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
+import java.util.Stack;
+
final class PathBuilder {
// the keys are kept "backward" (top of stack is end of path)
final private Stack keys;
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/PropertiesParser.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/PropertiesParser.java
index 50e31a3..43c7145 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/PropertiesParser.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/PropertiesParser.java
@@ -3,21 +3,13 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
-import java.io.IOException;
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.*;
+
final class PropertiesParser {
static AbstractConfigObject parse(Reader reader,
ConfigOrigin origin) throws IOException {
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ResolveContext.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ResolveContext.java
index 4f1ef72..0e9182a 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ResolveContext.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/ResolveContext.java
@@ -1,14 +1,10 @@
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
-import java.util.Collections;
-import java.util.IdentityHashMap;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Set;
-
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigResolveOptions;
+import java.util.*;
+
final class ResolveContext {
final private ResolveMemos memos;
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/SerializedConfigValue.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/SerializedConfigValue.java
index f159f7f..b85d4bd 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/SerializedConfigValue.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/SerializedConfigValue.java
@@ -3,32 +3,10 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInput;
-import java.io.DataInputStream;
-import java.io.DataOutput;
-import java.io.DataOutputStream;
-import java.io.Externalizable;
-import java.io.IOException;
-import java.io.NotSerializableException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.io.ObjectStreamException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.EnumMap;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import com.drtshock.playervaults.lib.com.typesafe.config.Config;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigList;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigObject;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValue;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValueType;
+import com.drtshock.playervaults.lib.com.typesafe.config.*;
+
+import java.io.*;
+import java.util.*;
/**
* Deliberately shoving all the serialization code into this class instead of
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/SimpleConfig.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/SimpleConfig.java
index b8c897f..0105a93 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/SimpleConfig.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/SimpleConfig.java
@@ -3,6 +3,8 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
+import com.drtshock.playervaults.lib.com.typesafe.config.*;
+
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.math.BigDecimal;
@@ -12,26 +14,9 @@
import java.time.Period;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAmount;
-import java.util.AbstractMap;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
import java.util.concurrent.TimeUnit;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigList;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigMemorySize;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigMergeable;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigObject;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigResolveOptions;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValue;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValueType;
-import com.drtshock.playervaults.lib.com.typesafe.config.Config;
-
/**
* One thing to keep in mind in the future: as Collection-like APIs are added
* here, including iterators or size() or anything, they should be consistent
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/SimpleConfigList.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/SimpleConfigList.java
index 5007d9c..cc31721 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/SimpleConfigList.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/SimpleConfigList.java
@@ -3,20 +3,11 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
+import com.drtshock.playervaults.lib.com.typesafe.config.*;
+
import java.io.ObjectStreamException;
import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
-
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigList;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigRenderOptions;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValue;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValueType;
+import java.util.*;
final class SimpleConfigList extends AbstractConfigValue implements ConfigList, Container, Serializable {
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/SimpleConfigObject.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/SimpleConfigObject.java
index 381d940..86e6e66 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/SimpleConfigObject.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/SimpleConfigObject.java
@@ -3,24 +3,11 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
+import com.drtshock.playervaults.lib.com.typesafe.config.*;
+
import java.io.ObjectStreamException;
import java.io.Serializable;
-import java.util.AbstractMap;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigObject;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigRenderOptions;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValue;
+import java.util.*;
final class SimpleConfigObject extends AbstractConfigObject implements Serializable {
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/SimpleConfigOrigin.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/SimpleConfigOrigin.java
index 790fccb..d58f031 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/SimpleConfigOrigin.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/SimpleConfigOrigin.java
@@ -3,21 +3,15 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
+import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
+import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
+import com.drtshock.playervaults.lib.com.typesafe.config.impl.SerializedConfigValue.SerializedField;
+
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.EnumMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
-import com.drtshock.playervaults.lib.com.typesafe.config.impl.SerializedConfigValue.SerializedField;
+import java.util.*;
// it would be cleaner to have a class hierarchy for various origin types,
// but was hoping this would be enough simpler to be a little messy. eh.
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/SimpleIncluder.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/SimpleIncluder.java
index 04c30be..5ab1d6f 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/SimpleIncluder.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/SimpleIncluder.java
@@ -3,24 +3,14 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
+import com.drtshock.playervaults.lib.com.typesafe.config.*;
+
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigFactory;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigIncludeContext;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigIncluder;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigIncluderClasspath;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigIncluderFile;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigIncluderURL;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigObject;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigParseOptions;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigParseable;
-import com.drtshock.playervaults.lib.com.typesafe.config.ConfigSyntax;
-
class SimpleIncluder implements FullIncluder {
private ConfigIncluder fallback;
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/Tokenizer.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/Tokenizer.java
index e6d7a5c..8bb7ea9 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/Tokenizer.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/Tokenizer.java
@@ -3,18 +3,14 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
-import java.io.IOException;
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Queue;
-
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigSyntax;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.*;
+
final class Tokenizer {
// this exception should not leave this file
private static class ProblemException extends Exception {
diff --git a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/Tokens.java b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/Tokens.java
index 08762d0..dfe92d1 100644
--- a/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/Tokens.java
+++ b/src/main/java/com/drtshock/playervaults/lib/com/typesafe/config/impl/Tokens.java
@@ -3,12 +3,12 @@
*/
package com.drtshock.playervaults.lib.com.typesafe.config.impl;
-import java.util.List;
-
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigException;
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigOrigin;
import com.drtshock.playervaults.lib.com.typesafe.config.ConfigValueType;
+import java.util.List;
+
/* FIXME the way the subclasses of Token are private with static isFoo and accessors is kind of ridiculous. */
final class Tokens {
static private class Value extends Token {
diff --git a/src/main/java/com/drtshock/playervaults/listeners/Listeners.java b/src/main/java/com/drtshock/playervaults/listeners/Listeners.java
index 5e60897..4837a29 100644
--- a/src/main/java/com/drtshock/playervaults/listeners/Listeners.java
+++ b/src/main/java/com/drtshock/playervaults/listeners/Listeners.java
@@ -28,7 +28,6 @@
import org.bukkit.Bukkit;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.EntityType;
-import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
@@ -44,50 +43,91 @@
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
public class Listeners implements Listener {
public final PlayerVaults plugin;
private final VaultManager vaultManager = VaultManager.getInstance();
+ // Guards against double-saves per player
+ private final Set savePending = Collections.newSetFromMap(new ConcurrentHashMap<>());
+
public Listeners(PlayerVaults playerVaults) {
this.plugin = playerVaults;
}
public void saveVault(Player player, Inventory inventory) {
- VaultViewInfo info = plugin.getInVault().remove(player.getUniqueId().toString());
- if (info != null) {
- boolean badDay = false;
- if (!(inventory.getHolder() instanceof VaultHolder)) {
- PlayerVaults.getInstance().getLogger().severe("Encountered lost vault situation for player '" + player.getName() + "', instead finding a '" + inventory.getType() + "' - attempting to save the vault if no viewers present");
- badDay = true;
- inventory = plugin.getOpenInventories().get(info.toString());
- if (inventory == null) {
- PlayerVaults.getInstance().getLogger().severe("Could not find inventory");
- return;
- }
+ UUID uuid = player.getUniqueId();
+
+ if (!savePending.add(uuid)) {
+ PlayerVaults.debug("Save already pending for " + player.getName() + ", skipping duplicate.");
+ return;
+ }
+
+ try {
+ VaultViewInfo info = plugin.getInVault().remove(uuid.toString());
+ if (info == null) return;
+
+ // This prevents ghost-item exploits
+ final ItemStack[] snapshot = snapshotInventory(inventory, info, player);
+ if (snapshot == null) {
+ // Re-insert info so a future close/quit can retry
+ plugin.getInVault().put(uuid.toString(), info);
+ return;
}
- Inventory inv = Bukkit.createInventory(null, inventory.getSize());
- inv.setContents(inventory.getContents().clone());
-
- PlayerVaults.debug(inventory.getType() + " " + inventory.getClass().getSimpleName());
- if (inventory.getViewers().size() <= 1) {
- PlayerVaults.debug("Saving!");
- vaultManager.saveVault(inv, info.getVaultName(), info.getNumber());
- plugin.getOpenInventories().remove(info.toString());
- } else {
- if (badDay) {
- PlayerVaults.getInstance().getLogger().severe("Viewers size >0: " + inventory.getViewers().stream().map(HumanEntity::getName).collect(Collectors.joining(", ")));
- }
- PlayerVaults.debug("Other viewers found, not saving! " + inventory.getViewers().stream().map(HumanEntity::getName).collect(Collectors.joining(" ")));
+
+ plugin.getOpenInventories().remove(info.toString());
+
+ // Build a clean inventory from the validated snapshot and hand it to the manager
+ Inventory saveInv = Bukkit.createInventory(null, inventory.getSize());
+ saveInv.setContents(snapshot);
+
+ vaultManager.saveVault(saveInv, info.getVaultName(), info.getNumber());
+ } finally {
+ // Always release the guard so future opens of this vault work correctly
+ savePending.remove(uuid);
+ }
+ }
+
+ private ItemStack[] snapshotInventory(Inventory inventory, VaultViewInfo info, Player player) {
+ if (inventory.getViewers().size() > 1) {
+ Inventory tracked = plugin.getOpenInventories().get(info.toString());
+ if (tracked == null) {
+ PlayerVaults.getInstance().getLogger().severe(
+ "Could not resolve shared inventory for " + player.getName());
+ return null;
}
+ // Don't save, the last viewer to close will handle it
+ PlayerVaults.debug("Other viewers present for " + player.getName() + ", deferring save.");
+ return null;
}
+
+ if (!(inventory.getHolder() instanceof VaultHolder) && inventory.getViewers().size() > 0) {
+ PlayerVaults.getInstance().getLogger().warning(
+ "Unexpected holder type for " + player.getName() + ": " + inventory.getType() +
+ " — contents will still be saved.");
+ }
+
+ ItemStack[] raw = inventory.getContents();
+ ItemStack[] sanitised = new ItemStack[raw.length];
+
+ for (int i = 0; i < raw.length; i++) {
+ ItemStack item = raw[i];
+ if (item == null) {
+ sanitised[i] = null;
+ continue;
+ }
+ int amount = item.getAmount();
+ int maxStack = item.getMaxStackSize();
+ if (amount < 1 || amount > maxStack) {
+ ItemStack clamped = item.clone();
+ clamped.setAmount(Math.max(1, Math.min(amount, maxStack)));
+ sanitised[i] = clamped;
+ } else sanitised[i] = item.clone();
+ }
+ return sanitised;
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
@@ -97,72 +137,92 @@ public void onTeleport(PlayerTeleportEvent event) {
}
Player p = event.getPlayer();
// The player will either quit, die, or close the inventory at some point
- if (plugin.getInVault().containsKey(p.getUniqueId().toString())) {
- return;
- }
- saveVault(p, p.getOpenInventory().getTopInventory());
+ if (plugin.getInVault().containsKey(p.getUniqueId().toString()))
+ p.closeInventory();
}
@EventHandler(priority = EventPriority.HIGH)
public void onQuit(PlayerQuitEvent event) {
- saveVault(event.getPlayer(), event.getPlayer().getOpenInventory().getTopInventory());
+ Player player = event.getPlayer();
+ if (plugin.getInVault().containsKey(player.getUniqueId().toString())) {
+ saveVault(player, player.getOpenInventory().getTopInventory());
+ }
+ savePending.remove(player.getUniqueId());
}
@EventHandler(priority = EventPriority.HIGH)
public void onDeath(PlayerDeathEvent event) {
- saveVault(event.getEntity(), event.getEntity().getOpenInventory().getTopInventory());
+ Player player = event.getEntity();
+ if (plugin.getInVault().containsKey(player.getUniqueId().toString())) {
+ saveVault(player, player.getOpenInventory().getTopInventory());
+ }
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onClose(InventoryCloseEvent event) {
- saveVault((Player) event.getPlayer(), event.getInventory());
+ Player player = (Player) event.getPlayer();
+ VaultViewInfo info = plugin.getInVault().get(player.getUniqueId().toString());
+
+ // If the player is still inside the inventory
+ if (info != null) {
+
+ // Put the items to a new inventory, so the system can save and the garbage collector can move faster
+ Inventory inv = Bukkit.createInventory(null, event.getInventory().getSize());
+ inv.setContents(event.getInventory().getContents().clone());
+
+ saveVault(player, inv);
+ }
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onInteractEntity(PlayerInteractEntityEvent event) {
Player player = event.getPlayer();
EntityType type = event.getRightClicked().getType();
- if ((type == EntityType.VILLAGER || type == EntityType.MINECART) && PlayerVaults.getInstance().getInVault().containsKey(player.getUniqueId().toString())) {
+ if ((type == EntityType.VILLAGER || type == EntityType.MINECART)
+ && plugin.getInVault().containsKey(player.getUniqueId().toString())) {
event.setCancelled(true);
}
}
@EventHandler(ignoreCancelled = true)
public void onClick(InventoryClickEvent event) {
- if (!(event.getWhoClicked() instanceof Player)) {
+ if (!(event.getWhoClicked() instanceof Player player))
return;
+
+ Inventory clickedInventory = event.getClickedInventory();
+ if (clickedInventory == null) return;
+
+ VaultViewInfo info = plugin.getInVault().get(player.getUniqueId().toString());
+ if (info == null) return;
+
+ String inventoryTitle = event.getView().getTitle();
+ String title = this.plugin.getVaultTitle(String.valueOf(info.getNumber()));
+ if (!inventoryTitle.equalsIgnoreCase(title))
+ return;
+
+ // This prevents duplication via SWAP_OFFHAND or hotbar-number key
+ ItemStack[] items = new ItemStack[2];
+ items[0] = event.getCurrentItem();
+
+ String clickName = event.getClick().name();
+ if (event.getHotbarButton() > -1) {
+ items[1] = player.getInventory().getItem(event.getHotbarButton());
+ } else if (clickName.equals("SWAP_OFFHAND")) {
+ items[1] = player.getInventory().getItemInOffHand();
}
- Player player = (Player) event.getWhoClicked();
+ // Cancel all clicks to prevent ghost items being inserted after snapshot
+ if (savePending.contains(player.getUniqueId())) {
+ event.setCancelled(true);
+ return;
+ }
- Inventory clickedInventory = event.getClickedInventory();
- if (clickedInventory != null) {
- VaultViewInfo info = PlayerVaults.getInstance().getInVault().get(player.getUniqueId().toString());
- if (info != null) {
- int num = info.getNumber();
- String inventoryTitle = event.getView().getTitle();
- String title = this.plugin.getVaultTitle(String.valueOf(num));
- if (inventoryTitle.equalsIgnoreCase(title)) {
- ItemStack[] items = new ItemStack[2];
- items[0] = event.getCurrentItem();
- if (event.getHotbarButton() > -1 && event.getWhoClicked().getInventory().getItem(event.getHotbarButton()) != null) {
- items[1] = event.getWhoClicked().getInventory().getItem(event.getHotbarButton());
- }
- if (event.getClick().name().equals("SWAP_OFFHAND")) {
- items[1] = event.getWhoClicked().getInventory().getItemInOffHand();
- }
-
- if (!player.hasPermission(Permission.BYPASS_BLOCKED_ITEMS)) {
- for (ItemStack item : items) {
- if (item == null) {
- continue;
- }
- if (this.isBlocked(player, item, info)) {
- event.setCancelled(true);
- return;
- }
- }
- }
+ if (!player.hasPermission(Permission.BYPASS_BLOCKED_ITEMS)) {
+ for (ItemStack item : items) {
+ if (item == null) continue;
+ if (this.isBlocked(player, item, info)) {
+ event.setCancelled(true);
+ return;
}
}
}
@@ -170,28 +230,31 @@ public void onClick(InventoryClickEvent event) {
@EventHandler(ignoreCancelled = true)
public void onDrag(InventoryDragEvent event) {
- if (!(event.getWhoClicked() instanceof Player)) {
+ if (!(event.getWhoClicked() instanceof Player player))
+ return;
+
+ Inventory draggedInventory = event.getInventory();
+ if (draggedInventory == null) return;
+
+ VaultViewInfo info = plugin.getInVault().get(player.getUniqueId().toString());
+ if (info == null) return;
+
+ String inventoryTitle = event.getView().getTitle();
+ String title = this.plugin.getVaultTitle(String.valueOf(info.getNumber()));
+ if (inventoryTitle == null || !inventoryTitle.equalsIgnoreCase(title))
+ return;
+
+ // Block drags while a save is pending to prevent ghost-item insertion.
+ if (savePending.contains(player.getUniqueId())) {
+ event.setCancelled(true);
return;
}
- Player player = (Player) event.getWhoClicked();
-
- Inventory clickedInventory = event.getInventory();
- if (clickedInventory != null) {
- VaultViewInfo info = PlayerVaults.getInstance().getInVault().get(player.getUniqueId().toString());
- if (info != null) {
- int num = info.getNumber();
- String inventoryTitle = event.getView().getTitle();
- String title = this.plugin.getVaultTitle(String.valueOf(num));
- if ((inventoryTitle != null && inventoryTitle.equalsIgnoreCase(title)) && event.getNewItems() != null) {
- if (!player.hasPermission(Permission.BYPASS_BLOCKED_ITEMS)) {
- for (ItemStack item : event.getNewItems().values()) {
- if (this.isBlocked(player, item, info)) {
- event.setCancelled(true);
- return;
- }
- }
- }
+ if (!player.hasPermission(Permission.BYPASS_BLOCKED_ITEMS) && event.getNewItems() != null) {
+ for (ItemStack item : event.getNewItems().values()) {
+ if (this.isBlocked(player, item, info)) {
+ event.setCancelled(true);
+ return;
}
}
}
diff --git a/src/main/java/com/drtshock/playervaults/vaultmanagement/CardboardBoxSerialization.java b/src/main/java/com/drtshock/playervaults/vaultmanagement/CardboardBoxSerialization.java
index b6db5ca..c11705b 100644
--- a/src/main/java/com/drtshock/playervaults/vaultmanagement/CardboardBoxSerialization.java
+++ b/src/main/java/com/drtshock/playervaults/vaultmanagement/CardboardBoxSerialization.java
@@ -7,11 +7,7 @@
import org.bukkit.inventory.ItemStack;
import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
+import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
diff --git a/src/main/java/com/drtshock/playervaults/vaultmanagement/VaultManager.java b/src/main/java/com/drtshock/playervaults/vaultmanagement/VaultManager.java
index 742ac8c..21337d7 100644
--- a/src/main/java/com/drtshock/playervaults/vaultmanagement/VaultManager.java
+++ b/src/main/java/com/drtshock/playervaults/vaultmanagement/VaultManager.java
@@ -36,6 +36,8 @@
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import java.util.logging.Level;
public class VaultManager {
@@ -46,6 +48,12 @@ public class VaultManager {
private final Map cachedVaultFiles = new ConcurrentHashMap<>();
private final PlayerVaults plugin;
+ // Variables for async saving
+ private final ExecutorService saveExecutor = Executors.newFixedThreadPool(2);
+ private final Map playerLocks = new ConcurrentHashMap<>();
+ // Key is ":" (e.g. "Steve:1")
+ private final Map lastSaveTime = new ConcurrentHashMap<>();
+
public VaultManager(PlayerVaults plugin) {
this.plugin = plugin;
instance = this;
@@ -60,6 +68,13 @@ public static VaultManager getInstance() {
return instance;
}
+ /**
+ * Per-player-vault lock key: ":".
+ */
+ private static String lockKey(String target, int number) {
+ return target + ":" + number;
+ }
+
/**
* Saves the inventory to the specified player and vault number.
*
@@ -68,11 +83,40 @@ public static VaultManager getInstance() {
* @param number The vault number.
*/
public void saveVault(Inventory inventory, String target, int number) {
+ String key = lockKey(target, number);
+ Long lastSave = lastSaveTime.get(key);
+
+ // Don't allow saves to fast, this prevents duping
+ if (lastSave != null && System.currentTimeMillis() - lastSave < 500) {
+ PlayerVaults.getInstance().getLogger().warning(
+ "Save throttled for " + key + " — possible dupe attempt.");
+ return;
+ }
+
+ ItemStack[] contents = inventory.getContents();
+ for (int i = 0; i < contents.length; i++) {
+ if (contents[i] == null) continue;
+ int amount = contents[i].getAmount();
+ int max = contents[i].getMaxStackSize();
+ if (amount < 1 || amount > max) {
+ contents[i] = contents[i].clone();
+ contents[i].setAmount(Math.max(1, Math.min(amount, max)));
+ }
+ }
+
+ lastSaveTime.put(key, System.currentTimeMillis());
+
+ // Snapshot into a dedicated inventory
+ Inventory snapshot = Bukkit.createInventory(null, inventory.getSize());
+ snapshot.setContents(contents);
+
YamlConfiguration yaml = getPlayerVaultFile(target, true);
- int size = VaultOperations.getMaxVaultSize(target);
- String serialized = CardboardBoxSerialization.toStorage(inventory, target);
+ String serialized = CardboardBoxSerialization.toStorage(snapshot, target);
+
yaml.set(String.format(VAULTKEY, number), serialized);
- saveFileSync(target, yaml);
+ yaml.set("vault_version_" + number, System.currentTimeMillis());
+
+ saveFileAsync(target, yaml);
}
/**
@@ -355,23 +399,51 @@ public YamlConfiguration loadPlayerVaultFile(String uniqueId, boolean createIfNo
return YamlConfiguration.loadConfiguration(file);
}
- public void saveFileSync(final String holder, final YamlConfiguration yaml) {
- if (cachedVaultFiles.containsKey(holder)) {
- cachedVaultFiles.put(holder, yaml);
- }
+ public void saveFileAsync(final String holder, final YamlConfiguration yaml) {
+ Object lock = playerLocks.computeIfAbsent(holder, k -> new Object());
- final boolean backups = PlayerVaults.getInstance().isBackupsEnabled();
- final File backupsFolder = PlayerVaults.getInstance().getBackupsFolder();
- final File file = new File(directory, holder + ".yml");
- if (file.exists() && backups) {
- file.renameTo(new File(backupsFolder, holder + ".yml"));
- }
- try {
- yaml.save(file);
- } catch (IOException e) {
- PlayerVaults.getInstance().addException(new IllegalStateException("Failed to save vault file for: " + holder, e));
- PlayerVaults.getInstance().getLogger().log(Level.SEVERE, "Failed to save vault file for: " + holder, e);
- }
- PlayerVaults.debug("Saved vault for " + holder);
+ saveExecutor.execute(() -> {
+ synchronized (lock) {
+ File tempFile = new File(directory, holder + ".yml.tmp");
+ File file = new File(directory, holder + ".yml");
+
+ try {
+ yaml.save(tempFile);
+
+ if (tempFile.length() == 0) throw new IOException("Temp file is empty — aborting save for " + holder);
+
+ final boolean backups = PlayerVaults.getInstance().isBackupsEnabled();
+ final File backupsFolder = PlayerVaults.getInstance().getBackupsFolder();
+
+ if (file.exists() && backups) {
+ File backup = new File(backupsFolder, holder + ".yml");
+ if (backup.exists()) backup.delete();
+ file.renameTo(backup);
+ }
+
+ if (!tempFile.renameTo(file)) {
+ try { Thread.sleep(20); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); }
+ if (!tempFile.renameTo(file))
+ throw new IOException("Failed to rename temp file for " + holder + " after retry");
+ }
+
+ YamlConfiguration verify = YamlConfiguration.loadConfiguration(file);
+ boolean hasVaultData = verify.getKeys(false).stream()
+ .anyMatch(k -> k.startsWith("vault"));
+ if (!hasVaultData) throw new IllegalStateException("Vault data missing after save for " + holder);
+
+ PlayerVaults.debug("Saved vault for " + holder);
+
+ } catch (IOException | IllegalStateException e) {
+ PlayerVaults.getInstance().addException(
+ new IllegalStateException("Failed to save vault file for: " + holder, e));
+ PlayerVaults.getInstance().getLogger().log(Level.SEVERE,
+ "Failed to save vault file for: " + holder, e);
+ } finally {
+ // Delete temp file if been saved
+ if (tempFile.exists()) tempFile.delete();
+ }
+ }
+ });
}
}