Skip to content

Commit 98bd03b

Browse files
committed
Add donation and update notification and fix some small issues
1 parent 0604248 commit 98bd03b

File tree

12 files changed

+330
-14
lines changed

12 files changed

+330
-14
lines changed

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ dependencies {
5353
// Utils
5454
implementation(libs.serverlib)
5555
implementation(libs.paperlib)
56+
implementation(libs.semver)
5657
// Stats
5758
implementation(libs.bstats)
5859
// Commands

crowdin.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
files:
2+
- source: src/main/resources/bettergopaint.properties
3+
translation: /src/main/resources/bettergopaint_%locale_with_underscore%.properties

src/main/java/net/onelitefeather/bettergopaint/BetterGoPaint.java

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,21 @@
1919
package net.onelitefeather.bettergopaint;
2020

2121
import com.fastasyncworldedit.core.Fawe;
22+
import net.kyori.adventure.key.Key;
23+
import net.kyori.adventure.text.Component;
2224
import net.kyori.adventure.text.minimessage.MiniMessage;
25+
import net.kyori.adventure.translation.GlobalTranslator;
26+
import net.kyori.adventure.translation.TranslationRegistry;
27+
import net.kyori.adventure.util.UTF8ResourceBundleControl;
2328
import net.onelitefeather.bettergopaint.brush.PlayerBrushManager;
2429
import net.onelitefeather.bettergopaint.command.GoPaintCommand;
2530
import net.onelitefeather.bettergopaint.command.ReloadCommand;
2631
import net.onelitefeather.bettergopaint.listeners.ConnectListener;
2732
import net.onelitefeather.bettergopaint.listeners.InteractListener;
2833
import net.onelitefeather.bettergopaint.listeners.InventoryListener;
2934
import net.onelitefeather.bettergopaint.objects.other.Settings;
35+
import net.onelitefeather.bettergopaint.service.UpdateService;
36+
import net.onelitefeather.bettergopaint.translations.PluginTranslationRegistry;
3037
import org.bstats.bukkit.Metrics;
3138
import org.bstats.charts.SimplePie;
3239
import org.bukkit.Bukkit;
@@ -45,21 +52,23 @@
4552

4653
import java.io.File;
4754
import java.io.IOException;
55+
import java.net.URL;
56+
import java.net.URLClassLoader;
4857
import java.nio.file.Files;
4958
import java.nio.file.Path;
59+
import java.util.HashSet;
60+
import java.util.Locale;
5061
import java.util.Objects;
62+
import java.util.ResourceBundle;
5163
import java.util.logging.Level;
5264

5365
public class BetterGoPaint extends JavaPlugin implements Listener {
5466

5567
public static final String PAPER_DOCS = "https://jd.papermc.io/paper/1.20.6/org/bukkit/Material.html#enum-constant-summary";
56-
public static final String USE_PERMISSION = "bettergopaint.use";
57-
public static final String ADMIN_PERMISSION = "bettergopaint.admin";
58-
public static final String RELOAD_PERMISSION = "bettergopaint.command.admin.reload";
59-
public static final String WORLD_BYPASS_PERMISSION = "bettergopaint.world.bypass";
6068

6169
private final PlayerBrushManager brushManager = new PlayerBrushManager();
6270
private final Metrics metrics = new Metrics(this, 18734);
71+
private UpdateService updateService;
6372

6473
@Override
6574
public void onLoad() {
@@ -84,6 +93,30 @@ public void onEnable() {
8493

8594
reloadConfig();
8695

96+
final TranslationRegistry translationRegistry = new PluginTranslationRegistry(TranslationRegistry.create(Key.key("bettergopaint", "translations")));
97+
translationRegistry.defaultLocale(Locale.US);
98+
Path langFolder = getDataFolder().toPath().resolve("lang");
99+
var languages = new HashSet<>(Settings.settings().generic.LANGUAGES);
100+
languages.add("en-US");
101+
if (Files.exists(langFolder)) {
102+
try (var urlClassLoader = new URLClassLoader(new URL[]{langFolder.toUri().toURL()})) {
103+
languages.stream().map(Locale::forLanguageTag).forEach(r -> {
104+
var bundle = ResourceBundle.getBundle("bettergopaint", r, urlClassLoader, UTF8ResourceBundleControl.get());
105+
translationRegistry.registerAll(r, bundle, false);
106+
});
107+
} catch (IOException e) {
108+
throw new RuntimeException(e);
109+
}
110+
} else {
111+
languages.stream().map(Locale::forLanguageTag).forEach(r -> {
112+
var bundle = ResourceBundle.getBundle("bettergopaint", r, UTF8ResourceBundleControl.get());
113+
translationRegistry.registerAll(r, bundle, false);
114+
});
115+
}
116+
GlobalTranslator.translator().addSource(translationRegistry);
117+
donationInformation();
118+
119+
87120
Material brush = Settings.settings().generic.DEFAULT_BRUSH;
88121
if (!brush.isItem()) {
89122
getComponentLogger().error("{} is not a valid default brush, it has to be an item", brush.name());
@@ -103,6 +136,7 @@ public void onEnable() {
103136
@Override
104137
public void onDisable() {
105138
metrics.shutdown();
139+
this.updateService.shutdown();
106140
}
107141

108142
public void reloadConfig() {
@@ -117,6 +151,13 @@ public void reloadConfig() {
117151

118152
}
119153

154+
private void updateService() {
155+
this.updateService = new UpdateService(this);
156+
this.updateService.run();
157+
this.updateService.notifyConsole(getComponentLogger());
158+
}
159+
160+
120161
@SuppressWarnings("UnstableApiUsage")
121162
private void registerCommands() {
122163
Bukkit.getCommandMap().register("gopaint", getPluginMeta().getName(), new GoPaintCommand(this));
@@ -132,13 +173,17 @@ private void registerListeners() {
132173
PluginManager pm = getServer().getPluginManager();
133174
pm.registerEvents(new InventoryListener(getBrushManager()), this);
134175
pm.registerEvents(new InteractListener(this), this);
135-
pm.registerEvents(new ConnectListener(getBrushManager()), this);
176+
pm.registerEvents(new ConnectListener(getBrushManager(), this), this);
136177
}
137178

138179
private boolean hasOriginalGoPaint() {
139180
return getServer().getPluginManager().getPlugin("goPaint") != this;
140181
}
141182

183+
private void donationInformation() {
184+
getComponentLogger().info(Component.translatable("bettergopaint.notify.donation.console"));
185+
}
186+
142187
private @Nullable AnnotationParser<CommandSender> enableCommandSystem() {
143188
try {
144189
LegacyPaperCommandManager<CommandSender> commandManager = LegacyPaperCommandManager.createNative(
@@ -161,4 +206,8 @@ private boolean hasOriginalGoPaint() {
161206
return brushManager;
162207
}
163208

209+
public UpdateService getUpdateService() {
210+
return updateService;
211+
}
212+
164213
}

src/main/java/net/onelitefeather/bettergopaint/command/GoPaintCommand.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import net.onelitefeather.bettergopaint.BetterGoPaint;
2222
import net.onelitefeather.bettergopaint.objects.other.Settings;
2323
import net.onelitefeather.bettergopaint.brush.PlayerBrush;
24+
import net.onelitefeather.bettergopaint.utils.Constants;
2425
import org.bukkit.command.Command;
2526
import org.bukkit.command.CommandSender;
2627
import org.bukkit.command.PluginIdentifiableCommand;
@@ -50,12 +51,12 @@ public boolean execute(
5051
}
5152
PlayerBrush pb = plugin.getBrushManager().getBrush(p);
5253
String prefix = Settings.settings().generic.PREFIX;
53-
if (!p.hasPermission(BetterGoPaint.USE_PERMISSION)) {
54+
if (!p.hasPermission(Constants.USE_PERMISSION)) {
5455
p.sendRichMessage(prefix + "<red>You are lacking the permission bettergopaint.use");
5556
return true;
5657
}
5758
if (args.length == 0) {
58-
if (p.hasPermission(BetterGoPaint.ADMIN_PERMISSION)) {
59+
if (p.hasPermission(Constants.ADMIN_PERMISSION)) {
5960
p.sendRichMessage(prefix + "<red>/gp size<gray>|<red>toggle<gray>|<red>info<gray>|<red>reload");
6061
return true;
6162
}
@@ -75,7 +76,7 @@ public boolean execute(
7576
}
7677
return true;
7778
} else if ((args[0].equalsIgnoreCase("reload") || args[0].equalsIgnoreCase("r")) && p.hasPermission(
78-
BetterGoPaint.ADMIN_PERMISSION)) {
79+
Constants.ADMIN_PERMISSION)) {
7980
plugin.reloadConfig();
8081
p.sendRichMessage(prefix + "<green>Reloaded");
8182
return true;
@@ -84,7 +85,7 @@ public boolean execute(
8485
p.sendRichMessage(prefix + "<aqua>Links: <gold><click:open_url:https://twitter.com/themeinerlp'><u>Twitter</u></click>");
8586
return true;
8687
}
87-
if (p.hasPermission(BetterGoPaint.ADMIN_PERMISSION)) {
88+
if (p.hasPermission(Constants.ADMIN_PERMISSION)) {
8889
p.sendRichMessage(prefix + "<red>/gp size<gray>|<red>toggle<gray>|<red>info<gray>|<red>reload");
8990
return true;
9091
}
@@ -102,7 +103,7 @@ public boolean execute(
102103
return true;
103104
}
104105
}
105-
if (p.hasPermission(BetterGoPaint.ADMIN_PERMISSION)) {
106+
if (p.hasPermission(Constants.ADMIN_PERMISSION)) {
106107
p.sendRichMessage(prefix + "<red>/gp size<gray>|<red>toggle<gray>|<red>info<gray>|<red>reload");
107108
return true;
108109
}

src/main/java/net/onelitefeather/bettergopaint/command/ReloadCommand.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package net.onelitefeather.bettergopaint.command;
2020

2121
import net.onelitefeather.bettergopaint.BetterGoPaint;
22+
import net.onelitefeather.bettergopaint.utils.Constants;
2223
import org.bukkit.entity.Player;
2324
import org.incendo.cloud.annotations.Command;
2425
import org.incendo.cloud.annotations.Permission;
@@ -32,7 +33,7 @@ public ReloadCommand(final BetterGoPaint betterGoPaint) {
3233
}
3334

3435
@Command("bgp|gp reload")
35-
@Permission(BetterGoPaint.RELOAD_PERMISSION)
36+
@Permission(Constants.RELOAD_PERMISSION)
3637
public void onReload(Player player) {
3738
betterGoPaint.reloadConfig();
3839
}

src/main/java/net/onelitefeather/bettergopaint/listeners/ConnectListener.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,43 @@
1818
*/
1919
package net.onelitefeather.bettergopaint.listeners;
2020

21+
import net.kyori.adventure.text.Component;
22+
import net.kyori.adventure.text.minimessage.MiniMessage;
23+
import net.onelitefeather.bettergopaint.BetterGoPaint;
2124
import net.onelitefeather.bettergopaint.brush.PlayerBrushManager;
25+
import net.onelitefeather.bettergopaint.objects.other.Settings;
26+
import net.onelitefeather.bettergopaint.utils.Constants;
2227
import org.bukkit.event.EventHandler;
2328
import org.bukkit.event.EventPriority;
2429
import org.bukkit.event.Listener;
30+
import org.bukkit.event.player.PlayerJoinEvent;
2531
import org.bukkit.event.player.PlayerQuitEvent;
2632
import org.jetbrains.annotations.NotNull;
2733

2834
public class ConnectListener implements Listener {
2935

3036
private final PlayerBrushManager brushManager;
37+
private final BetterGoPaint betterGoPaint;
3138

32-
public ConnectListener(@NotNull PlayerBrushManager brushManager) {
39+
public ConnectListener(@NotNull PlayerBrushManager brushManager, final BetterGoPaint paint) {
3340
this.brushManager = brushManager;
41+
this.betterGoPaint = paint;
3442
}
3543

3644
@EventHandler(priority = EventPriority.LOWEST)
3745
public void onQuit(@NotNull PlayerQuitEvent event) {
3846
brushManager.removeBrush(event.getPlayer());
3947
}
48+
49+
@EventHandler(priority = EventPriority.LOWEST)
50+
public void onJoin(@NotNull PlayerJoinEvent event) {
51+
var player = event.getPlayer();
52+
if (player.isOp() || (player.hasPermission(Constants.ADMIN_PERMISSION) && !player.hasPermission(Constants.DISABLE_DONATION_NOTIFY))) {
53+
player.sendMessage(Component.translatable("bettergopaint.notify.donation.player").arguments(MiniMessage.miniMessage()
54+
.deserialize(Settings.settings().generic.PREFIX)));
55+
}
56+
if (player.isOp() || player.hasPermission(Constants.PERMISSION_NOTIFY_UPDATE)) {
57+
this.betterGoPaint.getUpdateService().notifyPlayer(player);
58+
}
59+
}
4060
}

src/main/java/net/onelitefeather/bettergopaint/listeners/InteractListener.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import net.onelitefeather.bettergopaint.brush.PlayerBrush;
2727
import net.onelitefeather.bettergopaint.objects.brush.Brush;
2828
import net.onelitefeather.bettergopaint.objects.other.Settings;
29+
import net.onelitefeather.bettergopaint.utils.Constants;
2930
import org.bukkit.FluidCollisionMode;
3031
import org.bukkit.Location;
3132
import org.bukkit.block.Block;
@@ -52,7 +53,7 @@ public InteractListener(BetterGoPaint plugin) {
5253
public void onClick(PlayerInteractEvent event) {
5354
Player player = event.getPlayer();
5455

55-
if (!player.hasPermission(BetterGoPaint.USE_PERMISSION)) {
56+
if (!player.hasPermission(Constants.USE_PERMISSION)) {
5657
return;
5758
}
5859

@@ -85,7 +86,7 @@ public void onClick(PlayerInteractEvent event) {
8586
return;
8687
}
8788

88-
final boolean hasNotWorldByePassPermission = !player.hasPermission(BetterGoPaint.WORLD_BYPASS_PERMISSION);
89+
final boolean hasNotWorldByePassPermission = !player.hasPermission(Constants.WORLD_BYPASS_PERMISSION);
8990

9091
if (hasNotWorldByePassPermission && Settings.settings().generic.DISABLED_WORLDS
9192
.contains(location.getWorld().getName())) {

src/main/java/net/onelitefeather/bettergopaint/objects/other/Settings.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ public final class Settings extends Config {
4646
@Comment("This is related to generic settings")
4747
public static class Generic {
4848

49+
@Comment("Supported Languages")
50+
public List<String> LANGUAGES = new ArrayList<>();
51+
4952
@Comment({
5053
"Default brush item",
5154
"Possible values: " + BetterGoPaint.PAPER_DOCS,
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package net.onelitefeather.bettergopaint.service;
2+
3+
import com.github.zafarkhaja.semver.Version;
4+
import net.kyori.adventure.text.Component;
5+
import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
6+
import net.kyori.adventure.text.minimessage.MiniMessage;
7+
import net.onelitefeather.bettergopaint.BetterGoPaint;
8+
import net.onelitefeather.bettergopaint.objects.other.Settings;
9+
import net.onelitefeather.bettergopaint.utils.Constants;
10+
import org.bukkit.Bukkit;
11+
import org.bukkit.entity.Player;
12+
import org.bukkit.scheduler.BukkitTask;
13+
import org.jetbrains.annotations.Nullable;
14+
import org.slf4j.Logger;
15+
import org.slf4j.LoggerFactory;
16+
17+
import java.io.IOException;
18+
import java.net.http.HttpClient;
19+
import java.net.http.HttpResponse;
20+
21+
public final class UpdateService implements Runnable {
22+
private final HttpClient hangarClient = HttpClient.newBuilder().build();
23+
private static final Logger LOGGER = LoggerFactory.getLogger(UpdateService.class);
24+
private final Version localVersion;
25+
private Version remoteVersion;
26+
private final BukkitTask scheduler;
27+
private final String DOWNLOAD_URL = "https://hangar.papermc.io/OneLiteFeather/BetterGoPaint/versions/%s";
28+
29+
public UpdateService(BetterGoPaint betterGoPaint) {
30+
this.localVersion = Version.parse(betterGoPaint.getPluginMeta().getVersion());
31+
this.scheduler = Bukkit.getScheduler().runTaskTimerAsynchronously(betterGoPaint, this, 0, 20 * 60 * 60 * 3);
32+
}
33+
34+
35+
@Override
36+
public void run() {
37+
var remoteVersion = getNewerVersion();
38+
if (remoteVersion != null) {
39+
this.remoteVersion = remoteVersion;
40+
for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
41+
if (onlinePlayer.isOp() || onlinePlayer.hasPermission(Constants.PERMISSION_NOTIFY_UPDATE)) {
42+
notifyPlayer(localVersion, remoteVersion, onlinePlayer);
43+
}
44+
}
45+
}
46+
}
47+
48+
public void notifyConsole(ComponentLogger logger) {
49+
if (this.remoteVersion != null && this.remoteVersion.isHigherThan(this.localVersion)) {
50+
logger.warn(Component.translatable("bettergopaint.notify.update.console")
51+
.arguments(Component.text(localVersion.toString()),
52+
Component.text(remoteVersion.toString()),
53+
Component.text(DOWNLOAD_URL.formatted(remoteVersion.toString()))
54+
));
55+
}
56+
}
57+
58+
59+
public void notifyPlayer(Player player) {
60+
if (this.remoteVersion != null && this.remoteVersion.isHigherThan(this.localVersion)) {
61+
notifyPlayer(this.localVersion, this.remoteVersion, player);
62+
}
63+
}
64+
65+
66+
private void notifyPlayer(Version localVersion, Version remoteVersion, Player player) {
67+
player.sendMessage(Component.translatable("bettergopaint.notify.update.player")
68+
.arguments(
69+
MiniMessage.miniMessage().deserialize(Settings.settings().generic.PREFIX),
70+
Component.text(localVersion.toString()),
71+
Component.text(remoteVersion.toString())
72+
));
73+
}
74+
75+
76+
@Nullable
77+
private Version getNewerVersion() {
78+
try {
79+
HttpResponse<String> httpResponse = hangarClient.send(Constants.LATEST_RELEASE_VERSION_REQUEST, HttpResponse.BodyHandlers.ofString());
80+
Version remoteVersion = Version.parse(httpResponse.body());
81+
if (remoteVersion.isHigherThan(this.localVersion)) {
82+
return remoteVersion;
83+
}
84+
} catch (IOException | InterruptedException e) {
85+
LOGGER.error("Something went wrong to check updates", e);
86+
}
87+
return null;
88+
}
89+
90+
public void shutdown() {
91+
this.hangarClient.shutdownNow();
92+
this.scheduler.cancel();
93+
}
94+
}

0 commit comments

Comments
 (0)