Skip to content

Commit 6a22432

Browse files
committed
Add update check feature
1 parent 28cdf01 commit 6a22432

13 files changed

+185
-2
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ The `config.yml` file includes the following settings, but not all items need to
130130
- When updating the plugin, a warning will be displayed if this value does not match the plugin version.
131131
- A `config.new.yml` file will be generated, and manual migration of settings using a merge tool is required.
132132
- After migration, please change this value to the new version.
133+
- `checkUpdate`: Set whether to check for plugin updates. The default is `true`.
133134
- `language`: Set the language to be used. The default is English (`en`).
134135
- Refer to the comments in the [config file](./src/main/resources/config.yml) for supported languages.
135136
- `startTimeout`: After starting a server with this plugin, it will stop the server if there are no players for a certain period. The unit is seconds.

README_ja.md

+1
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ https://github.com/Kamesuta/BungeePteroPower/assets/16362824/019fdfc5-f0fc-4532-
130130
- プラグイン更新時、この値とプラグインのバージョンが一致しない場合、警告が表示されます。
131131
- `config.new.yml` が生成されるためマージツールなどを用いて設定を手動で移行する必要があります。
132132
- 移行後は、この値を新しいバージョンに変更してください。
133+
- `checkUpdate`: プラグインの更新を確認するかどうかを設定します。デフォルトは `true` です。
133134
- `language`: 使用する言語を設定します。デフォルトは英語(`en`)です。
134135
- 対応している言語は[コンフィグ内のコメント](./src/main/resources/config.yml)を参照してください。
135136
- `startTimeout`: このプラグインでサーバーを起動した後、一定時間プレイヤーがいない場合にサーバーを停止します。単位は秒です。

pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.kamesuta</groupId>
88
<artifactId>BungeePteroPower</artifactId>
9-
<version>1.5-SNAPSHOT</version>
9+
<version>1.6-SNAPSHOT</version>
1010
<packaging>jar</packaging>
1111

1212
<name>BungeePteroPower</name>

src/main/java/com/kamesuta/bungeepteropower/BungeePteroPower.java

+21
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.util.Map;
1010
import java.util.Objects;
1111
import java.util.concurrent.ConcurrentHashMap;
12+
import java.util.logging.Level;
1213
import java.util.logging.Logger;
1314

1415
/**
@@ -22,6 +23,10 @@ public final class BungeePteroPower extends Plugin implements BungeePteroPowerAP
2223
* Plugin Configurations
2324
*/
2425
public Config config;
26+
/**
27+
* Version checker
28+
*/
29+
public UpdateChecker updateChecker;
2530
/**
2631
* Fallback Translations
2732
*/
@@ -67,6 +72,22 @@ public void onEnable() {
6772
// Check config
6873
config.validateConfig(getProxy().getConsole());
6974

75+
// Check for updates
76+
String runningVersion = plugin.getDescription().getVersion().replace("-SNAPSHOT", "");
77+
updateChecker = new UpdateChecker(runningVersion);
78+
if (config.checkUpdate) {
79+
updateChecker.checkForUpdates().thenRun(() -> {
80+
// Log the result when starting the plugin
81+
if (updateChecker.isUpdateAvailable()) {
82+
logger.info("An update is available: v" + updateChecker.getRunningVersion() + " -> v" + updateChecker.getNewVersion());
83+
logger.info("You can download BungeePteroPower v" + updateChecker.getNewVersion() + " from " + updateChecker.getDownloadLink());
84+
}
85+
}).exceptionally(e -> {
86+
logger.log(Level.WARNING, "Update check failed", e);
87+
return null;
88+
});
89+
}
90+
7091
// Create DelayManager
7192
delay = new DelayManager();
7293

src/main/java/com/kamesuta/bungeepteropower/Config.java

+5
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ public class Config {
3535
* Config version
3636
*/
3737
public final int configVersion;
38+
/**
39+
* Whether to check for updates
40+
*/
41+
public final boolean checkUpdate;
3842
/**
3943
* Language
4044
*/
@@ -97,6 +101,7 @@ public Config() {
97101
try {
98102
// Basic settings
99103
this.configVersion = configuration.getInt("version", 0);
104+
this.checkUpdate = configuration.getBoolean("checkUpdate", true);
100105
this.language = configuration.getString("language");
101106
this.startTimeout = configuration.getInt("startTimeout");
102107
this.powerControllerType = configuration.getString("powerControllerType");

src/main/java/com/kamesuta/bungeepteropower/PlayerListener.java

+13-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,19 @@ public void onPlayerLogin(PostLoginEvent event) {
3636
player.hasPermission("ptero.start." + server.getName());
3737
player.hasPermission("ptero.stop." + server.getName());
3838
}
39-
player.hasPermission("ptero.reload");
39+
40+
// If the player has the permission to reload the config, notice update if available
41+
if (player.hasPermission("ptero.reload")) {
42+
// Show update message
43+
if (plugin.updateChecker.isUpdateAvailable()) {
44+
player.sendMessage(new ComponentBuilder()
45+
.append(plugin.messages.info("update_available", plugin.updateChecker.getRunningVersion(), plugin.updateChecker.getNewVersion()))
46+
.event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(plugin.messages.getMessage("update_available_tooltip", plugin.updateChecker.getRunningVersion(), plugin.updateChecker.getNewVersion()))))
47+
.event(new ClickEvent(ClickEvent.Action.OPEN_URL, plugin.updateChecker.getDownloadLink()))
48+
.create()
49+
);
50+
}
51+
}
4052
}
4153

4254
@EventHandler
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package com.kamesuta.bungeepteropower;
2+
3+
import javax.annotation.Nullable;
4+
import java.net.URI;
5+
import java.net.http.HttpClient;
6+
import java.net.http.HttpRequest;
7+
import java.net.http.HttpResponse;
8+
import java.util.Arrays;
9+
import java.util.Comparator;
10+
import java.util.List;
11+
import java.util.Objects;
12+
import java.util.concurrent.CompletableFuture;
13+
import java.util.stream.Collectors;
14+
15+
/**
16+
* Checks for updates via SpigotMC API
17+
*/
18+
public class UpdateChecker {
19+
/**
20+
* The resource ID of this plugin on SpigotMC
21+
*/
22+
private static final int ResourceId = 114883;
23+
/**
24+
* The current version
25+
*/
26+
private final String runningVersion;
27+
/**
28+
* The new version
29+
*/
30+
private String newVersion;
31+
32+
/**
33+
* Create a new update checker
34+
*
35+
* @param runningVersion The current version
36+
*/
37+
public UpdateChecker(String runningVersion) {
38+
this.runningVersion = runningVersion;
39+
}
40+
41+
/**
42+
* Check for updates
43+
*
44+
* @return A future that completes when the update check is finished
45+
*/
46+
public CompletableFuture<Void> checkForUpdates() {
47+
// Check for updates via SpigotMC API
48+
HttpClient client = HttpClient.newHttpClient();
49+
// Create a request
50+
HttpRequest request = HttpRequest.newBuilder()
51+
.uri(URI.create("https://api.spigotmc.org/legacy/update.php?resource=" + ResourceId))
52+
.build();
53+
54+
// Execute request and register a callback
55+
return client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
56+
.thenApply(HttpResponse::body)
57+
.thenAccept(version -> {
58+
newVersion = version;
59+
});
60+
}
61+
62+
/**
63+
* Returns whether an update is available
64+
*
65+
* @return true if an update is available
66+
*/
67+
public boolean isUpdateAvailable() {
68+
if (newVersion == null) {
69+
// If the update check has not been completed, assume there is no update
70+
return false;
71+
}
72+
// Compare the versions
73+
return compareVersions(runningVersion, newVersion);
74+
}
75+
76+
/**
77+
* Get download link
78+
*
79+
* @return the download link of the new version
80+
*/
81+
public String getDownloadLink() {
82+
return "https://www.spigotmc.org/resources/" + ResourceId;
83+
}
84+
85+
/**
86+
* Get the current version
87+
*
88+
* @return the current version
89+
*/
90+
public String getRunningVersion() {
91+
return runningVersion;
92+
}
93+
94+
/**
95+
* Get the new version
96+
*
97+
* @return the new version
98+
*/
99+
public @Nullable String getNewVersion() {
100+
return newVersion;
101+
}
102+
103+
/**
104+
* Compares two versions and returns whether the new version is newer than the current version
105+
*
106+
* @param runningVersion The current version
107+
* @param newVersion The new version
108+
* @return true if the new version is newer than the current version
109+
*/
110+
public static boolean compareVersions(String runningVersion, String newVersion) {
111+
// Split the running versions into integers
112+
List<Integer> current = Arrays.stream(runningVersion.split("\\."))
113+
.map(Integer::valueOf)
114+
.collect(Collectors.toList());
115+
// Split the new versions into integers
116+
List<Integer> latest = Arrays.stream(newVersion.split("\\."))
117+
.map(Integer::valueOf)
118+
.collect(Collectors.toList());
119+
// Compare the versions
120+
int comparison = Objects.compare(current, latest, Comparator.<List<Integer>>comparingInt(List::size).thenComparing(List::hashCode));
121+
return comparison < 0;
122+
}
123+
}

src/main/resources/config.yml

+5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
# Do not edit this value until the "/ptero check" asks you to do so.
88
version: 1
99

10+
# Check for updates
11+
# If true, the plugin will check for updates on startup.
12+
# If a new version is available, a message will be sent to the console and to players with the permission "ptero.reload".
13+
checkUpdate: true
14+
1015
# Language
1116
# Supported languages: en, ja, fr, ro
1217
# You can add your own language file in the plugins/BungeePteroPower directory.

src/main/resources/messages_en.yml

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
prefix: "[Ptero] "
22

3+
update_available: "An update is available: BungeePteroPower v%s → v%s"
4+
update_available_tooltip: "Click to download v%2$s!"
5+
36
join_autostart_title: "Starting server..."
47
join_autostart_subtitle: "Please wait a moment and try reconnecting."
58
join_start: "The server %s is suspended to reduce server resources, but it can be started by clicking the button below."

src/main/resources/messages_fr.yml

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
prefix: "[Ptero] "
22

3+
update_available: "Mise à jour disponible: BungeePteroPower v%s → v%s"
4+
update_available_tooltip: "Cliquez pour télécharger v%2$s!"
5+
36
join_autostart_title: "Démarrage du serveur..."
47
join_autostart_subtitle: "Veuillez patienter un moment et essayer de vous reconnecter."
58
join_start: "Le serveur %s est suspendu pour réduire les ressources du serveur, mais il peut être démarré en cliquant sur le bouton ci-dessous."

src/main/resources/messages_ja.yml

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
prefix: "[Ptero] "
22

3+
update_available: "アップデートが利用可能です: BungeePteroPower v%s → v%s"
4+
update_available_tooltip: "クリックして v%2$s をダウンロード!"
5+
36
join_autostart_title: "サーバーを起動中..."
47
join_autostart_subtitle: "しばらく待ってから再接続してください。"
58
join_start: "サーバー「%s」はサーバーリソースを節約するために休止中ですが、下のボタンをクリックすると起動できます。"

src/main/resources/messages_ro.yml

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
prefix: "[Ptero] "
22

3+
update_available: "Actualizare disponibilă: BungeePteroPower v%s → v%s"
4+
update_available_tooltip: "Click pentru a descărca v%2$s!"
5+
36
join_autostart_title: "Se pornește serverul..."
47
join_autostart_subtitle: "Vă rugăm să așteptați un moment și să încercați să vă reconectați."
58
join_start: "Serverul %s este suspendat pentru a reduce resursele, dar poate fi pornit făcând clic pe butonul de mai jos."

src/main/resources/messages_zh-cn.yml

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
prefix: "[Ptero] "
22

3+
update_available: "可用更新: BungeePteroPower v%s → v%s"
4+
update_available_tooltip: "点击下载 v%2$s!"
5+
36
join_autostart_title: "服务器启动中..."
47
join_autostart_subtitle: "请稍候再尝试重新连接。"
58
join_start: "服务器「%s」处于休眠状态以节省资源,但您可以通过点击下方按钮来启动。"

0 commit comments

Comments
 (0)