diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index c058a07c..b6c05cc8 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -3,7 +3,7 @@ on: push: branches: - master - - dev + - develop jobs: build: # Run on all label events (won't be duplicated) or all push events or on PR syncs not from the same repo diff --git a/build.gradle.kts b/build.gradle.kts index 6efc8bb9..4b6711cb 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,21 +1,20 @@ import io.papermc.hangarpublishplugin.model.Platforms +import kotlin.system.exitProcess import net.minecrell.pluginyml.bukkit.BukkitPluginDescription import net.minecrell.pluginyml.paper.PaperPluginDescription import xyz.jpenilla.runpaper.task.RunServer -import kotlin.system.exitProcess plugins { - id("idea") id("java") - id("java-library") - id("olf.build-logic") - + alias(libs.plugins.shadowJar) + alias(libs.plugins.publishdata) + alias(libs.plugins.paper.run) + alias(libs.plugins.paper.yml) + alias(libs.plugins.hangar) + alias(libs.plugins.modrinth) alias(libs.plugins.spotless) - alias(libs.plugins.minotaur) - alias(libs.plugins.shadow) - alias(libs.plugins.hangar.publish.plugin) - alias(libs.plugins.plugin.yml.paper) - alias(libs.plugins.run.paper) + id("olf.build-logic") + `maven-publish` } if (!File("$rootDir/.git").exists()) { @@ -30,23 +29,18 @@ if (!File("$rootDir/.git").exists()) { allprojects { group = "net.onelitefeather.bettergopaint" - version = property("projectVersion") as String // from gradle.properties + version = "1.1.0" } group = "net.onelitefeather.bettergopaint" val supportedMinecraftVersions = listOf( - "1.20", - "1.20.1", - "1.20.2", - "1.20.3", - "1.20.4", - "1.20.5", - "1.20.6" + "1.21" ) repositories { mavenCentral() maven("https://papermc.io/repo/repository/maven-public/") + maven("https://maven.enginehub.org/repo/") } dependencies { @@ -54,19 +48,26 @@ dependencies { compileOnly(libs.paper) // Fawe / WorldEdit implementation(platform(libs.fawe.bom)) - compileOnlyApi(libs.fawe.bukkit) + compileOnly(libs.fawe.bukkit) // Utils implementation(libs.serverlib) implementation(libs.paperlib) + implementation(libs.semver) // Stats implementation(libs.bstats) // Commands - implementation(libs.cloud.annotations) - implementation(libs.cloud.minecraft.extras) - implementation(libs.cloud.paper) - annotationProcessor(libs.cloud.annotations) + implementation(libs.cloud.command.annotations) + implementation(libs.cloud.command.extras) + implementation(libs.cloud.command.paper) + annotationProcessor(libs.cloud.command.annotations) } +publishData { + useEldoNexusRepos(false) + publishTask("shadowJar") +} + + paper { name = "BetterGoPaint" main = "net.onelitefeather.bettergopaint.BetterGoPaint" @@ -87,6 +88,12 @@ paper { register("bettergopaint.command.admin.reload") { default = BukkitPluginDescription.Permission.Default.OP } + register("bettergopaint.notify.admin.update") { + default = BukkitPluginDescription.Permission.Default.OP + } + register("bettergopaint.notify.disable.donation") { + default = BukkitPluginDescription.Permission.Default.FALSE + } register("bettergopaint.use") { default = BukkitPluginDescription.Permission.Default.OP } @@ -145,7 +152,7 @@ tasks { } val branch = rootProject.branchName() -val baseVersion = project.version as String +val baseVersion = publishData.getVersion(false) val isRelease = !baseVersion.contains('-') val isMainBranch = branch == "master" if (!isRelease || isMainBranch) { // Only publish releases from the main branch @@ -159,7 +166,7 @@ if (!isRelease || isMainBranch) { // Only publish releases from the main branch hangarPublish { publications.register("BetterGoPaint") { version.set(suffixedVersion) - channel.set(if (isRelease) "Release" else if (isMainBranch) "Snapshot" else "Alpha") + channel.set(if (isRelease) "Release" else "Snapshot") changelog.set(changelogContent) apiKey.set(System.getenv("HANGAR_SECRET")) id.set("BetterGoPaint") @@ -175,7 +182,7 @@ if (!isRelease || isMainBranch) { // Only publish releases from the main branch modrinth { token.set(System.getenv("MODRINTH_TOKEN")) projectId.set("qf7sNg9A") - versionType.set(if (isRelease) "release" else if (isMainBranch) "beta" else "alpha") + versionType.set(if (isRelease) "release" else "beta") versionNumber.set(suffixedVersion) versionName.set(suffixedVersion) changelog.set(changelogContent) @@ -186,3 +193,26 @@ if (!isRelease || isMainBranch) { // Only publish releases from the main branch loaders.add("folia") } } + +publishing { + publications.create("maven") { + // Configure our maven publication + publishData.configurePublication(this) + } + + repositories { + // We add EldoNexus as our repository. The used url is defined by the publish data. + maven { + authentication { + credentials(PasswordCredentials::class) { + // Those credentials need to be set under "Settings -> Secrets -> Actions" in your repository + username = System.getenv("ELDO_USERNAME") + password = System.getenv("ELDO_PASSWORD") + } + } + + name = "EldoNexus" + setUrl(publishData.getRepository()) + } + } +} diff --git a/crowdin.yml b/crowdin.yml new file mode 100644 index 00000000..7b735c0f --- /dev/null +++ b/crowdin.yml @@ -0,0 +1,3 @@ +files: + - source: src/main/resources/bettergopaint.properties + translation: /src/main/resources/bettergopaint_%locale_with_underscore%.properties diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml deleted file mode 100644 index a828a13f..00000000 --- a/gradle/libs.versions.toml +++ /dev/null @@ -1,25 +0,0 @@ -[versions] -minecraft = "1.20.6-R0.1-SNAPSHOT" -intellectualsites = "1.27" -bstats = "3.0.2" -cloud-minecraft = "2.0.0-beta.8" -cloud-annotations = "2.0.0-rc.2" - -[libraries] -paper = { group = "io.papermc.paper", name = "paper-api", version.ref = "minecraft" } -fawe-bom = { group = "com.intellectualsites.bom", name = "bom-newest", version.ref = "intellectualsites" } -fawe-bukkit = { group = "com.fastasyncworldedit", name = "FastAsyncWorldEdit-Bukkit" } -serverlib = { group = "dev.notmyfault.serverlib", name = "ServerLib" } -paperlib = { group = "io.papermc", name = "paperlib" } -bstats = { group = "org.bstats", name = "bstats-bukkit", version.ref = "bstats" } -cloud-annotations = { group = "org.incendo", name = "cloud-annotations", version.ref = "cloud-annotations" } -cloud-minecraft-extras = { group = "org.incendo", name = "cloud-minecraft-extras", version.ref = "cloud-minecraft" } -cloud-paper = { group = "org.incendo", name = "cloud-paper", version.ref = "cloud-minecraft" } - -[plugins] -spotless = { id = "com.diffplug.spotless", version = "6.18.0" } -minotaur = { id = "com.modrinth.minotaur", version = "2.+" } -shadow = { id = "io.github.goooler.shadow", version = "8.1.7" } -hangar-publish-plugin = { id = "io.papermc.hangar-publish-plugin", version = "0.1.2" } -plugin-yml-paper = { id = "net.minecrell.plugin-yml.paper", version = "0.6.0" } -run-paper = { id = "xyz.jpenilla.run-paper", version = "2.1.0" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 1427e0e7..9f70ff0f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,2 +1,54 @@ rootProject.name = "BetterGoPaint" includeBuild("build-logic") + +pluginManagement { + repositories { + maven("https://eldonexus.de/repository/maven-public/") + gradlePluginPortal() + } +} + +dependencyResolutionManagement { + versionCatalogs { + create("libs") { + version("publishdata", "1.4.0") + version("modrinth", "2.+") + version("hangar", "0.1.2") + version("paper.yml", "0.6.0") + version("paper.run", "2.3.0") + version("shadowJar", "8.1.1") + version("intellectualsites", "1.51") + + version("paper", "1.21.3-R0.1-SNAPSHOT") + version("bstats", "3.0.2") + + version("cloudcommand", "2.0.0-SNAPSHOT") + + version("adventure", "4.17.0") + version("semver", "0.10.2") + + library("paper", "io.papermc.paper", "paper-api").versionRef("paper") + library("minimessage", "net.kyori", "adventure-text-minimessage").versionRef("adventure") + library("bstats", "org.bstats", "bstats-bukkit").versionRef("bstats") + + library("fawe.bom", "com.intellectualsites.bom", "bom-newest").versionRef("intellectualsites") + library("fawe.bukkit", "com.fastasyncworldedit", "FastAsyncWorldEdit-Bukkit").withoutVersion() + library("serverlib", "dev.notmyfault.serverlib", "ServerLib").withoutVersion() + library("paperlib", "io.papermc", "paperlib").withoutVersion() + + library("cloud.command.paper", "org.incendo", "cloud-paper").versionRef("cloudcommand") + library("cloud.command.annotations", "org.incendo", "cloud-annotations").versionRef("cloudcommand") + library("cloud.command.extras", "org.incendo", "cloud-minecraft-extras").versionRef("cloudcommand") + + library("semver", "com.github.zafarkhaja", "java-semver").versionRef("semver") + + plugin("publishdata","de.chojo.publishdata").versionRef("publishdata") + plugin("modrinth", "com.modrinth.minotaur").versionRef("modrinth") + plugin("hangar", "io.papermc.hangar-publish-plugin").versionRef("hangar") + plugin("paper.yml", "net.minecrell.plugin-yml.paper").versionRef("paper.yml") + plugin("paper.run", "xyz.jpenilla.run-paper").versionRef("paper.run") + plugin("shadowJar", "com.github.johnrengelman.shadow").versionRef("shadowJar") + plugin("spotless", "com.diffplug.spotless").version("6.18.0") + } + } +} diff --git a/src/main/java/net/onelitefeather/bettergopaint/BetterGoPaint.java b/src/main/java/net/onelitefeather/bettergopaint/BetterGoPaint.java index 82ce591f..0a7f5df4 100644 --- a/src/main/java/net/onelitefeather/bettergopaint/BetterGoPaint.java +++ b/src/main/java/net/onelitefeather/bettergopaint/BetterGoPaint.java @@ -19,7 +19,12 @@ package net.onelitefeather.bettergopaint; import com.fastasyncworldedit.core.Fawe; +import net.kyori.adventure.key.Key; +import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.translation.GlobalTranslator; +import net.kyori.adventure.translation.TranslationRegistry; +import net.kyori.adventure.util.UTF8ResourceBundleControl; import net.onelitefeather.bettergopaint.brush.PlayerBrushManager; import net.onelitefeather.bettergopaint.command.GoPaintCommand; import net.onelitefeather.bettergopaint.command.ReloadCommand; @@ -27,6 +32,8 @@ import net.onelitefeather.bettergopaint.listeners.InteractListener; import net.onelitefeather.bettergopaint.listeners.InventoryListener; import net.onelitefeather.bettergopaint.objects.other.Settings; +import net.onelitefeather.bettergopaint.service.UpdateService; +import net.onelitefeather.bettergopaint.translations.PluginTranslationRegistry; import org.bstats.bukkit.Metrics; import org.bstats.charts.SimplePie; import org.bukkit.Bukkit; @@ -44,19 +51,24 @@ import org.jetbrains.annotations.Nullable; import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashSet; +import java.util.Locale; import java.util.Objects; +import java.util.ResourceBundle; import java.util.logging.Level; public class BetterGoPaint extends JavaPlugin implements Listener { public static final String PAPER_DOCS = "https://jd.papermc.io/paper/1.20.6/org/bukkit/Material.html#enum-constant-summary"; - public static final String USE_PERMISSION = "bettergopaint.use"; - public static final String ADMIN_PERMISSION = "bettergopaint.admin"; - public static final String RELOAD_PERMISSION = "bettergopaint.command.admin.reload"; - public static final String WORLD_BYPASS_PERMISSION = "bettergopaint.world.bypass"; private final PlayerBrushManager brushManager = new PlayerBrushManager(); private final Metrics metrics = new Metrics(this, 18734); + private UpdateService updateService; @Override public void onLoad() { @@ -81,6 +93,30 @@ public void onEnable() { reloadConfig(); + final TranslationRegistry translationRegistry = new PluginTranslationRegistry(TranslationRegistry.create(Key.key("bettergopaint", "translations"))); + translationRegistry.defaultLocale(Locale.US); + Path langFolder = getDataFolder().toPath().resolve("lang"); + var languages = new HashSet<>(Settings.settings().generic.LANGUAGES); + languages.add("en-US"); + if (Files.exists(langFolder)) { + try (var urlClassLoader = new URLClassLoader(new URL[]{langFolder.toUri().toURL()})) { + languages.stream().map(Locale::forLanguageTag).forEach(r -> { + var bundle = ResourceBundle.getBundle("bettergopaint", r, urlClassLoader, UTF8ResourceBundleControl.get()); + translationRegistry.registerAll(r, bundle, false); + }); + } catch (IOException e) { + throw new RuntimeException(e); + } + } else { + languages.stream().map(Locale::forLanguageTag).forEach(r -> { + var bundle = ResourceBundle.getBundle("bettergopaint", r, UTF8ResourceBundleControl.get()); + translationRegistry.registerAll(r, bundle, false); + }); + } + GlobalTranslator.translator().addSource(translationRegistry); + donationInformation(); + + Material brush = Settings.settings().generic.DEFAULT_BRUSH; if (!brush.isItem()) { getComponentLogger().error("{} is not a valid default brush, it has to be an item", brush.name()); @@ -95,17 +131,34 @@ public void onEnable() { registerListeners(); registerCommands(); + updateService(); } @Override public void onDisable() { metrics.shutdown(); + this.updateService.shutdown(); } public void reloadConfig() { - Settings.settings().reload(this, new File(getDataFolder(), "config.yml")); + try { + Files.createDirectories(getDataFolder().toPath()); + final Path resolve = getDataFolder().toPath().resolve("config.yml"); + Settings.settings().save(resolve.toFile()); + Settings.settings().load(resolve.toFile()); + } catch (IOException e) { + getLogger().log(Level.SEVERE, "Cannot init config", e); + } + } + private void updateService() { + this.updateService = new UpdateService(this); + this.updateService.run(); + this.updateService.notifyConsole(getComponentLogger()); + } + + @SuppressWarnings("UnstableApiUsage") private void registerCommands() { Bukkit.getCommandMap().register("gopaint", getPluginMeta().getName(), new GoPaintCommand(this)); @@ -121,13 +174,17 @@ private void registerListeners() { PluginManager pm = getServer().getPluginManager(); pm.registerEvents(new InventoryListener(getBrushManager()), this); pm.registerEvents(new InteractListener(this), this); - pm.registerEvents(new ConnectListener(getBrushManager()), this); + pm.registerEvents(new ConnectListener(getBrushManager(), this), this); } private boolean hasOriginalGoPaint() { return getServer().getPluginManager().getPlugin("goPaint") != this; } + private void donationInformation() { + getComponentLogger().info(Component.translatable("bettergopaint.notify.donation.console")); + } + private @Nullable AnnotationParser enableCommandSystem() { try { LegacyPaperCommandManager commandManager = LegacyPaperCommandManager.createNative( @@ -150,4 +207,8 @@ private boolean hasOriginalGoPaint() { return brushManager; } + public UpdateService getUpdateService() { + return updateService; + } + } diff --git a/src/main/java/net/onelitefeather/bettergopaint/command/GoPaintCommand.java b/src/main/java/net/onelitefeather/bettergopaint/command/GoPaintCommand.java index d98156df..6c36c0bc 100644 --- a/src/main/java/net/onelitefeather/bettergopaint/command/GoPaintCommand.java +++ b/src/main/java/net/onelitefeather/bettergopaint/command/GoPaintCommand.java @@ -21,6 +21,7 @@ import net.onelitefeather.bettergopaint.BetterGoPaint; import net.onelitefeather.bettergopaint.objects.other.Settings; import net.onelitefeather.bettergopaint.brush.PlayerBrush; +import net.onelitefeather.bettergopaint.utils.Constants; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.command.PluginIdentifiableCommand; @@ -50,12 +51,12 @@ public boolean execute( } PlayerBrush pb = plugin.getBrushManager().getBrush(p); String prefix = Settings.settings().generic.PREFIX; - if (!p.hasPermission(BetterGoPaint.USE_PERMISSION)) { + if (!p.hasPermission(Constants.USE_PERMISSION)) { p.sendRichMessage(prefix + "You are lacking the permission bettergopaint.use"); return true; } if (args.length == 0) { - if (p.hasPermission(BetterGoPaint.ADMIN_PERMISSION)) { + if (p.hasPermission(Constants.ADMIN_PERMISSION)) { p.sendRichMessage(prefix + "/gp size|toggle|info|reload"); return true; } @@ -75,7 +76,7 @@ public boolean execute( } return true; } else if ((args[0].equalsIgnoreCase("reload") || args[0].equalsIgnoreCase("r")) && p.hasPermission( - BetterGoPaint.ADMIN_PERMISSION)) { + Constants.ADMIN_PERMISSION)) { plugin.reloadConfig(); p.sendRichMessage(prefix + "Reloaded"); return true; @@ -84,7 +85,7 @@ public boolean execute( p.sendRichMessage(prefix + "Links: Twitter"); return true; } - if (p.hasPermission(BetterGoPaint.ADMIN_PERMISSION)) { + if (p.hasPermission(Constants.ADMIN_PERMISSION)) { p.sendRichMessage(prefix + "/gp size|toggle|info|reload"); return true; } @@ -102,7 +103,7 @@ public boolean execute( return true; } } - if (p.hasPermission(BetterGoPaint.ADMIN_PERMISSION)) { + if (p.hasPermission(Constants.ADMIN_PERMISSION)) { p.sendRichMessage(prefix + "/gp size|toggle|info|reload"); return true; } diff --git a/src/main/java/net/onelitefeather/bettergopaint/command/ReloadCommand.java b/src/main/java/net/onelitefeather/bettergopaint/command/ReloadCommand.java index 184cd516..f7769a86 100644 --- a/src/main/java/net/onelitefeather/bettergopaint/command/ReloadCommand.java +++ b/src/main/java/net/onelitefeather/bettergopaint/command/ReloadCommand.java @@ -19,6 +19,7 @@ package net.onelitefeather.bettergopaint.command; import net.onelitefeather.bettergopaint.BetterGoPaint; +import net.onelitefeather.bettergopaint.utils.Constants; import org.bukkit.entity.Player; import org.incendo.cloud.annotations.Command; import org.incendo.cloud.annotations.Permission; @@ -32,7 +33,7 @@ public ReloadCommand(final BetterGoPaint betterGoPaint) { } @Command("bgp|gp reload") - @Permission(BetterGoPaint.RELOAD_PERMISSION) + @Permission(Constants.RELOAD_PERMISSION) public void onReload(Player player) { betterGoPaint.reloadConfig(); } diff --git a/src/main/java/net/onelitefeather/bettergopaint/listeners/ConnectListener.java b/src/main/java/net/onelitefeather/bettergopaint/listeners/ConnectListener.java index 86a8b9cb..81d9049c 100644 --- a/src/main/java/net/onelitefeather/bettergopaint/listeners/ConnectListener.java +++ b/src/main/java/net/onelitefeather/bettergopaint/listeners/ConnectListener.java @@ -18,23 +18,43 @@ */ package net.onelitefeather.bettergopaint.listeners; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.onelitefeather.bettergopaint.BetterGoPaint; import net.onelitefeather.bettergopaint.brush.PlayerBrushManager; +import net.onelitefeather.bettergopaint.objects.other.Settings; +import net.onelitefeather.bettergopaint.utils.Constants; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.jetbrains.annotations.NotNull; public class ConnectListener implements Listener { private final PlayerBrushManager brushManager; + private final BetterGoPaint betterGoPaint; - public ConnectListener(@NotNull PlayerBrushManager brushManager) { + public ConnectListener(@NotNull PlayerBrushManager brushManager, final BetterGoPaint paint) { this.brushManager = brushManager; + this.betterGoPaint = paint; } @EventHandler(priority = EventPriority.LOWEST) public void onQuit(@NotNull PlayerQuitEvent event) { brushManager.removeBrush(event.getPlayer()); } + + @EventHandler(priority = EventPriority.LOWEST) + public void onJoin(@NotNull PlayerJoinEvent event) { + var player = event.getPlayer(); + if (player.isOp() || (player.hasPermission(Constants.ADMIN_PERMISSION) && !player.hasPermission(Constants.DISABLE_DONATION_NOTIFY))) { + player.sendMessage(Component.translatable("bettergopaint.notify.donation.player").arguments(MiniMessage.miniMessage() + .deserialize(Settings.settings().generic.PREFIX))); + } + if (player.isOp() || player.hasPermission(Constants.PERMISSION_NOTIFY_UPDATE)) { + this.betterGoPaint.getUpdateService().notifyPlayer(player); + } + } } diff --git a/src/main/java/net/onelitefeather/bettergopaint/listeners/InteractListener.java b/src/main/java/net/onelitefeather/bettergopaint/listeners/InteractListener.java index da875ff1..1176f58c 100644 --- a/src/main/java/net/onelitefeather/bettergopaint/listeners/InteractListener.java +++ b/src/main/java/net/onelitefeather/bettergopaint/listeners/InteractListener.java @@ -26,6 +26,7 @@ import net.onelitefeather.bettergopaint.brush.PlayerBrush; import net.onelitefeather.bettergopaint.objects.brush.Brush; import net.onelitefeather.bettergopaint.objects.other.Settings; +import net.onelitefeather.bettergopaint.utils.Constants; import org.bukkit.FluidCollisionMode; import org.bukkit.Location; import org.bukkit.block.Block; @@ -52,7 +53,7 @@ public InteractListener(BetterGoPaint plugin) { public void onClick(PlayerInteractEvent event) { Player player = event.getPlayer(); - if (!player.hasPermission(BetterGoPaint.USE_PERMISSION)) { + if (!player.hasPermission(Constants.USE_PERMISSION)) { return; } @@ -85,7 +86,7 @@ public void onClick(PlayerInteractEvent event) { return; } - final boolean hasNotWorldByePassPermission = !player.hasPermission(BetterGoPaint.WORLD_BYPASS_PERMISSION); + final boolean hasNotWorldByePassPermission = !player.hasPermission(Constants.WORLD_BYPASS_PERMISSION); if (hasNotWorldByePassPermission && Settings.settings().generic.DISABLED_WORLDS .contains(location.getWorld().getName())) { diff --git a/src/main/java/net/onelitefeather/bettergopaint/objects/other/Settings.java b/src/main/java/net/onelitefeather/bettergopaint/objects/other/Settings.java index 8db7c306..71e975bc 100644 --- a/src/main/java/net/onelitefeather/bettergopaint/objects/other/Settings.java +++ b/src/main/java/net/onelitefeather/bettergopaint/objects/other/Settings.java @@ -23,8 +23,6 @@ import org.bukkit.Axis; import org.bukkit.Material; -import java.io.File; -import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -33,19 +31,6 @@ public final class Settings extends Config { @Ignore private static final Settings settings = new Settings(); - public void reload(BetterGoPaint plugin, File file) { - try { - if (file.isFile() || file.createNewFile()) { - load(file); - save(file); - } else { - plugin.getComponentLogger().error("Failed to create file {}", file.getName()); - } - } catch (IOException e) { - plugin.getComponentLogger().error("Failed to create file {}", file.getName(), e); - } - } - @Create public Generic generic; @@ -61,6 +46,9 @@ public void reload(BetterGoPaint plugin, File file) { @Comment("This is related to generic settings") public static class Generic { + @Comment("Supported Languages") + public List LANGUAGES = new ArrayList<>(); + @Comment({ "Default brush item", "Possible values: " + BetterGoPaint.PAPER_DOCS, diff --git a/src/main/java/net/onelitefeather/bettergopaint/service/UpdateService.java b/src/main/java/net/onelitefeather/bettergopaint/service/UpdateService.java new file mode 100644 index 00000000..d508e2f4 --- /dev/null +++ b/src/main/java/net/onelitefeather/bettergopaint/service/UpdateService.java @@ -0,0 +1,112 @@ +/* + * goPaint is designed to simplify painting inside of Minecraft. + * Copyright (C) Arcaniax-Development + * Copyright (C) Arcaniax team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.onelitefeather.bettergopaint.service; + +import com.github.zafarkhaja.semver.Version; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.logger.slf4j.ComponentLogger; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.onelitefeather.bettergopaint.BetterGoPaint; +import net.onelitefeather.bettergopaint.objects.other.Settings; +import net.onelitefeather.bettergopaint.utils.Constants; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitTask; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.http.HttpClient; +import java.net.http.HttpResponse; + +public final class UpdateService implements Runnable { + private final HttpClient hangarClient = HttpClient.newBuilder().build(); + private static final Logger LOGGER = LoggerFactory.getLogger(UpdateService.class); + private final Version localVersion; + private Version remoteVersion; + private final BukkitTask scheduler; + private final String DOWNLOAD_URL = "https://hangar.papermc.io/OneLiteFeather/BetterGoPaint/versions/%s"; + + public UpdateService(BetterGoPaint betterGoPaint) { + this.localVersion = Version.parse(betterGoPaint.getPluginMeta().getVersion()); + this.scheduler = Bukkit.getScheduler().runTaskTimerAsynchronously(betterGoPaint, this, 0, 20 * 60 * 60 * 3); + } + + + @Override + public void run() { + var remoteVersion = getNewerVersion(); + if (remoteVersion != null) { + this.remoteVersion = remoteVersion; + for (Player onlinePlayer : Bukkit.getOnlinePlayers()) { + if (onlinePlayer.isOp() || onlinePlayer.hasPermission(Constants.PERMISSION_NOTIFY_UPDATE)) { + notifyPlayer(localVersion, remoteVersion, onlinePlayer); + } + } + } + } + + public void notifyConsole(ComponentLogger logger) { + if (this.remoteVersion != null && this.remoteVersion.isHigherThan(this.localVersion)) { + logger.warn(Component.translatable("bettergopaint.notify.update.console") + .arguments(Component.text(localVersion.toString()), + Component.text(remoteVersion.toString()), + Component.text(DOWNLOAD_URL.formatted(remoteVersion.toString())) + )); + } + } + + + public void notifyPlayer(Player player) { + if (this.remoteVersion != null && this.remoteVersion.isHigherThan(this.localVersion)) { + notifyPlayer(this.localVersion, this.remoteVersion, player); + } + } + + + private void notifyPlayer(Version localVersion, Version remoteVersion, Player player) { + player.sendMessage(Component.translatable("bettergopaint.notify.update.player") + .arguments( + MiniMessage.miniMessage().deserialize(Settings.settings().generic.PREFIX), + Component.text(localVersion.toString()), + Component.text(remoteVersion.toString()) + )); + } + + + @Nullable + private Version getNewerVersion() { + try { + HttpResponse httpResponse = hangarClient.send(Constants.LATEST_RELEASE_VERSION_REQUEST, HttpResponse.BodyHandlers.ofString()); + Version remoteVersion = Version.parse(httpResponse.body()); + if (remoteVersion.isHigherThan(this.localVersion)) { + return remoteVersion; + } + } catch (IOException | InterruptedException e) { + LOGGER.error("Something went wrong to check updates", e); + } + return null; + } + + public void shutdown() { + this.hangarClient.shutdownNow(); + this.scheduler.cancel(); + } +} diff --git a/src/main/java/net/onelitefeather/bettergopaint/translations/PluginTranslationRegistry.java b/src/main/java/net/onelitefeather/bettergopaint/translations/PluginTranslationRegistry.java new file mode 100644 index 00000000..cd7038e5 --- /dev/null +++ b/src/main/java/net/onelitefeather/bettergopaint/translations/PluginTranslationRegistry.java @@ -0,0 +1,138 @@ +/* + * goPaint is designed to simplify painting inside of Minecraft. + * Copyright (C) Arcaniax-Development + * Copyright (C) Arcaniax team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.onelitefeather.bettergopaint.translations; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.ComponentLike; +import net.kyori.adventure.text.TranslatableComponent; +import net.kyori.adventure.text.minimessage.Context; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.ParsingException; +import net.kyori.adventure.text.minimessage.tag.Tag; +import net.kyori.adventure.text.minimessage.tag.resolver.ArgumentQueue; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import net.kyori.adventure.translation.TranslationRegistry; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.text.MessageFormat; +import java.util.List; +import java.util.Locale; +import java.util.Objects; + +public final class PluginTranslationRegistry implements TranslationRegistry { + + private final TranslationRegistry backedRegistry; + + public PluginTranslationRegistry(TranslationRegistry backedRegistry) { + this.backedRegistry = backedRegistry; + } + + @Override + public boolean contains(@NotNull String key) { + return backedRegistry.contains(key); + } + + @Override + public @NotNull Key name() { + return backedRegistry.name(); + } + + @Override + public @Nullable MessageFormat translate(@NotNull String key, @NotNull Locale locale) { + return null; + } + + @Override + public @Nullable Component translate( + @NotNull TranslatableComponent component, + @NotNull Locale locale + ) { + final MessageFormat translationFormat = backedRegistry.translate(component.key(), locale); + + if (translationFormat == null) { + return null; + } + + final String miniMessageString = translationFormat.toPattern(); + + final Component resultingComponent; + + if (component.arguments().isEmpty()) { + resultingComponent = MiniMessage.miniMessage().deserialize(miniMessageString); + } else { + resultingComponent = MiniMessage.miniMessage().deserialize(miniMessageString, + new ArgumentTag(component.arguments())); + } + + if (component.children().isEmpty()) { + return resultingComponent; + } else { + return resultingComponent.children(component.children()); + } + } + + @Override + public void defaultLocale(@NotNull Locale locale) { + backedRegistry.defaultLocale(locale); + } + + @Override + public void register(@NotNull String key, @NotNull Locale locale, @NotNull MessageFormat format) { + backedRegistry.register(key, locale, format); + } + + @Override + public void unregister(@NotNull String key) { + backedRegistry.unregister(key); + } + + private static final class ArgumentTag implements TagResolver { + private static final String NAME = "argument"; + private static final String NAME_1 = "arg"; + + private final List argumentComponents; + + private ArgumentTag(final @NotNull List argumentComponents) { + this.argumentComponents = Objects.requireNonNull(argumentComponents, "argumentComponents"); + } + + @Override + public Tag resolve( + final @NotNull String name, + final @NotNull ArgumentQueue arguments, + final @NotNull Context ctx + ) throws ParsingException { + final int index = arguments.popOr("No argument number provided") + .asInt().orElseThrow(() -> ctx.newException("Invalid argument number", arguments)); + + if (index < 0 || index >= argumentComponents.size()) { + throw ctx.newException("Invalid argument number", arguments); + } + + return Tag.inserting(argumentComponents.get(index)); + } + + @Override + public boolean has(final @NotNull String name) { + return name.equals(NAME) || name.equals(NAME_1); + } + } +} diff --git a/src/main/java/net/onelitefeather/bettergopaint/utils/Constants.java b/src/main/java/net/onelitefeather/bettergopaint/utils/Constants.java new file mode 100644 index 00000000..a183b1a9 --- /dev/null +++ b/src/main/java/net/onelitefeather/bettergopaint/utils/Constants.java @@ -0,0 +1,36 @@ +/* + * goPaint is designed to simplify painting inside of Minecraft. + * Copyright (C) Arcaniax-Development + * Copyright (C) Arcaniax team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.onelitefeather.bettergopaint.utils; + +import java.net.URI; +import java.net.http.HttpRequest; + +public final class Constants { + + public static final String USE_PERMISSION = "bettergopaint.use"; + public static final String ADMIN_PERMISSION = "bettergopaint.admin"; + public static final String PERMISSION_NOTIFY_UPDATE = "bettergopaint.notify.admin.update"; + public static final String DISABLE_DONATION_NOTIFY = "bettergopaint.notify.disable.donation"; + public static final String RELOAD_PERMISSION = "bettergopaint.command.admin.reload"; + public static final String WORLD_BYPASS_PERMISSION = "bettergopaint.world.bypass"; + + public static final URI LATEST_RELEASE_VERSION_URI = URI.create("https://hangar.papermc.io/api/v1/projects/BetterGoPaint/latestrelease"); + public static final HttpRequest LATEST_RELEASE_VERSION_REQUEST = HttpRequest.newBuilder().GET().uri(LATEST_RELEASE_VERSION_URI).build(); + +} diff --git a/src/main/resources/bettergopaint.properties b/src/main/resources/bettergopaint.properties new file mode 100644 index 00000000..f5f3be7e --- /dev/null +++ b/src/main/resources/bettergopaint.properties @@ -0,0 +1,5 @@ +bettergopaint.notify.donation.console=To keep the project alive, we ask for donations to our https://opencollective\ + .com/onelitefeather/projects/bettergopaint +bettergopaint.notify.donation.player= To keep the project alive, we ask for donations to our OpenCollective +bettergopaint.notify.update.player= Your version() is older than our latest published version (). Please update as soon as possible to get continued support. Or click me to get on the download page! +bettergopaint.notify.update.console=Your version() is older than our latest published version (). Please update as soon as possible to get continued support. Or click use this link