[Idea]: Folia support for OpenInv #196
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>openinvparent</artifactId>
|
||||
<groupId>com.lishid</groupId>
|
||||
<version>4.2.3-SNAPSHOT</version>
|
||||
<version>4.3.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>openinvapi</artifactId>
|
||||
|
@@ -22,9 +22,7 @@ import com.lishid.openinv.internal.ISpecialEnderChest;
|
||||
import com.lishid.openinv.internal.ISpecialInventory;
|
||||
import com.lishid.openinv.internal.ISpecialPlayerInventory;
|
||||
import com.lishid.openinv.util.InventoryAccess;
|
||||
import com.lishid.openinv.util.StringMetric;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
@@ -65,6 +63,15 @@ public interface IOpenInv {
|
||||
*/
|
||||
boolean disableOfflineAccess();
|
||||
|
||||
/**
|
||||
* Check the configuration value for whether OpenInv uses history for opening commands. If false, OpenInv will use
|
||||
* the previous parameterized search when no parameters are provided.
|
||||
*
|
||||
* @return false unless configured otherwise
|
||||
* @since 4.3.0
|
||||
*/
|
||||
boolean noArgsOpensSelf();
|
||||
|
||||
/**
|
||||
* Get the active {@link IAnySilentContainer} implementation.
|
||||
*
|
||||
@@ -219,74 +226,7 @@ public interface IOpenInv {
|
||||
* @param name the string to match
|
||||
* @return the user with the closest matching name
|
||||
*/
|
||||
default @Nullable OfflinePlayer matchPlayer(@NotNull String name) {
|
||||
|
||||
// Warn if called on the main thread - if we resort to searching offline players, this may take several seconds.
|
||||
if (Bukkit.getServer().isPrimaryThread()) {
|
||||
this.getLogger().warning("Call to OpenInv#matchPlayer made on the main thread!");
|
||||
this.getLogger().warning("This can cause the server to hang, potentially severely.");
|
||||
this.getLogger().log(Level.WARNING, "Current stack trace", new Throwable("Current stack trace"));
|
||||
}
|
||||
|
||||
OfflinePlayer player;
|
||||
|
||||
try {
|
||||
UUID uuid = UUID.fromString(name);
|
||||
player = Bukkit.getOfflinePlayer(uuid);
|
||||
// Ensure player is an existing player.
|
||||
if (player.hasPlayedBefore() || player.isOnline()) {
|
||||
return player;
|
||||
}
|
||||
// Return null otherwise.
|
||||
return null;
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
// Not a UUID
|
||||
}
|
||||
|
||||
// Exact online match first.
|
||||
player = Bukkit.getServer().getPlayerExact(name);
|
||||
|
||||
if (player != null) {
|
||||
return player;
|
||||
}
|
||||
|
||||
// Exact offline match second - ensure offline access works when matchable users are online.
|
||||
player = Bukkit.getServer().getOfflinePlayer(name);
|
||||
|
||||
if (player.hasPlayedBefore()) {
|
||||
return player;
|
||||
}
|
||||
|
||||
// Inexact online match.
|
||||
player = Bukkit.getServer().getPlayer(name);
|
||||
|
||||
if (player != null) {
|
||||
return player;
|
||||
}
|
||||
|
||||
// Finally, inexact offline match.
|
||||
float bestMatch = 0;
|
||||
for (OfflinePlayer offline : Bukkit.getServer().getOfflinePlayers()) {
|
||||
if (offline.getName() == null) {
|
||||
// Loaded by UUID only, name has never been looked up.
|
||||
continue;
|
||||
}
|
||||
|
||||
float currentMatch = StringMetric.compareJaroWinkler(name, offline.getName());
|
||||
|
||||
if (currentMatch == 1.0F) {
|
||||
return offline;
|
||||
}
|
||||
|
||||
if (currentMatch > bestMatch) {
|
||||
bestMatch = currentMatch;
|
||||
player = offline;
|
||||
}
|
||||
}
|
||||
|
||||
// Only null if no players have played ever, otherwise even the worst match will do.
|
||||
return player;
|
||||
}
|
||||
@Nullable OfflinePlayer matchPlayer(@NotNull String name);
|
||||
|
||||
/**
|
||||
* @deprecated OpenInv uses action bar chat for notifications. Whether they show is based on language settings.
|
||||
|
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<groupId>com.lishid</groupId>
|
||||
<artifactId>openinvparent</artifactId>
|
||||
<version>4.2.3-SNAPSHOT</version>
|
||||
<version>4.3.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>openinvassembly</artifactId>
|
||||
|
@@ -23,7 +23,7 @@
|
||||
<artifactId>openinvparent</artifactId>
|
||||
<groupId>com.lishid</groupId>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
<version>4.2.3-SNAPSHOT</version>
|
||||
<version>4.3.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>openinvadapter1_18_R2</artifactId>
|
||||
|
@@ -23,7 +23,7 @@
|
||||
<artifactId>openinvparent</artifactId>
|
||||
<groupId>com.lishid</groupId>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
<version>4.2.3-SNAPSHOT</version>
|
||||
<version>4.3.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>openinvadapter1_19_R1</artifactId>
|
||||
|
@@ -23,7 +23,7 @@
|
||||
<artifactId>openinvparent</artifactId>
|
||||
<groupId>com.lishid</groupId>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
<version>4.2.3-SNAPSHOT</version>
|
||||
<version>4.3.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>openinvadapter1_19_R2</artifactId>
|
||||
|
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>openinvparent</artifactId>
|
||||
<groupId>com.lishid</groupId>
|
||||
<version>4.2.3-SNAPSHOT</version>
|
||||
<version>4.3.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>openinvplugincore</artifactId>
|
||||
|
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.lishid.openinv;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.lishid.openinv.commands.ContainerSettingCommand;
|
||||
import com.lishid.openinv.commands.OpenInvCommand;
|
||||
import com.lishid.openinv.commands.SearchContainerCommand;
|
||||
@@ -28,7 +30,9 @@ import com.lishid.openinv.internal.ISpecialPlayerInventory;
|
||||
import com.lishid.openinv.util.ConfigUpdater;
|
||||
import com.lishid.openinv.util.LanguageManager;
|
||||
import com.lishid.openinv.util.Permissions;
|
||||
import com.lishid.openinv.util.StringMetric;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
@@ -37,6 +41,7 @@ import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Stream;
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
@@ -52,6 +57,7 @@ import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.profile.PlayerProfile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -62,6 +68,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
*/
|
||||
public class OpenInv extends JavaPlugin implements IOpenInv {
|
||||
|
||||
private final Cache<String, PlayerProfile> offlineLookUpCache = CacheBuilder.newBuilder().maximumSize(10).build();
|
||||
private final Map<UUID, ISpecialPlayerInventory> inventories = new ConcurrentHashMap<>();
|
||||
private final Map<UUID, ISpecialEnderChest> enderChests = new ConcurrentHashMap<>();
|
||||
|
||||
@@ -190,6 +197,11 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
|
||||
return this.getConfig().getBoolean("settings.disable-offline-access", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean noArgsOpensSelf() {
|
||||
return this.getConfig().getBoolean("settings.command.open.no-args-opens-self", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull IAnySilentContainer getAnySilentContainer() {
|
||||
return this.accessor.getAnySilentContainer();
|
||||
@@ -311,6 +323,95 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
|
||||
return player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable OfflinePlayer matchPlayer(@NotNull String name) {
|
||||
|
||||
// Warn if called on the main thread - if we resort to searching offline players, this may take several seconds.
|
||||
if (Bukkit.getServer().isPrimaryThread()) {
|
||||
this.getLogger().warning("Call to OpenInv#matchPlayer made on the main thread!");
|
||||
this.getLogger().warning("This can cause the server to hang, potentially severely.");
|
||||
this.getLogger().log(Level.WARNING, "Current stack trace", new Throwable("Current stack trace"));
|
||||
}
|
||||
|
||||
OfflinePlayer player;
|
||||
|
||||
try {
|
||||
UUID uuid = UUID.fromString(name);
|
||||
player = Bukkit.getOfflinePlayer(uuid);
|
||||
// Ensure player is an existing player.
|
||||
if (player.hasPlayedBefore() || player.isOnline()) {
|
||||
return player;
|
||||
}
|
||||
// Return null otherwise.
|
||||
return null;
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
// Not a UUID
|
||||
}
|
||||
|
||||
// Exact online match first.
|
||||
player = Bukkit.getServer().getPlayerExact(name);
|
||||
|
||||
if (player != null) {
|
||||
return player;
|
||||
}
|
||||
|
||||
// Cached offline match.
|
||||
PlayerProfile cachedResult = offlineLookUpCache.getIfPresent(name);
|
||||
if (cachedResult != null && cachedResult.getUniqueId() != null) {
|
||||
player = Bukkit.getOfflinePlayer(cachedResult.getUniqueId());
|
||||
// Ensure player is an existing player.
|
||||
if (player.hasPlayedBefore() || player.isOnline()) {
|
||||
return player;
|
||||
}
|
||||
// Return null otherwise.
|
||||
return null;
|
||||
}
|
||||
|
||||
// Exact offline match second - ensure offline access works when matchable users are online.
|
||||
player = Bukkit.getServer().getOfflinePlayer(name);
|
||||
|
||||
if (player.hasPlayedBefore()) {
|
||||
offlineLookUpCache.put(name, player.getPlayerProfile());
|
||||
return player;
|
||||
}
|
||||
|
||||
// Inexact online match.
|
||||
player = Bukkit.getServer().getPlayer(name);
|
||||
|
||||
if (player != null) {
|
||||
return player;
|
||||
}
|
||||
|
||||
// Finally, inexact offline match.
|
||||
float bestMatch = 0;
|
||||
for (OfflinePlayer offline : Bukkit.getServer().getOfflinePlayers()) {
|
||||
if (offline.getName() == null) {
|
||||
// Loaded by UUID only, name has never been looked up.
|
||||
continue;
|
||||
}
|
||||
|
||||
float currentMatch = StringMetric.compareJaroWinkler(name, offline.getName());
|
||||
|
||||
if (currentMatch == 1.0F) {
|
||||
return offline;
|
||||
}
|
||||
|
||||
if (currentMatch > bestMatch) {
|
||||
bestMatch = currentMatch;
|
||||
player = offline;
|
||||
}
|
||||
}
|
||||
|
||||
if (player != null) {
|
||||
// If a match was found, store it.
|
||||
offlineLookUpCache.put(name, player.getPlayerProfile());
|
||||
return player;
|
||||
}
|
||||
|
||||
// No players have ever joined the server.
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload(@NotNull final OfflinePlayer offline) {
|
||||
setPlayerOffline(offline, OfflineHandler.REMOVE_AND_CLOSE);
|
||||
@@ -492,6 +593,45 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
|
||||
void setPlayerOnline(@NotNull Player player) {
|
||||
setPlayerOnline(inventories, player, player::updateInventory);
|
||||
setPlayerOnline(enderChests, player, null);
|
||||
|
||||
if (player.hasPlayedBefore()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// New player may have a name that already points to someone else in lookup cache.
|
||||
String name = player.getName();
|
||||
this.offlineLookUpCache.invalidate(name);
|
||||
|
||||
// If no offline matches are mapped, don't hit scheduler.
|
||||
if (this.offlineLookUpCache.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// New player may also be a more exact match than one already in the cache.
|
||||
// I.e. new player "lava1" is a better match for "lava" than "lava123"
|
||||
// Player joins are already quite intensive, so this is run on a delay.
|
||||
this.getServer().getScheduler().runTaskLaterAsynchronously(this, () -> {
|
||||
Iterator<Map.Entry<String, PlayerProfile>> iterator = this.offlineLookUpCache.asMap().entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, PlayerProfile> entry = iterator.next();
|
||||
String oldMatch = entry.getValue().getName();
|
||||
|
||||
// Shouldn't be possible - all profiles should be complete.
|
||||
if (oldMatch == null) {
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
String lookup = entry.getKey();
|
||||
float oldMatchScore = StringMetric.compareJaroWinkler(lookup, oldMatch);
|
||||
float newMatchScore = StringMetric.compareJaroWinkler(lookup, name);
|
||||
|
||||
// If new match exceeds old match, delete old match.
|
||||
if (newMatchScore > oldMatchScore) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}, 101L); // Odd delay for pseudo load balancing; Player tasks are usually scheduled with full seconds.
|
||||
}
|
||||
|
||||
private void setPlayerOnline(
|
||||
|
@@ -57,19 +57,23 @@ public class OpenInvCommand implements TabExecutor {
|
||||
return true;
|
||||
}
|
||||
|
||||
// History management
|
||||
String history = (openInv ? this.openInvHistory : this.openEnderHistory).get(player);
|
||||
String noArgValue;
|
||||
if (plugin.noArgsOpensSelf()) {
|
||||
noArgValue = player.getUniqueId().toString();
|
||||
} else {
|
||||
// History management
|
||||
noArgValue = (openInv ? this.openInvHistory : this.openEnderHistory).get(player);
|
||||
|
||||
if (history == null || history.isEmpty()) {
|
||||
history = player.getName();
|
||||
(openInv ? this.openInvHistory : this.openEnderHistory).put(player, history);
|
||||
if (noArgValue == null || noArgValue.isEmpty()) {
|
||||
noArgValue = player.getUniqueId().toString();
|
||||
(openInv ? this.openInvHistory : this.openEnderHistory).put(player, noArgValue);
|
||||
}
|
||||
}
|
||||
|
||||
final String name;
|
||||
|
||||
// Read from history if target is not named
|
||||
if (args.length < 1) {
|
||||
name = history;
|
||||
name = noArgValue;
|
||||
} else {
|
||||
name = args[0];
|
||||
}
|
||||
@@ -185,8 +189,10 @@ public class OpenInvCommand implements TabExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
// Record the target
|
||||
(openinv ? this.openInvHistory : this.openEnderHistory).put(player, target.getUniqueId().toString());
|
||||
if (!plugin.noArgsOpensSelf()) {
|
||||
// Record the target
|
||||
(openinv ? this.openInvHistory : this.openEnderHistory).put(player, target.getUniqueId().toString());
|
||||
}
|
||||
|
||||
// Create the inventory
|
||||
final ISpecialInventory inv;
|
||||
|
@@ -57,6 +57,9 @@ public record ConfigUpdater(OpenInv plugin) {
|
||||
if (version < 5) {
|
||||
updateConfig4To5();
|
||||
}
|
||||
if (version < 6) {
|
||||
updateConfig5To6();
|
||||
}
|
||||
|
||||
plugin.getServer().getScheduler().runTask(plugin, () -> {
|
||||
plugin.saveConfig();
|
||||
@@ -65,6 +68,13 @@ public record ConfigUpdater(OpenInv plugin) {
|
||||
});
|
||||
}
|
||||
|
||||
private void updateConfig5To6() {
|
||||
plugin.getServer().getScheduler().runTask(plugin, () -> {
|
||||
plugin.getConfig().set("settings.command.open.no-args-opens-self", false);
|
||||
plugin.getConfig().set("config-version", 6);
|
||||
});
|
||||
}
|
||||
|
||||
private void updateConfig4To5() {
|
||||
plugin.getServer().getScheduler().runTask(plugin, () -> {
|
||||
plugin.getConfig().set("settings.disable-offline-access", false);
|
||||
|
@@ -1,5 +1,8 @@
|
||||
config-version: 5
|
||||
config-version: 6
|
||||
settings:
|
||||
command:
|
||||
open:
|
||||
no-args-opens-self: false
|
||||
disable-offline-access: false
|
||||
disable-saving: false
|
||||
locale: 'en_us'
|
||||
|
8
pom.xml
8
pom.xml
@@ -21,7 +21,7 @@
|
||||
<artifactId>openinvparent</artifactId>
|
||||
<name>OpenInv</name>
|
||||
<url>http://dev.bukkit.org/bukkit-plugins/openinv/</url>
|
||||
<version>4.2.3-SNAPSHOT</version>
|
||||
<version>4.3.0-SNAPSHOT</version>
|
||||
|
||||
<packaging>pom</packaging>
|
||||
|
||||
@@ -78,19 +78,19 @@
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<scope>provided</scope>
|
||||
<version>1.17.1-R0.1-SNAPSHOT</version>
|
||||
<version>1.18.2-R0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>openinvapi</artifactId>
|
||||
<groupId>com.lishid</groupId>
|
||||
<scope>compile</scope>
|
||||
<version>4.2.3-SNAPSHOT</version>
|
||||
<version>4.3.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>openinvplugincore</artifactId>
|
||||
<groupId>com.lishid</groupId>
|
||||
<scope>compile</scope>
|
||||
<version>4.2.3-SNAPSHOT</version>
|
||||
<version>4.3.0-SNAPSHOT</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.lishid</groupId>
|
||||
|
Reference in New Issue
Block a user