diff --git a/LICENSE b/LICENSE index 3d90694..818433e 100644 --- a/LICENSE +++ b/LICENSE @@ -671,4 +671,4 @@ into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read -. \ No newline at end of file +. diff --git a/README.md b/README.md index bdab0e8..0482ddd 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ -# Bungeecord-Expansion -Expansion for bungeecord placeholders -[![Build Status](http://ci.extendedclip.com/buildStatus/icon?job=Bungeecord-Expansion)](http://ci.extendedclip.com/job/Bungeecord-Expansion/) +# BungeeCord-Expansion +Expansion for BungeeCord placeholders +[![Build Status](http://ci.extendedclip.com/buildStatus/icon?job=BungeeCord-Expansion)](http://ci.extendedclip.com/job/BungeeCord-Expansion/) diff --git a/pom.xml b/pom.xml index d820ae1..5efd6b9 100644 --- a/pom.xml +++ b/pom.xml @@ -1,17 +1,25 @@ - + 4.0.0 com.extendedclip.papi.bungeeexpansion bungee-expansion - 2.2 + 3.0 Expansion-Bungee - PlaceholderAPI expansion for bungeecord placeholders + PlaceholderAPI expansion for BungeeCord placeholders. - 1.8 - 1.8 + 25 + 25 + + UTF-8 + UTF-8 + UTF-8 + + 25 @@ -19,6 +27,7 @@ spigot-repo https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + placeholderapi https://repo.extendedclip.com/content/repositories/placeholderapi/ @@ -29,29 +38,31 @@ org.spigotmc spigot-api - 1.15.2-R0.1-SNAPSHOT + [26.1.2.build,) provided + me.clip placeholderapi - 2.10.6 + 2.12.2 provided + ${project.name}-${project.version} org.apache.maven.plugins maven-jar-plugin - 3.2.0 + 3.5.0 - ${project.name} false false + true @@ -59,4 +70,4 @@ - \ No newline at end of file + diff --git a/src/main/java/com/extendedclip/papi/bungeeexpansion/BungeeExpansion.java b/src/main/java/com/extendedclip/papi/bungeeexpansion/BungeeExpansion.java index e53cb4e..739df98 100644 --- a/src/main/java/com/extendedclip/papi/bungeeexpansion/BungeeExpansion.java +++ b/src/main/java/com/extendedclip/papi/bungeeexpansion/BungeeExpansion.java @@ -2,7 +2,6 @@ import com.google.common.base.Splitter; import com.google.common.collect.Iterables; -import com.google.common.io.ByteArrayDataInput; import com.google.common.io.ByteArrayDataOutput; import com.google.common.io.ByteStreams; import me.clip.placeholderapi.expansion.Configurable; @@ -12,14 +11,18 @@ import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; import org.bukkit.plugin.messaging.PluginMessageListener; -import org.bukkit.scheduler.BukkitTask; +import org.jspecify.annotations.NonNull; import java.io.ByteArrayInputStream; import java.io.DataInputStream; -import java.lang.reflect.Field; +import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import java.util.logging.Level; @@ -33,34 +36,27 @@ public final class BungeeExpansion extends PlaceholderExpansion implements Plugi private static final Splitter SPLITTER = Splitter.on(",").trimResults(); + private final Map counts = new ConcurrentHashMap<>(); + private final AtomicReference> cached = new AtomicReference<>(); - private final Map counts = new HashMap<>(); - private final AtomicReference cached = new AtomicReference<>(); - - private static Field inputField; - - static { - try { - inputField = Class.forName("com.google.common.io.ByteStreams$ByteArrayDataInputStream").getDeclaredField("input"); - inputField.setAccessible(true); - } catch (Exception e) { - e.printStackTrace(); - } - } + private ScheduledExecutorService executor; @Override + @NonNull public String getIdentifier() { return "bungee"; } @Override + @NonNull public String getAuthor() { return "clip"; } @Override + @NonNull public String getVersion() { - return "2.3"; + return "3.0"; } @Override @@ -68,41 +64,38 @@ public Map getDefaults() { return Collections.singletonMap(CONFIG_INTERVAL, 30); } - @Override public String onRequest(final OfflinePlayer player, String identifier) { - final int value; - - switch (identifier.toLowerCase()) { - case "all": - case "total": - value = counts.values().stream().mapToInt(Integer::intValue).sum(); - break; - default: - value = counts.getOrDefault(identifier.toLowerCase(), 0); - break; - } + final int value = switch (identifier.toLowerCase()) { + case "all", "total" -> counts.values().stream().mapToInt(Integer::intValue).sum(); + default -> counts.getOrDefault(identifier.toLowerCase(), 0); + }; return String.valueOf(value); } @Override public void start() { - final BukkitTask task = Bukkit.getScheduler().runTaskTimer(getPlaceholderAPI(), () -> { + if (executor == null) { + executor = Executors.newSingleThreadScheduledExecutor(r -> { + final Thread thread = new Thread(r, "BungeeExpansion-Scheduler"); + thread.setDaemon(true); + return thread; + }); + } + + final ScheduledFuture task = executor.scheduleAtFixedRate(() -> { if (counts.isEmpty()) { sendServersChannelMessage(); - } - else { + } else { counts.keySet().forEach(this::sendPlayersChannelMessage); } + }, 2L, getLong(CONFIG_INTERVAL, 30), TimeUnit.SECONDS); - }, 20L * 2L, 20L * getLong(CONFIG_INTERVAL, 30)); - - - final BukkitTask prev = cached.getAndSet(task); + final ScheduledFuture prev = cached.getAndSet(task); if (prev != null) { - prev.cancel(); + prev.cancel(false); } else { Bukkit.getMessenger().registerOutgoingPluginChannel(getPlaceholderAPI(), MESSAGE_CHANNEL); Bukkit.getMessenger().registerIncomingPluginChannel(getPlaceholderAPI(), MESSAGE_CHANNEL, this); @@ -111,50 +104,55 @@ public void start() { @Override public void stop() { - final BukkitTask prev = cached.getAndSet(null); + final ScheduledFuture prev = cached.getAndSet(null); if (prev == null) { return; } - prev.cancel(); + prev.cancel(false); counts.clear(); + if (executor != null) { + executor.shutdownNow(); + executor = null; + } + Bukkit.getMessenger().unregisterOutgoingPluginChannel(getPlaceholderAPI(), MESSAGE_CHANNEL); Bukkit.getMessenger().unregisterIncomingPluginChannel(getPlaceholderAPI(), MESSAGE_CHANNEL, this); } - @Override - public void onPluginMessageReceived(final String channel, final Player player, final byte[] message) { + public void onPluginMessageReceived(final @NonNull String channel, final @NonNull Player player, final byte @NonNull [] message) { if (!MESSAGE_CHANNEL.equals(channel)) { return; } - //noinspection UnstableApiUsage - final ByteArrayDataInput in = ByteStreams.newDataInput(message); - try { - DataInputStream stream = (DataInputStream) inputField.get(in); + try (DataInputStream in = new DataInputStream(new ByteArrayInputStream(message))) { switch (in.readUTF()) { - case PLAYERS_CHANNEL: - if (stream.available() == 0) return; // how ? - final String server = in.readUTF(); - if (stream.available() == 0) { // how ? x2 - getPlaceholderAPI().getLogger().log(Level.SEVERE, String.format("[%s] Could not get the player count from server %s.", getName(), server)); - counts.put(server.toLowerCase(), 0); - } else counts.put(server.toLowerCase(), in.readInt()); - break; - case SERVERS_CHANNEL: - SPLITTER.split(in.readUTF()).forEach(serverName -> counts.putIfAbsent(serverName.toLowerCase(), 0)); - break; + case PLAYERS_CHANNEL -> { + if (in.available() == 0) { + return; + } + + final String server = in.readUTF(); + if (in.available() == 0) { + getPlaceholderAPI().getLogger().log(Level.SEVERE, String.format("[%s] Could not get the player count from server %s.", getName(), server)); + counts.put(server.toLowerCase(), 0); + } else { + counts.put(server.toLowerCase(), in.readInt()); + } + } + case SERVERS_CHANNEL -> + SPLITTER.split(in.readUTF()).forEach(serverName -> counts.putIfAbsent(serverName.toLowerCase(), 0)); } } catch (Exception e) { - e.printStackTrace(); + getPlaceholderAPI().getLogger().log(Level.SEVERE, String.format("[%s] Failed to handle plugin message on channel %s.", getName(), channel), e); } } - private void sendServersChannelMessage() { - sendMessage(SERVERS_CHANNEL, out -> { }); + sendMessage(SERVERS_CHANNEL, _ -> { + }); } private void sendPlayersChannelMessage(final String serverName) { @@ -162,12 +160,11 @@ private void sendPlayersChannelMessage(final String serverName) { } private void sendMessage(final String channel, final Consumer consumer) { - final Player player = Iterables.getFirst(Bukkit.getOnlinePlayers(), null); + final Player player = Iterables.getFirst(new ArrayList<>(Bukkit.getOnlinePlayers()), null); if (player == null) { return; } - //noinspection UnstableApiUsage final ByteArrayDataOutput out = ByteStreams.newDataOutput(); out.writeUTF(channel); @@ -175,5 +172,4 @@ private void sendMessage(final String channel, final Consumer