From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Mon, 27 May 2019 01:10:06 -0500 Subject: [PATCH] Version Command 2.0 diff --git a/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java b/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java new file mode 100644 index 0000000000000000000000000000000000000000..a736d7bcdc5861a01b66ba36158db1c716339346 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java @@ -0,0 +1,45 @@ +package com.destroystokyo.paper.util; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.jetbrains.annotations.NotNull; + +public interface VersionFetcher { + /** + * Amount of time to cache results for in milliseconds + *

+ * Negative values will never cache. + * + * @return cache time + */ + long getCacheTime(); + + /** + * Gets the version message to cache and show to command senders. + * + *

NOTE: This is run in a new thread separate from that of the command processing thread

+ * + * @param serverVersion the current version of the server (will match {@link Bukkit#getVersion()}) + * @return the message to show when requesting a version + */ + @NotNull + Component getVersionMessage(@NotNull String serverVersion); + + class DummyVersionFetcher implements VersionFetcher { + + @Override + public long getCacheTime() { + return -1; + } + + @NotNull + @Override + public Component getVersionMessage(@NotNull String serverVersion) { + Bukkit.getLogger().warning("Version provider has not been set, cannot check for updates!"); + Bukkit.getLogger().info("Override the default implementation of org.bukkit.UnsafeValues#getVersionFetcher()"); + new Throwable().printStackTrace(); + return Component.text("Unable to check for updates. No version provider set.", NamedTextColor.RED); + } + } +} diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java index c9ecd5b1908e05a1b39dadcded27241672adcddf..355c46f1c1f08072446f3cc92c0d22898933a7fc 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java @@ -94,5 +94,12 @@ public interface UnsafeValues { * @return name */ String getTimingsServerName(); + + /** + * Called once by the version command on first use, then cached. + */ + default com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { + return new com.destroystokyo.paper.util.VersionFetcher.DummyVersionFetcher(); + } // Paper end } diff --git a/src/main/java/org/bukkit/command/defaults/VersionCommand.java b/src/main/java/org/bukkit/command/defaults/VersionCommand.java index 04b4fb6859df0221f8f9f92c5a7ac2dda1073355..b50f614806f4634960d383e8a33f094c2f46935f 100644 --- a/src/main/java/org/bukkit/command/defaults/VersionCommand.java +++ b/src/main/java/org/bukkit/command/defaults/VersionCommand.java @@ -1,5 +1,6 @@ package org.bukkit.command.defaults; +import com.destroystokyo.paper.util.VersionFetcher; // Paper - version supplier import com.google.common.base.Charsets; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -26,6 +27,15 @@ import org.bukkit.util.StringUtil; import org.jetbrains.annotations.NotNull; public class VersionCommand extends BukkitCommand { + private VersionFetcher versionFetcher; + private VersionFetcher getVersionFetcher() { // lazy load because unsafe isn't available at command registration + if (versionFetcher == null) { + versionFetcher = Bukkit.getUnsafe().getVersionFetcher(); + } + + return versionFetcher; + } + public VersionCommand(@NotNull String name) { super(name); @@ -40,7 +50,7 @@ public class VersionCommand extends BukkitCommand { if (!testPermission(sender)) return true; if (args.length == 0) { - sender.sendMessage("This server is running " + Bukkit.getName() + " version " + Bukkit.getVersion() + " (Implementing API version " + Bukkit.getBukkitVersion() + ")"); + //sender.sendMessage("This server is running " + Bukkit.getName() + " version " + Bukkit.getVersion() + " (Implementing API version " + Bukkit.getBukkitVersion() + ")"); // Paper - moved to setVersionMessage sendVersion(sender); } else { StringBuilder name = new StringBuilder(); @@ -146,14 +156,14 @@ public class VersionCommand extends BukkitCommand { private final ReentrantLock versionLock = new ReentrantLock(); private boolean hasVersion = false; - private String versionMessage = null; + private net.kyori.adventure.text.Component versionMessage = null; // Paper private final Set versionWaiters = new HashSet(); private boolean versionTaskStarted = false; private long lastCheck = 0; private void sendVersion(@NotNull CommandSender sender) { if (hasVersion) { - if (System.currentTimeMillis() - lastCheck > 21600000) { + if (System.currentTimeMillis() - lastCheck > getVersionFetcher().getCacheTime()) { // Paper - use version supplier lastCheck = System.currentTimeMillis(); hasVersion = false; } else { @@ -168,7 +178,7 @@ public class VersionCommand extends BukkitCommand { return; } versionWaiters.add(sender); - sender.sendMessage("Checking version, please wait..."); + sender.sendMessage(net.kyori.adventure.text.Component.text("Checking version, please wait...", net.kyori.adventure.text.format.NamedTextColor.WHITE, net.kyori.adventure.text.format.TextDecoration.ITALIC)); // Paper if (!versionTaskStarted) { versionTaskStarted = true; new Thread(new Runnable() { @@ -186,6 +196,13 @@ public class VersionCommand extends BukkitCommand { private void obtainVersion() { String version = Bukkit.getVersion(); + // Paper start + if (version.startsWith("null")) { // running from ide? + setVersionMessage(net.kyori.adventure.text.Component.text("Unknown version, custom build?", net.kyori.adventure.text.format.NamedTextColor.YELLOW)); + return; + } + setVersionMessage(getVersionFetcher().getVersionMessage(version)); + /* if (version == null) version = "Custom"; String[] parts = version.substring(0, version.indexOf(' ')).split("-"); if (parts.length == 4) { @@ -215,11 +232,24 @@ public class VersionCommand extends BukkitCommand { } else { setVersionMessage("Unknown version, custom build?"); } + */ + // Paper end } - private void setVersionMessage(@NotNull String msg) { + // Paper start + private void setVersionMessage(final @NotNull net.kyori.adventure.text.Component msg) { lastCheck = System.currentTimeMillis(); - versionMessage = msg; + final net.kyori.adventure.text.Component message = net.kyori.adventure.text.TextComponent.ofChildren( + net.kyori.adventure.text.Component.text("This server is running " + Bukkit.getName() + " version " + Bukkit.getVersion() + " (Implementing API version " + Bukkit.getBukkitVersion() + ")", net.kyori.adventure.text.format.NamedTextColor.WHITE), + net.kyori.adventure.text.Component.newline(), + msg + ); + this.versionMessage = net.kyori.adventure.text.Component.text() + .append(message) + .hoverEvent(net.kyori.adventure.text.Component.text("Click to copy to clipboard", net.kyori.adventure.text.format.NamedTextColor.WHITE)) + .clickEvent(net.kyori.adventure.text.event.ClickEvent.copyToClipboard(net.kyori.adventure.text.serializer.plain.PlainComponentSerializer.plain().serialize(message))) + .build(); + // Paper end versionLock.lock(); try { hasVersion = true;