├── .github └── dependabot.yml ├── .gitignore ├── LICENSE ├── README.md ├── bukkit-base ├── pom.xml └── src │ └── main │ └── com │ └── namelessmc │ └── plugin │ └── bukkit │ ├── BukkitCommandProxy.java │ ├── BukkitDataSender.java │ ├── BukkitEventProxy.java │ ├── BukkitNamelessPlugin.java │ ├── BukkitScheduler.java │ ├── UserSyncTask.java │ ├── VaultPermissions.java │ ├── audiences │ ├── BukkitNamelessConsole.java │ └── BukkitNamelessPlayer.java │ ├── hooks │ ├── PapiHook.java │ └── maintenance │ │ ├── KennyMaintenance.java │ │ └── MaintenanceStatusProvider.java │ └── store │ └── StoreMenu.java ├── bungeecord ├── pom.xml ├── resources │ └── bungee.yml └── src │ └── main │ └── com │ └── namelessmc │ └── plugin │ └── bungee │ ├── BungeeCommandProxy.java │ ├── BungeeDataSender.java │ ├── BungeeEventProxy.java │ ├── BungeeNamelessPlugin.java │ ├── BungeeScheduler.java │ └── audiences │ ├── BungeeAudienceProvider.java │ ├── BungeeNamelessConsole.java │ └── BungeeNamelessPlayer.java ├── common ├── pom.xml ├── resources │ ├── commands.yaml │ ├── languages │ │ ├── ar_SA.yaml │ │ ├── cs_CZ.yaml │ │ ├── da_DK.yaml │ │ ├── de_DE.yaml │ │ ├── el_GR.yaml │ │ ├── en_UK.yaml │ │ ├── en_US.yaml │ │ ├── es_419.yaml │ │ ├── es_ES.yaml │ │ ├── fa_IR.yaml │ │ ├── fr_FR.yaml │ │ ├── he_IL.yaml │ │ ├── hr_HR.yaml │ │ ├── hu_HU.yaml │ │ ├── id_ID.yaml │ │ ├── it_IT.yaml │ │ ├── ja_JP.yaml │ │ ├── ko_KR.yaml │ │ ├── lt_LT.yaml │ │ ├── nb_NO.yaml │ │ ├── nl_NL.yaml │ │ ├── nl_NL_form.yaml │ │ ├── pl_PL.yaml │ │ ├── pt_BR.yaml │ │ ├── ro_RO.yaml │ │ ├── ru_RU.yaml │ │ ├── sk_SK.yaml │ │ ├── sq_AL.yaml │ │ ├── sr_RS.yaml │ │ ├── sv_SE.yaml │ │ ├── tr_TR.yaml │ │ ├── uk_UA.yaml │ │ ├── vi_VN.yaml │ │ └── zh_CN.yaml │ ├── main.yaml │ └── modules.yaml └── src │ ├── filtered │ └── com │ │ └── namelessmc │ │ └── plugin │ │ └── common │ │ └── MavenConstants.java │ ├── main │ └── com │ │ └── namelessmc │ │ └── plugin │ │ └── common │ │ ├── AbstractDataSender.java │ │ ├── AbstractPermissions.java │ │ ├── AnnouncementTask.java │ │ ├── ApiProvider.java │ │ ├── ConfigurationHandler.java │ │ ├── DateFormatter.java │ │ ├── GroupSync.java │ │ ├── JoinNotRegisteredMessage.java │ │ ├── JoinNotificationsMessage.java │ │ ├── LanguageHandler.java │ │ ├── LuckPermsPermissions.java │ │ ├── Metrics.java │ │ ├── NamelessPlugin.java │ │ ├── Permission.java │ │ ├── Reloadable.java │ │ ├── Store.java │ │ ├── SyncBanToWebsite.java │ │ ├── UserCache.java │ │ ├── Websend.java │ │ ├── audiences │ │ ├── AbstractAudienceProvider.java │ │ ├── NamelessCommandSender.java │ │ ├── NamelessConsole.java │ │ └── NamelessPlayer.java │ │ ├── command │ │ ├── AbstractScheduledTask.java │ │ ├── AbstractScheduler.java │ │ ├── CommonCommand.java │ │ ├── GetNotificationsCommand.java │ │ ├── NamelessPluginCommand.java │ │ ├── RegisterCommand.java │ │ ├── ReportCommand.java │ │ ├── StoreChangeCreditsCommand.java │ │ ├── StoreViewCreditsCommand.java │ │ ├── SuggestCommand.java │ │ ├── UserInfoCommand.java │ │ └── VerifyCommand.java │ │ ├── event │ │ ├── NamelessEvent.java │ │ ├── NamelessJoinEvent.java │ │ ├── NamelessOfflinePlayerEvent.java │ │ ├── NamelessPlayerBanEvent.java │ │ ├── NamelessPlayerEvent.java │ │ └── NamelessPlayerQuitEvent.java │ │ └── logger │ │ ├── AbstractLogger.java │ │ └── JulLogger.java │ └── test │ └── java │ └── LanguageHandlerTest.java ├── oldbukkit ├── pom.xml ├── resources │ └── plugin.yml └── src │ └── main │ └── com │ └── namelessmc │ └── plugin │ └── oldbukkit │ ├── OldBukkitDataSender.java │ ├── OldBukkitNamelessPlugin.java │ └── audiences │ ├── LegacyCommandSenderAudience.java │ ├── OldBukkitAudienceProvider.java │ └── OldBukkitNamelessPlayer.java ├── paper ├── pom.xml ├── resources │ └── plugin.yml └── src │ └── main │ └── com │ └── namelessmc │ └── plugin │ └── paper │ ├── PaperAudienceProvider.java │ ├── PaperDataSender.java │ └── PaperNamelessPlugin.java ├── pom.xml ├── spigot ├── pom.xml ├── resources │ └── plugin.yml └── src │ └── main │ └── com │ └── namelessmc │ └── plugin │ └── spigot │ ├── SpigotAudienceProvider.java │ ├── SpigotDataSender.java │ └── SpigotNamelessPlugin.java ├── sponge10 ├── pom.xml ├── resources │ └── sponge_plugins.json └── src │ └── main │ └── com │ └── namelessmc │ └── plugin │ └── sponge10 │ └── SpongeNamelessPlugin.java ├── sponge7 ├── pom.xml └── src │ └── main │ └── com │ └── namelessmc │ └── plugin │ └── sponge7 │ ├── Slf4jLogger.java │ ├── SpongeCommandProxy.java │ ├── SpongeDataSender.java │ ├── SpongeEventProxy.java │ ├── SpongeNamelessPlugin.java │ ├── SpongeScheduler.java │ └── audiences │ ├── SpongeAudienceProvider.java │ ├── SpongeNamelessConsole.java │ └── SpongeNamelessPlayer.java ├── sponge8 ├── pom.xml ├── resources │ └── sponge_plugins.json └── src │ └── main │ └── com │ └── namelessmc │ └── plugin │ └── sponge8 │ ├── Log4jLogger.java │ ├── SpongeCommandProxy.java │ ├── SpongeDataSender.java │ ├── SpongeEventProxy.java │ ├── SpongeNamelessPlugin.java │ ├── SpongeScheduler.java │ └── audiences │ ├── SpongeAudienceProvider.java │ ├── SpongeNamelessConsole.java │ └── SpongeNamelessPlayer.java ├── sponge9 ├── pom.xml ├── resources │ └── sponge_plugins.json └── src │ └── main │ └── com │ └── namelessmc │ └── plugin │ └── sponge9 │ ├── Log4jLogger.java │ ├── SpongeCommandProxy.java │ ├── SpongeDataSender.java │ ├── SpongeEventProxy.java │ ├── SpongeNamelessPlugin.java │ ├── SpongeScheduler.java │ └── audiences │ ├── SpongeAudienceProvider.java │ ├── SpongeNamelessConsole.java │ └── SpongeNamelessPlayer.java └── velocity ├── pom.xml └── src └── main └── com └── namelessmc └── plugin └── velocity ├── Slf4jLogger.java ├── VelocityCommandProxy.java ├── VelocityDataSender.java ├── VelocityEventProxy.java ├── VelocityNamelessPlugin.java ├── VelocityScheduler.java └── audiences ├── VelocityAudienceProvider.java ├── VelocityNamelessConsole.java └── VelocityNamelessPlayer.java /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: maven 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .project 2 | *.prefs 3 | *.classpath 4 | target/ 5 | .idea/ 6 | *.iml -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nameless-Plugin 2 | 3 | [![build status](https://ci.rkslot.nl/buildStatus/icon?job=Nameless+Plugin)](https://ci.rkslot.nl/job/Nameless%20Plugin/) 4 | [![translation status](https://translate.namelessmc.com/widgets/namelessmc/-/spigot-plugin/svg-badge.svg)](https://translate.namelessmc.com/engage/namelessmc/) 5 | [![discord](https://discord.com/api/guilds/246705793066467328/widget.png?style=shield)](https://discord.gg/nameless) 6 | 7 | The official Minecraft plugin for NamelessMC v2. For compiled files see the [spigot resource page](https://www.spigotmc.org/resources/nameless-plugin-for-v2.59032/) 8 | 9 | ## Features 10 | * Multi-platform! Supports Spigot 1.8-1.19, BungeeCord, Velocity, Sponge 7-9. 11 | * Commands to register or verify an account, report a player, read website notifications and more. 12 | * Configurable command names to avoid conflicts 13 | * Configurable messages with translation support 14 | * Server data sender (the plugin can send detailed information about the minecraft servers and the players online to the website) 15 | * Sync Minecraft groups to website groups 16 | * Whitelist registered users 17 | * Ban users on website when banned in-game 18 | * PlaceholderAPI placeholder for number of notifications (bukkit only) 19 | * Send placeholders to website for leaderboards (bukkit only) 20 | * Integration with Websend module to view server logs in StaffCP and run commands on the server. 21 | * Display website announcements in chat 22 | 23 | ## Installation 24 | 1. Install the plugin jar file in the `plugins` folder 25 | 2. Restart the server 26 | 3. Modify `config.yaml`: enter API URL and server id. 27 | 4. Run `/nlpl reload` 28 | 29 | ## Translations 30 | 31 | Translation status 32 | 33 | 34 | ## Compiling 35 | 36 | Requirements: Maven, Git, JDK 11, JDK 17 (only required for paper and sponge9) 37 | 38 | On Debian/Ubuntu: `apt install maven git openjdk-11-jdk openjdk-17-jdk` 39 | 40 | ```sh 41 | git clone https://github.com/Derkades/Derkutils 42 | cd Derkutils 43 | git checkout spigot-1.13 # important! 44 | mvn clean install # Uses JDK 11 45 | cd .. 46 | 47 | git clone https://github.com/NamelessMC/Nameless-Java-API 48 | cd Nameless-Java-API 49 | mvn clean install # Uses JDK 11 50 | cd .. 51 | 52 | git clone https://github.com/NamelessMC/Nameless-Plugin 53 | cd Nameless-Plugin 54 | mvn clean package # Uses JDK 11 and 17 55 | # find jar in {bungeecord,paper,spigot,sponge7,sponge8,sponge9,velocity}/target/* 56 | ``` 57 | 58 | Building the entire project can take quite a long time. You might want to build a single module only: 59 | ```sh 60 | mvn package -pl velocity -am 61 | ``` 62 | -------------------------------------------------------------------------------- /bukkit-base/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | plugin-bukkit-base 7 | Nameless-Plugin-Bukkit-Base 8 | 9 | 10 | ../pom.xml 11 | com.namelessmc 12 | plugin 13 | ${revision} 14 | 15 | 16 | 17 | src/main 18 | 19 | 20 | 21 | 22 | 23 | com.namelessmc 24 | plugin-common 25 | 26 | 27 | 28 | net.kyori 29 | adventure-text-serializer-plain 30 | 31 | 32 | 33 | org.bukkit 34 | bukkit 35 | 36 | 37 | com.google.code.gson 38 | gson 39 | 40 | 41 | org.yaml 42 | snakeyaml 43 | 44 | 45 | com.google.guava 46 | guava 47 | 48 | 49 | provided 50 | 51 | 52 | 53 | org.bstats 54 | bstats-bukkit 55 | 56 | 57 | 58 | me.clip 59 | placeholderapi 60 | provided 61 | 62 | 63 | 64 | com.github.MilkBowl 65 | VaultAPI 66 | provided 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /bukkit-base/src/main/com/namelessmc/plugin/bukkit/BukkitCommandProxy.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.bukkit; 2 | 3 | import java.util.Collections; 4 | import java.util.List; 5 | 6 | import org.bukkit.command.Command; 7 | import org.bukkit.command.CommandSender; 8 | import org.bukkit.command.ConsoleCommandSender; 9 | import org.bukkit.command.PluginIdentifiableCommand; 10 | import org.bukkit.entity.Player; 11 | import org.bukkit.plugin.Plugin; 12 | import org.checkerframework.checker.nullness.qual.Nullable; 13 | 14 | import com.namelessmc.plugin.common.NamelessPlugin; 15 | import com.namelessmc.plugin.common.audiences.AbstractAudienceProvider; 16 | import com.namelessmc.plugin.common.audiences.NamelessCommandSender; 17 | import com.namelessmc.plugin.common.command.CommonCommand; 18 | 19 | import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; 20 | import xyz.derkades.derkutils.bukkit.reflection.ReflectionUtil; 21 | 22 | public class BukkitCommandProxy { 23 | 24 | static void registerCommands(final NamelessPlugin plugin, 25 | final BukkitNamelessPlugin bukkitPlugin) { 26 | CommonCommand.commands(plugin).forEach(command -> { 27 | final String name = command.actualName(); 28 | if (name == null) { 29 | return; // Command is disabled 30 | } 31 | 32 | final PlainTextComponentSerializer ser = PlainTextComponentSerializer.plainText(); 33 | final String description = ser.serialize(command.description()); 34 | final String usage = ser.serialize(command.usage()); 35 | 36 | final Command spigotCommand = new SpigotCommand(bukkitPlugin, plugin.audiences(), command, name, description, usage); 37 | 38 | ReflectionUtil.registerCommand("nameless", spigotCommand); 39 | }); 40 | } 41 | 42 | private static class SpigotCommand extends Command implements PluginIdentifiableCommand { 43 | 44 | private final BukkitNamelessPlugin bukkitPlugin; 45 | private final AbstractAudienceProvider audiences; 46 | private final CommonCommand command; 47 | 48 | protected SpigotCommand(final BukkitNamelessPlugin bukkitPlugin, 49 | final AbstractAudienceProvider audiences, 50 | final CommonCommand command, 51 | final String name, 52 | final String plainDescription, 53 | final String plainUsage) { 54 | super(name, plainDescription, plainUsage, Collections.emptyList()); 55 | 56 | this.bukkitPlugin = bukkitPlugin; 57 | this.audiences = audiences; 58 | this.command = command; 59 | } 60 | 61 | private @Nullable NamelessCommandSender bukkitToNamelessSender(final CommandSender bukkitCommandSender) { 62 | if (bukkitCommandSender instanceof Player) { 63 | return this.audiences.player(((Player) bukkitCommandSender).getUniqueId()); 64 | } else if (bukkitCommandSender instanceof ConsoleCommandSender) { 65 | return this.audiences.console(); 66 | } else { 67 | return null; 68 | } 69 | } 70 | 71 | @Override 72 | public boolean execute(final CommandSender bukkitCommandSender, final String commandLabel, final String[] args) { 73 | final NamelessCommandSender sender = bukkitToNamelessSender(bukkitCommandSender); 74 | if (sender == null) { 75 | bukkitCommandSender.sendMessage("ERROR: Audience is null"); 76 | return true; 77 | } 78 | 79 | command.verifyPermissionThenExecute(sender, args); 80 | return true; 81 | } 82 | 83 | @Override 84 | public List tabComplete(final CommandSender bukkitCommandSender, final String alias, final String[] args) throws IllegalArgumentException { 85 | final NamelessCommandSender sender = bukkitToNamelessSender(bukkitCommandSender); 86 | if (sender == null) { 87 | return Collections.singletonList("ERROR: Audience is null"); 88 | } 89 | return command.complete(sender, args); 90 | } 91 | 92 | @Override 93 | public Plugin getPlugin() { 94 | return this.bukkitPlugin; 95 | } 96 | 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /bukkit-base/src/main/com/namelessmc/plugin/bukkit/BukkitEventProxy.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.bukkit; 2 | 3 | import com.namelessmc.plugin.common.NamelessPlugin; 4 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 5 | import com.namelessmc.plugin.common.event.NamelessJoinEvent; 6 | import com.namelessmc.plugin.common.event.NamelessPlayerBanEvent; 7 | import com.namelessmc.plugin.common.event.NamelessPlayerQuitEvent; 8 | import org.bukkit.entity.Player; 9 | import org.bukkit.event.EventHandler; 10 | import org.bukkit.event.EventPriority; 11 | import org.bukkit.event.Listener; 12 | import org.bukkit.event.player.PlayerJoinEvent; 13 | import org.bukkit.event.player.PlayerKickEvent; 14 | import org.bukkit.event.player.PlayerQuitEvent; 15 | import org.checkerframework.checker.nullness.qual.NonNull; 16 | 17 | import java.util.UUID; 18 | 19 | public class BukkitEventProxy implements Listener { 20 | 21 | private final @NonNull NamelessPlugin plugin; 22 | 23 | BukkitEventProxy(final @NonNull NamelessPlugin plugin) { 24 | this.plugin = plugin; 25 | } 26 | 27 | 28 | @EventHandler(priority = EventPriority.MONITOR) 29 | public void onJoin(final @NonNull PlayerJoinEvent event) { 30 | final Player bukkitPlayer = event.getPlayer(); 31 | final NamelessPlayer player = this.plugin.audiences().player(bukkitPlayer.getUniqueId()); 32 | if (player == null) { 33 | this.plugin.logger().severe("Skipped join event for " + bukkitPlayer.getName() + ", audience is null"); 34 | return; 35 | } 36 | this.plugin.events().post(new NamelessJoinEvent(player)); 37 | } 38 | 39 | @EventHandler(priority = EventPriority.MONITOR) 40 | public void onQuit(final @NonNull PlayerQuitEvent event) { 41 | final UUID uuid = event.getPlayer().getUniqueId(); 42 | this.plugin.events().post(new NamelessPlayerQuitEvent(uuid)); 43 | } 44 | 45 | @EventHandler(priority = EventPriority.MONITOR) 46 | public void onBan(final PlayerKickEvent event) { 47 | if (event.getPlayer().isBanned()) { 48 | this.plugin.events().post(new NamelessPlayerBanEvent(event.getPlayer().getUniqueId())); 49 | } 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /bukkit-base/src/main/com/namelessmc/plugin/bukkit/BukkitNamelessPlugin.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.bukkit; 2 | 3 | import com.namelessmc.plugin.bukkit.hooks.PapiHook; 4 | import com.namelessmc.plugin.bukkit.hooks.maintenance.KennyMaintenance; 5 | import com.namelessmc.plugin.bukkit.hooks.maintenance.MaintenanceStatusProvider; 6 | import com.namelessmc.plugin.common.LanguageHandler; 7 | import com.namelessmc.plugin.common.NamelessPlugin; 8 | import com.namelessmc.plugin.common.logger.JulLogger; 9 | import org.bstats.bukkit.Metrics; 10 | import org.bukkit.Bukkit; 11 | import org.bukkit.entity.Player; 12 | import org.bukkit.plugin.Plugin; 13 | import org.bukkit.plugin.java.JavaPlugin; 14 | import org.checkerframework.checker.nullness.qual.NonNull; 15 | import org.checkerframework.checker.nullness.qual.Nullable; 16 | 17 | import java.nio.file.Path; 18 | 19 | public abstract class BukkitNamelessPlugin extends JavaPlugin { 20 | 21 | private @Nullable MaintenanceStatusProvider maintenanceStatusProvider; 22 | public @Nullable MaintenanceStatusProvider getMaintenanceStatusProvider() { return this.maintenanceStatusProvider; } 23 | 24 | protected final @NonNull NamelessPlugin plugin; 25 | 26 | private final PapiHook papiHook; 27 | 28 | public BukkitNamelessPlugin(String platformInternalName) { 29 | final Path dataDirectory = this.getDataFolder().toPath(); 30 | this.plugin = new NamelessPlugin( 31 | dataDirectory, 32 | new BukkitScheduler(this), 33 | config -> new JulLogger(config, this.getLogger()), 34 | Path.of("logs", "latest.log"), 35 | platformInternalName, 36 | Bukkit.getVersion() 37 | ); 38 | 39 | this.plugin.registerReloadable(new UserSyncTask(this.plugin, this)); 40 | this.plugin.registerPermissionAdapter(new VaultPermissions(this.plugin)); 41 | 42 | this.papiHook = this.plugin.registerReloadable(new PapiHook(this, this.plugin)); 43 | } 44 | 45 | @Override 46 | public void onEnable() { 47 | this.configureAudiences(); 48 | 49 | this.plugin.load(); 50 | 51 | initMaintenance(); 52 | new Metrics(this, 13396); 53 | 54 | BukkitCommandProxy.registerCommands(this.plugin, this); 55 | 56 | this.getServer().getPluginManager().registerEvents(new BukkitEventProxy(this.plugin), this); 57 | } 58 | 59 | @Override 60 | public void onDisable() { 61 | this.plugin.unload(); 62 | } 63 | 64 | protected abstract void configureAudiences(); 65 | 66 | public abstract void kickPlayer(final @NonNull Player player, final LanguageHandler.@NonNull Term term); 67 | 68 | public PapiHook papi() { 69 | return this.papiHook; 70 | } 71 | 72 | private void initMaintenance() { 73 | if (!Bukkit.getPluginManager().isPluginEnabled("Maintenance")) { 74 | return; 75 | } 76 | 77 | Plugin plugin = Bukkit.getPluginManager().getPlugin("Maintenance"); 78 | if (!plugin.getDescription().getAuthors().contains("kennytv")) { 79 | return; 80 | } 81 | 82 | final String version = plugin.getDescription().getVersion(); 83 | if (!version.startsWith("4")) { 84 | this.plugin.logger().warning("Ignoring unsupported KennyTV Maintenance version: " + 85 | version); 86 | return; 87 | } 88 | 89 | this.maintenanceStatusProvider = new KennyMaintenance(); 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /bukkit-base/src/main/com/namelessmc/plugin/bukkit/BukkitScheduler.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.bukkit; 2 | 3 | import java.time.Duration; 4 | 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.scheduler.BukkitTask; 7 | import org.checkerframework.checker.nullness.qual.NonNull; 8 | import org.checkerframework.checker.nullness.qual.Nullable; 9 | 10 | import com.namelessmc.plugin.common.command.AbstractScheduledTask; 11 | import com.namelessmc.plugin.common.command.AbstractScheduler; 12 | 13 | public class BukkitScheduler extends AbstractScheduler { 14 | 15 | private final @NonNull BukkitNamelessPlugin plugin; 16 | 17 | BukkitScheduler(final @NonNull BukkitNamelessPlugin plugin) { 18 | this.plugin = plugin; 19 | } 20 | 21 | @Override 22 | public void runAsync(final @NonNull Runnable runnable) { 23 | if (!this.plugin.isEnabled()) { 24 | return; 25 | } 26 | Bukkit.getScheduler().runTaskAsynchronously(this.plugin, runnable); 27 | } 28 | 29 | @Override 30 | public void runSync(final @NonNull Runnable runnable) { 31 | if (!this.plugin.isEnabled()) { 32 | return; 33 | } 34 | Bukkit.getScheduler().runTask(this.plugin, runnable); 35 | } 36 | 37 | @Override 38 | @Nullable 39 | public BukkitScheduledTask runTimer(final @NonNull Runnable runnable, 40 | final @NonNull Duration interval) { 41 | if (!this.plugin.isEnabled()) { 42 | return null; 43 | } 44 | final long ticks = interval.toMillis() / 50; 45 | final BukkitTask task = Bukkit.getScheduler().runTaskTimer(this.plugin, runnable, ticks, ticks); 46 | return new BukkitScheduledTask(task); 47 | } 48 | 49 | @Override 50 | @Nullable 51 | public BukkitScheduledTask runDelayed(final @NonNull Runnable runnable, 52 | final @NonNull Duration delay) { 53 | if (!this.plugin.isEnabled()) { 54 | return null; 55 | } 56 | final long ticks = delay.toMillis() / 50; 57 | final BukkitTask task = Bukkit.getScheduler().runTaskLater(this.plugin, runnable, ticks); 58 | return new BukkitScheduledTask(task); 59 | } 60 | 61 | public static class BukkitScheduledTask extends AbstractScheduledTask { 62 | 63 | private final @NonNull BukkitTask task; 64 | 65 | private BukkitScheduledTask(final @NonNull BukkitTask task) { 66 | this.task = task; 67 | } 68 | 69 | @Override 70 | public void cancel() { 71 | this.task.cancel(); 72 | } 73 | 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /bukkit-base/src/main/com/namelessmc/plugin/bukkit/VaultPermissions.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.bukkit; 2 | 3 | import com.namelessmc.plugin.bukkit.audiences.BukkitNamelessPlayer; 4 | import com.namelessmc.plugin.common.AbstractPermissions; 5 | import com.namelessmc.plugin.common.NamelessPlugin; 6 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 7 | import com.namelessmc.plugin.common.logger.AbstractLogger; 8 | import net.milkbowl.vault.permission.Permission; 9 | import org.bukkit.Bukkit; 10 | import org.bukkit.entity.Player; 11 | import org.bukkit.plugin.RegisteredServiceProvider; 12 | import org.checkerframework.checker.nullness.qual.NonNull; 13 | import org.checkerframework.checker.nullness.qual.Nullable; 14 | 15 | import java.util.Arrays; 16 | import java.util.Set; 17 | import java.util.stream.Collectors; 18 | 19 | public class VaultPermissions extends AbstractPermissions { 20 | 21 | private final NamelessPlugin plugin; 22 | 23 | private @Nullable Permission permission; 24 | 25 | public VaultPermissions(final NamelessPlugin plugin) { 26 | this.plugin = plugin; 27 | } 28 | 29 | @Override 30 | public void unload() { 31 | this.permission = null; 32 | } 33 | 34 | @Override 35 | public void load() { 36 | final AbstractLogger log = this.plugin.logger(); 37 | if (Bukkit.getServer().getPluginManager().getPlugin("Vault") == null) { 38 | log.fine("Vault is not installed."); 39 | return; 40 | } 41 | 42 | final RegisteredServiceProvider permissionProvider = Bukkit.getServer().getServicesManager().getRegistration(Permission.class); 43 | if (permissionProvider == null) { 44 | log.warning("Vault is installed, but no vault-compatible permissions system is loaded. Is your permissions plugin compatible with Vault?"); 45 | return; 46 | } 47 | final Permission permission = permissionProvider.getProvider(); 48 | if (permission == null) { 49 | log.warning("Vault is installed, but no vault-compatible permissions system is loaded. Is your permissions plugin compatible with Vault?"); 50 | return; 51 | } 52 | 53 | if (!permission.hasGroupSupport()) { 54 | log.warning("Vault is installed, but the loaded permissions system ('" + permission.getName() + "') does not support groups. Is your permissions plugin compatible with Vault?"); 55 | return; 56 | } 57 | 58 | log.fine("Vault permissions seem to work"); 59 | 60 | this.permission = permission; 61 | } 62 | 63 | @Override 64 | public boolean isUsable() { 65 | return this.permission != null; 66 | } 67 | 68 | @Override 69 | public Set getGroups() { 70 | if (this.permission == null) { 71 | throw new ProviderNotUsableException(); 72 | } 73 | return Arrays.stream(this.permission.getGroups()).collect(Collectors.toUnmodifiableSet()); 74 | } 75 | 76 | @Override 77 | public Set getPlayerGroups(final @NonNull NamelessPlayer player) { 78 | if (this.permission == null) { 79 | throw new ProviderNotUsableException(); 80 | } 81 | final Player bukkitPlayer = ((BukkitNamelessPlayer) player).bukkitPlayer(); 82 | return Arrays.stream(this.permission.getPlayerGroups(bukkitPlayer)).collect(Collectors.toUnmodifiableSet()); 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /bukkit-base/src/main/com/namelessmc/plugin/bukkit/audiences/BukkitNamelessConsole.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.bukkit.audiences; 2 | 3 | import org.bukkit.Bukkit; 4 | 5 | import com.namelessmc.plugin.common.audiences.NamelessConsole; 6 | 7 | import net.kyori.adventure.audience.Audience; 8 | 9 | public class BukkitNamelessConsole extends NamelessConsole { 10 | 11 | public BukkitNamelessConsole(Audience audience) { 12 | super(audience); 13 | } 14 | 15 | @Override 16 | public void dispatchCommand(String command) { 17 | Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /bukkit-base/src/main/com/namelessmc/plugin/bukkit/audiences/BukkitNamelessPlayer.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.bukkit.audiences; 2 | 3 | import org.bukkit.entity.Player; 4 | import org.bukkit.metadata.MetadataValue; 5 | 6 | import com.namelessmc.plugin.common.ConfigurationHandler; 7 | import com.namelessmc.plugin.common.Permission; 8 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 9 | 10 | import net.kyori.adventure.audience.Audience; 11 | 12 | public class BukkitNamelessPlayer extends NamelessPlayer { 13 | 14 | private final Player player; 15 | 16 | public BukkitNamelessPlayer(final ConfigurationHandler config, final Audience audience, final Player player) { 17 | super(config, audience, player.getUniqueId(), player.getName()); 18 | this.player = player; 19 | } 20 | 21 | public Player bukkitPlayer() { 22 | return this.player; 23 | } 24 | 25 | @Override 26 | public boolean hasPermission(Permission permission) { 27 | return this.player.hasPermission(permission.toString()); 28 | } 29 | 30 | @Override 31 | public boolean isVanished() { 32 | // Supposedly works for at least SuperVanish and PremiumVanish 33 | // https://github.com/NamelessMC/Nameless-Plugin/issues/412#issuecomment-2567065505 34 | for (MetadataValue meta : player.getMetadata("vanished")) { 35 | if (meta.asBoolean()) { 36 | return true; 37 | } 38 | } 39 | return false; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /bukkit-base/src/main/com/namelessmc/plugin/bukkit/hooks/maintenance/KennyMaintenance.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.bukkit.hooks.maintenance; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | import java.lang.reflect.Method; 5 | 6 | public class KennyMaintenance implements MaintenanceStatusProvider { 7 | 8 | private Method instanceGetMethod; 9 | private Method isMaintenanceMethod; 10 | 11 | public KennyMaintenance() { 12 | try { 13 | Class maintenanceProviderClass = Class.forName("eu.kennytv.maintenance.api.MaintenanceProvider"); 14 | this.instanceGetMethod = maintenanceProviderClass.getMethod("get"); 15 | Class maintenanceInterface = Class.forName("eu.kennytv.maintenance.api.Maintenance"); 16 | this.isMaintenanceMethod = maintenanceInterface.getMethod("isMaintenance"); 17 | } catch (ClassNotFoundException | NoSuchMethodException e) { 18 | e.printStackTrace(); 19 | } 20 | } 21 | 22 | @Override 23 | public boolean maintenanceEnabled() { 24 | if (instanceGetMethod == null || isMaintenanceMethod == null) { 25 | // Not initialized properly 26 | return false; 27 | } 28 | 29 | try { 30 | Object instance = instanceGetMethod.invoke(null); 31 | Object isMaintenance = isMaintenanceMethod.invoke(instance); 32 | if (isMaintenance instanceof Boolean) { 33 | return (boolean) isMaintenance; 34 | } else { 35 | System.err.println("Unexpected return value from isMaintenance method"); 36 | return false; 37 | } 38 | } catch (IllegalAccessException | InvocationTargetException e) { 39 | e.printStackTrace(); 40 | return false; 41 | } 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /bukkit-base/src/main/com/namelessmc/plugin/bukkit/hooks/maintenance/MaintenanceStatusProvider.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.bukkit.hooks.maintenance; 2 | 3 | public interface MaintenanceStatusProvider { 4 | 5 | boolean maintenanceEnabled(); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /bukkit-base/src/main/com/namelessmc/plugin/bukkit/store/StoreMenu.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.bukkit.store; 2 | 3 | import com.namelessmc.java_api.NamelessAPI; 4 | import com.namelessmc.java_api.exception.NamelessException; 5 | import com.namelessmc.java_api.modules.store.StoreProduct; 6 | import com.namelessmc.plugin.common.NamelessPlugin; 7 | import org.bukkit.Material; 8 | import org.bukkit.entity.Player; 9 | import org.bukkit.inventory.ItemStack; 10 | import org.bukkit.plugin.Plugin; 11 | import org.checkerframework.checker.nullness.qual.Nullable; 12 | import xyz.derkades.derkutils.bukkit.ItemBuilder; 13 | import xyz.derkades.derkutils.bukkit.menu.IconMenu; 14 | import xyz.derkades.derkutils.bukkit.menu.OptionClickEvent; 15 | 16 | import java.util.Collections; 17 | import java.util.List; 18 | 19 | public class StoreMenu extends IconMenu { 20 | 21 | private final NamelessPlugin plugin; 22 | 23 | private @Nullable StoreProduct[] productsBySlot; 24 | 25 | public StoreMenu(Plugin bukkitPlugin, NamelessPlugin plugin, Player player) { 26 | super(bukkitPlugin, "Store menu", 3, player); 27 | this.plugin = plugin; 28 | 29 | this.plugin.scheduler().runAsync(this::loadPackages); 30 | } 31 | 32 | public void loadPackages() { 33 | NamelessAPI api = this.plugin.apiProvider().api(); 34 | if (api == null) { 35 | return; 36 | } 37 | 38 | final List products; 39 | try { 40 | products = api.store().products(); 41 | } catch (NamelessException e) { 42 | e.printStackTrace(); 43 | return; 44 | } 45 | 46 | this.plugin.scheduler().runSync(() -> fillMenu(products)); 47 | } 48 | 49 | public void fillMenu(List products) { 50 | StoreProduct[] productsBySlot = new StoreProduct[27]; 51 | int slot = 0; 52 | for (StoreProduct product : products) { 53 | if (product.isHidden()) { 54 | continue; 55 | } 56 | 57 | ItemStack item = new ItemBuilder(Material.STONE) 58 | .name(product.name()) 59 | .lore(Collections.singletonList("Price: " + String.format("%.2f", product.priceCents() / 100f))) 60 | .create(); 61 | 62 | this.addItem(slot, item); 63 | productsBySlot[slot] = product; 64 | slot++; 65 | } 66 | } 67 | 68 | @Override 69 | public boolean onOptionClick(OptionClickEvent event) { 70 | int slot = event.getPosition(); 71 | Player player = event.getPlayer(); 72 | 73 | if (this.productsBySlot == null) { 74 | player.sendMessage("menu not loaded yet"); 75 | return false; 76 | } 77 | 78 | StoreProduct product = this.productsBySlot[slot]; 79 | 80 | if (product == null) { 81 | player.sendMessage("unknown click"); 82 | return false; 83 | } 84 | 85 | if (product.isDisabled()) { 86 | player.sendMessage("product is disabled"); 87 | return false; 88 | } 89 | 90 | player.sendMessage("buy product " + product); 91 | return true; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /bungeecord/resources/bungee.yml: -------------------------------------------------------------------------------- 1 | name: NamelessMC 2 | main: com.namelessmc.plugin.bungee.BungeeNamelessPlugin 3 | version: '@project.version@' 4 | author: Derkades 5 | -------------------------------------------------------------------------------- /bungeecord/src/main/com/namelessmc/plugin/bungee/BungeeCommandProxy.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.bungee; 2 | 3 | import com.namelessmc.plugin.common.NamelessPlugin; 4 | import com.namelessmc.plugin.common.audiences.NamelessCommandSender; 5 | import com.namelessmc.plugin.common.command.CommonCommand; 6 | import net.md_5.bungee.api.CommandSender; 7 | import net.md_5.bungee.api.ProxyServer; 8 | import net.md_5.bungee.api.chat.TextComponent; 9 | import net.md_5.bungee.api.connection.ProxiedPlayer; 10 | import net.md_5.bungee.api.plugin.Command; 11 | import org.checkerframework.checker.nullness.qual.NonNull; 12 | 13 | public class BungeeCommandProxy { 14 | 15 | static void registerCommands(final NamelessPlugin plugin, final BungeeNamelessPlugin bungeePlugin) { 16 | CommonCommand.commands(plugin).forEach(command -> { 17 | final String name = command.actualName(); 18 | if (name == null) { 19 | return; // Command is disabled 20 | } 21 | final String permission = command.permission().toString(); 22 | 23 | Command bungeeCommand = new Command(name, permission) { 24 | @Override 25 | public void execute(final @NonNull CommandSender bungeeSender, final String[] args) { 26 | final NamelessCommandSender sender; 27 | if (bungeeSender instanceof ProxiedPlayer) { 28 | sender = plugin.audiences().player(((ProxiedPlayer) bungeeSender).getUniqueId()); 29 | } else { 30 | sender = plugin.audiences().console(); 31 | } 32 | 33 | if (sender == null) { 34 | bungeeSender.sendMessage(new TextComponent("ERROR: null audience")); 35 | return; 36 | } 37 | 38 | command.verifyPermissionThenExecute(sender, args); 39 | } 40 | }; 41 | 42 | ProxyServer.getInstance().getPluginManager().registerCommand(bungeePlugin, bungeeCommand); 43 | }); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /bungeecord/src/main/com/namelessmc/plugin/bungee/BungeeDataSender.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.bungee; 2 | 3 | import com.namelessmc.plugin.bungee.audiences.BungeeNamelessPlayer; 4 | import com.namelessmc.plugin.common.AbstractDataSender; 5 | import com.namelessmc.plugin.common.NamelessPlugin; 6 | import net.md_5.bungee.api.ProxyServer; 7 | import net.md_5.bungee.api.connection.ProxiedPlayer; 8 | import org.checkerframework.checker.nullness.qual.NonNull; 9 | 10 | public class BungeeDataSender extends AbstractDataSender { 11 | 12 | public BungeeDataSender(final @NonNull NamelessPlugin plugin) { 13 | super(plugin); 14 | } 15 | 16 | @SuppressWarnings("deprecation") 17 | @Override 18 | protected void registerCustomProviders() { 19 | // Max players 20 | // ProxyConfig is deprecated, but there seems to be no alternative. 21 | this.registerGlobalInfoProvider(json -> 22 | json.addProperty("max_players", ProxyServer.getInstance().getConfig().getPlayerLimit())); 23 | 24 | // Player address 25 | this.registerPlayerInfoProvider((json, player) -> { 26 | final ProxiedPlayer bungeePlayer = ((BungeeNamelessPlayer) player).bungeePlayer(); 27 | json.addProperty("address", bungeePlayer.getSocketAddress().toString()); 28 | }); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /bungeecord/src/main/com/namelessmc/plugin/bungee/BungeeEventProxy.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.bungee; 2 | 3 | import com.namelessmc.plugin.common.NamelessPlugin; 4 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 5 | import com.namelessmc.plugin.common.event.NamelessJoinEvent; 6 | import com.namelessmc.plugin.common.event.NamelessPlayerQuitEvent; 7 | import net.md_5.bungee.api.event.PlayerDisconnectEvent; 8 | import net.md_5.bungee.api.event.PostLoginEvent; 9 | import net.md_5.bungee.api.plugin.Listener; 10 | import net.md_5.bungee.event.EventHandler; 11 | import org.checkerframework.checker.nullness.qual.NonNull; 12 | 13 | import java.util.UUID; 14 | 15 | public class BungeeEventProxy implements Listener { 16 | 17 | private final @NonNull NamelessPlugin plugin; 18 | 19 | BungeeEventProxy(final @NonNull NamelessPlugin plugin) { 20 | this.plugin = plugin; 21 | } 22 | 23 | @EventHandler 24 | public void onJoin(final @NonNull PostLoginEvent event) { 25 | final NamelessPlayer player = plugin.audiences().player(event.getPlayer().getUniqueId()); 26 | if (player == null) { 27 | this.plugin.logger().severe("Skipped join event for player " + event.getPlayer().getName() + 28 | ", Audience is null"); 29 | return; 30 | } 31 | final NamelessJoinEvent event2 = new NamelessJoinEvent(player); 32 | plugin.events().post(event2); 33 | } 34 | 35 | @EventHandler 36 | public void onQuit(final @NonNull PlayerDisconnectEvent event) { 37 | final UUID uuid = event.getPlayer().getUniqueId(); 38 | final NamelessPlayerQuitEvent event2 = new NamelessPlayerQuitEvent(uuid); 39 | plugin.events().post(event2); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /bungeecord/src/main/com/namelessmc/plugin/bungee/BungeeNamelessPlugin.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.bungee; 2 | 3 | import com.namelessmc.plugin.bungee.audiences.BungeeAudienceProvider; 4 | import com.namelessmc.plugin.common.NamelessPlugin; 5 | import com.namelessmc.plugin.common.logger.JulLogger; 6 | import net.md_5.bungee.api.ProxyServer; 7 | import net.md_5.bungee.api.plugin.Plugin; 8 | import org.bstats.bungeecord.Metrics; 9 | import org.checkerframework.checker.nullness.qual.NonNull; 10 | 11 | import java.nio.file.Path; 12 | 13 | public class BungeeNamelessPlugin extends Plugin { 14 | 15 | private final @NonNull NamelessPlugin plugin; 16 | 17 | public BungeeNamelessPlugin() { 18 | Path dataDirectory = this.getDataFolder().toPath(); 19 | this.plugin = new NamelessPlugin( 20 | dataDirectory, 21 | new BungeeScheduler(this), 22 | config -> new JulLogger(config, this.getLogger()), 23 | Path.of("logs", "latest.log"), 24 | "bungeecord", 25 | ProxyServer.getInstance().getVersion() 26 | ); 27 | this.plugin.registerReloadable(new BungeeDataSender(this.plugin)); 28 | } 29 | 30 | @Override 31 | public void onEnable() { 32 | this.plugin.setAudienceProvider(new BungeeAudienceProvider(this.plugin.config(), this)); 33 | this.plugin.load(); 34 | 35 | new Metrics(this, 14864); 36 | 37 | BungeeCommandProxy.registerCommands(this.plugin, this); 38 | 39 | ProxyServer.getInstance().getPluginManager().registerListener(this, new BungeeEventProxy(this.plugin)); 40 | } 41 | 42 | @Override 43 | public void onDisable() { 44 | this.plugin.unload(); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /bungeecord/src/main/com/namelessmc/plugin/bungee/BungeeScheduler.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.bungee; 2 | 3 | import com.namelessmc.plugin.common.command.AbstractScheduledTask; 4 | import com.namelessmc.plugin.common.command.AbstractScheduler; 5 | import net.md_5.bungee.api.ProxyServer; 6 | import net.md_5.bungee.api.scheduler.ScheduledTask; 7 | import org.checkerframework.checker.nullness.qual.NonNull; 8 | 9 | import java.time.Duration; 10 | import java.util.concurrent.TimeUnit; 11 | 12 | public class BungeeScheduler extends AbstractScheduler { 13 | 14 | private final @NonNull BungeeNamelessPlugin plugin; 15 | 16 | BungeeScheduler(final @NonNull BungeeNamelessPlugin plugin) { 17 | this.plugin = plugin; 18 | } 19 | 20 | @Override 21 | public void runAsync(final @NonNull Runnable runnable) { 22 | ProxyServer.getInstance().getScheduler() 23 | .runAsync(this.plugin, runnable); 24 | } 25 | 26 | @Override 27 | public void runSync(final @NonNull Runnable runnable) { 28 | ProxyServer.getInstance().getScheduler() 29 | .schedule(this.plugin, runnable, 0, TimeUnit.NANOSECONDS); 30 | } 31 | 32 | @Override 33 | public @NonNull BungeeScheduledTask runTimer(@NonNull Runnable runnable, @NonNull Duration interval) { 34 | long l = interval.toNanos(); 35 | final ScheduledTask task = ProxyServer.getInstance().getScheduler() 36 | .schedule(this.plugin, runnable, l, l, TimeUnit.NANOSECONDS); 37 | return new BungeeScheduledTask(task); 38 | } 39 | 40 | 41 | @Override 42 | public @NonNull BungeeScheduledTask runDelayed(@NonNull Runnable runnable, @NonNull Duration delay) { 43 | long l = delay.toNanos(); 44 | final ScheduledTask task = ProxyServer.getInstance().getScheduler() 45 | .schedule(this.plugin, runnable, l, TimeUnit.NANOSECONDS); 46 | return new BungeeScheduledTask(task); 47 | } 48 | 49 | public static class BungeeScheduledTask extends AbstractScheduledTask { 50 | 51 | private final @NonNull ScheduledTask task; 52 | 53 | private BungeeScheduledTask(final @NonNull ScheduledTask task) { 54 | this.task = task; 55 | } 56 | 57 | @Override 58 | public void cancel() { 59 | this.task.cancel(); 60 | } 61 | 62 | 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /bungeecord/src/main/com/namelessmc/plugin/bungee/audiences/BungeeAudienceProvider.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.bungee.audiences; 2 | 3 | import com.namelessmc.plugin.bungee.BungeeNamelessPlugin; 4 | import com.namelessmc.plugin.common.ConfigurationHandler; 5 | import com.namelessmc.plugin.common.audiences.AbstractAudienceProvider; 6 | import com.namelessmc.plugin.common.audiences.NamelessConsole; 7 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 8 | import net.kyori.adventure.audience.Audience; 9 | import net.kyori.adventure.platform.bungeecord.BungeeAudiences; 10 | import net.md_5.bungee.api.ProxyServer; 11 | import net.md_5.bungee.api.connection.ProxiedPlayer; 12 | import org.checkerframework.checker.nullness.qual.NonNull; 13 | import org.checkerframework.checker.nullness.qual.Nullable; 14 | 15 | import java.util.Collection; 16 | import java.util.UUID; 17 | import java.util.stream.Collectors; 18 | 19 | public class BungeeAudienceProvider extends AbstractAudienceProvider { 20 | 21 | private final ConfigurationHandler config; 22 | private final BungeeAudiences audiences; 23 | 24 | public BungeeAudienceProvider(final ConfigurationHandler config, 25 | final BungeeNamelessPlugin bungeePlugin) { 26 | this.config = config; 27 | this.audiences = BungeeAudiences.create(bungeePlugin); 28 | } 29 | 30 | @Override 31 | public @NonNull NamelessConsole console() { 32 | return new BungeeNamelessConsole(audiences); 33 | } 34 | 35 | @Override 36 | public @NonNull Audience broadcast() { 37 | return audiences.all(); 38 | } 39 | 40 | public @Nullable NamelessPlayer bungeeToNamelessPlayer(final ProxiedPlayer bungeePlayer) { 41 | return bungeePlayer == null 42 | ? null 43 | : new BungeeNamelessPlayer(this.config, this.audiences, bungeePlayer); 44 | } 45 | 46 | @Override 47 | public @Nullable NamelessPlayer player(@NonNull UUID uuid) { 48 | return bungeeToNamelessPlayer(ProxyServer.getInstance().getPlayer(uuid)); 49 | } 50 | 51 | @Override 52 | public @Nullable NamelessPlayer playerByUsername(@NonNull String username) { 53 | return bungeeToNamelessPlayer(ProxyServer.getInstance().getPlayer(username)); 54 | } 55 | 56 | @Override 57 | public @NonNull Collection<@NonNull NamelessPlayer> onlinePlayers() { 58 | return ProxyServer.getInstance().getPlayers().stream() 59 | .map(p -> (NamelessPlayer) new BungeeNamelessPlayer(this.config, this.audiences, p)) 60 | .collect(Collectors.toUnmodifiableList()); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /bungeecord/src/main/com/namelessmc/plugin/bungee/audiences/BungeeNamelessConsole.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.bungee.audiences; 2 | 3 | import com.namelessmc.plugin.common.audiences.NamelessConsole; 4 | import net.kyori.adventure.platform.bungeecord.BungeeAudiences; 5 | import net.md_5.bungee.api.ProxyServer; 6 | 7 | public class BungeeNamelessConsole extends NamelessConsole { 8 | 9 | public BungeeNamelessConsole(BungeeAudiences audiences) { 10 | super(audiences.console()); 11 | } 12 | 13 | @Override 14 | public void dispatchCommand(String command) { 15 | ProxyServer.getInstance().getPluginManager().dispatchCommand(ProxyServer.getInstance().getConsole(), command); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /bungeecord/src/main/com/namelessmc/plugin/bungee/audiences/BungeeNamelessPlayer.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.bungee.audiences; 2 | 3 | import com.namelessmc.plugin.common.ConfigurationHandler; 4 | import com.namelessmc.plugin.common.Permission; 5 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 6 | import net.kyori.adventure.platform.bungeecord.BungeeAudiences; 7 | import net.md_5.bungee.api.connection.ProxiedPlayer; 8 | 9 | public class BungeeNamelessPlayer extends NamelessPlayer { 10 | 11 | private final ProxiedPlayer player; 12 | 13 | public BungeeNamelessPlayer(final ConfigurationHandler config, final BungeeAudiences audiences, final ProxiedPlayer player) { 14 | super(config, audiences.player(player), player.getUniqueId(), player.getName()); 15 | this.player = player; 16 | } 17 | 18 | public ProxiedPlayer bungeePlayer() { 19 | return this.player; 20 | } 21 | 22 | @Override 23 | public boolean hasPermission(final Permission permission) { 24 | return this.player.hasPermission(permission.toString()); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /common/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | plugin-common 7 | Nameless-Plugin-Common 8 | 9 | 10 | ../pom.xml 11 | com.namelessmc 12 | plugin 13 | ${revision} 14 | 15 | 16 | 17 | src/main 18 | 19 | 20 | 21 | resources 22 | true 23 | 24 | 25 | 26 | 27 | 28 | org.codehaus.mojo 29 | templating-maven-plugin 30 | 3.0.0 31 | 32 | 33 | filter-src 34 | 35 | filter-sources 36 | 37 | 38 | 39 | 40 | src/filtered 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | com.namelessmc 50 | java-api 51 | 52 | 53 | 54 | xyz.derkades 55 | Derkutils 56 | 57 | 58 | 59 | net.kyori 60 | event-api 61 | 62 | 63 | 64 | org.bstats 65 | bstats-base 66 | 67 | 68 | 69 | net.kyori 70 | adventure-api 71 | 72 | 73 | 74 | net.kyori 75 | adventure-text-minimessage 76 | 77 | 78 | 79 | org.spongepowered 80 | configurate-yaml 81 | 82 | 83 | 84 | org.checkerframework 85 | checker-qual 86 | 87 | 88 | 89 | net.luckperms 90 | api 91 | provided 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /common/resources/commands.yaml: -------------------------------------------------------------------------------- 1 | # The server needs to be fully restarted for changes to take effect due to Minecraft limitations. 2 | # Commands can be disabled by commenting a line. 3 | 4 | get-notifications: 'notifications' 5 | register: 'register' 6 | report: 'report' 7 | user-info: 'webinfo' 8 | verify: 'verify' 9 | plugin: 'nlpl' 10 | 11 | # Commands for Partydragen's store module 12 | #store-change-credits: 'changecredits' 13 | #store-view-credits: 'credits' 14 | 15 | # Commands for Partydragen's suggestions module 16 | #suggest: 'suggest' 17 | -------------------------------------------------------------------------------- /common/resources/languages/el_GR.yaml: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /common/resources/languages/fa_IR.yaml: -------------------------------------------------------------------------------- 1 | error: 2 | website-username-not-exist: Hich karbare website ba in name vojod nadarad. 3 | -------------------------------------------------------------------------------- /common/resources/languages/hr_HR.yaml: -------------------------------------------------------------------------------- 1 | command: 2 | not-a-player: Morate biti igrač da biste izvršili ovu naredbu. 3 | plugin: 4 | description: Administrativne naredbe za NamelessMC dodatak 5 | usage: / 'reload'/'rl'/'last_error' 6 | notifications: 7 | output: 8 | no-notifications: Nemate nijednu nepročitanu obavijest. 9 | notification: "> 10 | usage: / 11 | description: Prikazuje popis obavijesti web stranice. 12 | no-permission: Nemate dozvolu za izvršenje ove naredbe. 13 | error: 14 | username-not-online: Navedeno korisničko ime je nevažeće ili igrač nije online. 15 | discord-username-not-exist: Ne postoji korisnik s ovim korisničkim imenom na 16 | Discord-u. 17 | website-username-not-exist: Ne postoji korisnik s ovim korisničkim imenom. 18 | website-connection: Došlo je do pogreške prilikom pokušaja povezivanja na web 19 | stranicu. 20 | minecraft-uuid-not-exist: Ne postoji korisnik web stranice s ovim Minecraft 21 | UUID-om. 22 | target-no-website-account: Navedeni igrač nema račun na web stranici. 23 | player: 24 | self: 25 | command-banned: Ne možete pokrenuti ovu naredbu, zabranjen vam je pristup 26 | web stranici. 27 | not-registered: Morate se registrirati kako biste izvršili ovu radnju. 28 | boolean: 29 | yes-positive: Da 30 | yes-negative: Da 31 | no-positive: Ne 32 | no-negative: Ne 33 | -------------------------------------------------------------------------------- /common/resources/languages/id_ID.yaml: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /common/resources/languages/ko_KR.yaml: -------------------------------------------------------------------------------- 1 | player: 2 | other: {} 3 | self: 4 | command-banned: 사이트에서 차단되어 이 명령을 실행할 수 없습니다. 5 | not-registered: 이 동작을 수행하려면 등록되어야 합니다. 6 | command: 7 | notifications: 8 | output: 9 | no-notifications: 새 알림이 없습니다. 10 | notification: "> 11 | usage: /{command} 12 | description: 웹 사이트의 알림 목록을 불러옵니다. 13 | register: 14 | output: 15 | fail: 16 | email-used: 다른 계정에서 사용 중인 메일입니다. 17 | email-invalid: 유효하지 않은 메일 주소입니다. 18 | cannot-send-email: 인증 메일을 보낼 수 없습니다. 관리자를 통해 계정을 활성화하십시오. 19 | username-invalid: 잘못된 아이디입니다. 20 | username-used: 이미 사용중인 닉네임입니다. 21 | minecraft-used: 당신의 마인크래프트 계정은 이미 다른 사용자의 계정에 연결되어있습니다. 22 | console-must-specify-username: 콘솔에서 register 명령을 실행할 때 사용자 이름을 지정해야 합니다. 23 | custom-username-disabled: Minecraft 사용자 이름이 아닌 다른 사용자 이름으로 등록할 수 없습니다. 24 | success: 25 | email: 발송된 인증 메일을 확인하십시오. 26 | link: '{link}로 접속해 인증을 완료하십시오.' 27 | usage: /{command} [username] 28 | description: 웹 사이트 아이디를 생성합니다 29 | report: 30 | output: 31 | fail: 32 | already-open: 이미 신고된 플레이어를 신고할 수 없습니다. 33 | report-self: 스스로를 신고할 수 없습니다. 34 | success: 신고가 접수되었습니다. 35 | usage: /{command} <닉네임/UUID> <사유> 36 | description: 플레이어를 신고합니다 37 | validate: 38 | output: 39 | fail: 40 | already-validated: 이미 인증된 계정입니다. 41 | invalid-code: 잘못된 코드입니다. 제대로 복사했는지 확인 후 다시 시도하십시오. 42 | success: 계정이 활성화되었습니다. 43 | usage: /{command} <코드> 44 | description: 입력된 코드로 플레이어의 웹 사이트 계정을 활성화합니다. 45 | not-a-player: 플레이어만 이 명령어를 사용할 수 있습니다. 46 | no-permission: 권한이 없습니다. 47 | user-info: 48 | usage: /{command} [아이디] 49 | description: 웹 사이트 유저의 정보를 불러옵니다 50 | output: 51 | username: '아이디: {username}' 52 | displayname: '표시된 이름: {displayname}' 53 | uuid: 'UUID: {uuid}' 54 | uuid-unknown: 알 수 없음 55 | primary-group: '기본 그룹: {groupname}' 56 | all-groups: '모든 그룹: {groups_names_list}' 57 | registered-date: '{date}에 가입함' 58 | validated: '{validated}에 인증됨' 59 | banned: '{banned}에 차단됨' 60 | integrations: 61 | identifier: '식별자: ' 62 | username: '닉네임: ' 63 | linked-date: '연결 날짜: ' 64 | header: '통합:' 65 | verified: '인증 여부: ' 66 | custom-field: "커스텀 항목 '': " 67 | subcommands: {} 68 | plugin: 69 | output: 70 | reload-successful: 플러그인이 다시 로드되었습니다. 71 | usage: / 'reload'|'rl'|'last_error' 72 | description: NamelessMC 플러그인 관리자 명령어 73 | store-credits: {} 74 | join-not-registered: 웹 사이트 계정이 존재하지 않습니다. /register 로 가입하세요. 75 | error: 76 | website-username-not-exist: 해당 아이디의 웹 사이트 사용자가 없습니다. 77 | website-connection: 웹 사이트에 연결하는 도중 오류가 발생했습니다. 78 | username-not-online: 접속해 있지 않거나 유효하지 않은 닉네임입니다. 79 | discord-username-not-exist: 해당 디스코드 닉네임의 사용자가 없습니다. 80 | minecraft-uuid-not-exist: 해당 마인크래프트 UUID의 사용자가 없습니다. 81 | target-no-website-account: 해당 플레이어는 웹사이트 계정이 없습니다. 82 | boolean: 83 | yes-positive: 84 | yes-negative: 85 | no-positive: 아니오 86 | no-negative: 아니오 87 | join-notifications: 웹 사이트에서 알림이 왔습니다. / 명령어로 자세히 확인해보세요. 88 | website-announcement: '웹 사이트 공지: ' 89 | user-sync-kick: 웹 사이트 계정이 차단되어 이 서버에서 차단되었습니다. 90 | -------------------------------------------------------------------------------- /common/resources/languages/lt_LT.yaml: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /common/resources/languages/nb_NO.yaml: -------------------------------------------------------------------------------- 1 | player: 2 | other: {} 3 | self: 4 | not-registered: Du må registrere en konto for å utføre denne handlingen. 5 | command-banned: Du kan ikke utføre denne kommandoen, du er utestengt fra nettsiden. 6 | command: 7 | report: 8 | description: Rapporter en spiller 9 | usage: /{command} 10 | output: 11 | success: Takk for at du rapporterte denne spilleren. 12 | fail: 13 | already-open: Du kan ikke rapportere denne spillere, fordi en rapport allerede 14 | er åpen for dem. 15 | report-self: Du kan ikke rapportere deg selv. 16 | notifications: 17 | usage: /{command} 18 | output: 19 | no-notifications: Du har ingen uleste varslinger. 20 | notification: "> 21 | description: Viser en liste over alle nettsidevarsler. 22 | no-permission: Du har ikke tilgang til denne kommandoen. 23 | register: 24 | usage: /{command} 25 | description: Opprett en nettsidekonto 26 | output: 27 | success: 28 | email: Sjekk innboksen din for å fullføre registrering . 29 | link: ">Vennligst 30 | fullfør registreringen ved å gå til . 31 | fail: 32 | email-used: Denne e-postadressen er allerede i bruk av en annen brukerkonto. 33 | email-invalid: Den angitte e-postadressen er ugyldig. 34 | username-invalid: Det angitte brukernavnet er ugyldig. 35 | cannot-send-email: Kunne ikke sende registreringse-post, vennligst kontakt 36 | en admin for å aktivere kontoen din. 37 | validate: 38 | usage: /{command} 39 | output: 40 | success: Kontoen din har blitt validert. 41 | fail: 42 | invalid-code: Valideringskoden var feil. Vennligst sjekk at du kopierte den 43 | riktig og prøv igjen. 44 | already-validated: Kontoen din er allerede validert. 45 | description: Validerer brukerens nettsidekonto med den oppgitte koden. 46 | user-info: 47 | usage: /{command} [brukernavn] 48 | output: 49 | displayname: 'Visningsnavn: ' 50 | uuid: 'UUID: ' 51 | uuid-unknown: ukjent 52 | validated: 'Konto validert: ' 53 | username: 'Brukernavn: ' 54 | all-groups: 'Alle grupper: ' 55 | registered-date: Registrert 56 | banned: 'Utestengt: ' 57 | primary-group: 'Primærgruppe: ' 58 | description: Hent informasjon om en nettsidebruker 59 | not-a-player: Du må være en spiller for å utføre denne kommandoen. 60 | website-announcement: 'Nettsidekunngjøring: ' 61 | join-not-registered: Du har ikke en konto på nettsiden vår enda. Vennligst registrer 62 | deg med /register. 63 | -------------------------------------------------------------------------------- /common/resources/languages/nl_NL_form.yaml: -------------------------------------------------------------------------------- 1 | player: 2 | self: 3 | not-registered: U heeft een account nodig om deze actie uit te voeren. 4 | command-banned: U kunt deze opdracht niet uitvoeren, u bent verbannen van de website. 5 | other: {} 6 | command: 7 | not-a-player: U moet een speler zijn om dit commando uit te voeren. 8 | notifications: 9 | usage: '/{command}' 10 | output: 11 | no-notifications: U heeft geen ongelezen berichten. 12 | notification: "> 13 | description: Laat een lijst van websiteberichten zien. 14 | no-permission: U heeft geen toestemming om dit commando uit te voeren. 15 | report: 16 | description: Rapporteer een speler 17 | usage: '/{command} ' 18 | output: 19 | fail: 20 | already-open: U kunt deze speler niet rapporteren, u heeft al een open rapport 21 | over hem. 22 | report-self: U kunt uzelf niet rapporteren. 23 | success: Bedankt om deze speler te rapporteren. 24 | user-info: 25 | usage: '/{command} [gebruikersnaam]' 26 | output: 27 | registered-date: Geregistreerd op 28 | validated: 'Account gevalideerd: ' 29 | username: 'Gebruikersnaam: ' 30 | primary-group: 'Hoofdgroep: ' 31 | banned: 'Verbannen: ' 32 | all-groups: 'Alle groepen: ' 33 | displayname: 'Weergavenaam: ' 34 | uuid: 'UUID: ' 35 | uuid-unknown: onbekend 36 | description: Haal informatie op over een website gebruiker 37 | validate: 38 | output: 39 | success: Uw account is gevalideerd. 40 | fail: 41 | already-validated: Uw account is al gevalideerd. 42 | invalid-code: Uw validatie code is ongeldig. Kijkt u alstublieft na of u deze 43 | correct gekopieerd heeft en probeer het opnieuw. 44 | usage: /{command} 45 | description: Valideert de gebruiker zijn website account door middel van de opgegeven 46 | code. 47 | register: 48 | usage: '/{command} ' 49 | output: 50 | fail: 51 | username-invalid: De opgegeven gebruikersnaam is ongeldig. 52 | cannot-send-email: Kon de registratie e-mail niet verzenden, neem contact 53 | op met de serverbeheerder. 54 | email-used: Dit email adres is al gebruikt voor een ander account. 55 | email-invalid: Het opgegeven email adres is ongeldig. 56 | success: 57 | link: ">Om 58 | de registratie te voltooien, ga alstublieft naar . 59 | email: Controleer alstublieft uw e-mail inbox om de registratie te voltooien. 60 | description: Maak een website account 61 | subcommands: {} 62 | join-not-registered: U heeft nog geen account op onze website. Registreer alstublieft 63 | met /register. 64 | website-announcement: 'Website aankondiging: ' 65 | -------------------------------------------------------------------------------- /common/resources/languages/pl_PL.yaml: -------------------------------------------------------------------------------- 1 | player: 2 | other: {} 3 | self: 4 | not-registered: Musisz być zarejestrowany, aby wykonać tą akcję. 5 | command-banned: Nie możesz użyć tej komendy, ponieważ zostałeś/aś wykluczony/a 6 | ze strony. 7 | command: 8 | not-a-player: Musisz być graczem, aby wykonać tą komendę. 9 | no-permission: Nie posiadasz odpowiednich uprawnień, aby wykonać to polecenie. 10 | notifications: 11 | usage: '/' 12 | output: 13 | no-notifications: Brak nie przeczytanych powiadomień. 14 | notification: "> 15 | description: Wyświetla listę powiadomień strony. 16 | register: 17 | usage: '/ \ [nick]' 18 | output: 19 | success: 20 | email: Prosze sprawdzic swoja skrzynke w celu dokonczenia rejestracji. 21 | link: Prosze wejsc na w celu dokkonczenia rejestracji. 22 | fail: 23 | email-used: Ten adres email został już użyty przez innego użytkownika. 24 | email-invalid: Podany email jest nieprawidłowy. 25 | username-invalid: Podana nazwa nie jest prawidłowa. 26 | cannot-send-email: Nie udało się wysłać rejerstracji email, proszę skontaktuj 27 | się z adminem aby aktywował twoje konto. 28 | username-used: Podany nick jest już używany przez inne konto. 29 | minecraft-used: Twoje konto Minecraft jest już podłączone pod inne konto. 30 | description: Tworzy konto na stronie 31 | report: 32 | usage: '/{command} ' 33 | output: 34 | success: Dziekujemy za zgloszenie. 35 | fail: 36 | already-open: Nie możesz zgłosić tego gracza, już został przez ciebie zgłoszony. 37 | report-self: Nie możesz zgłosić siebie. 38 | description: Zglos gracza 39 | validate: 40 | usage: '/{command} ' 41 | description: Zweryfikuj swoje konto na stronie uzywajac kodu. 42 | output: 43 | success: Twoje konto zostalo zweryfikowane. 44 | fail: 45 | invalid-code: Twoj kod weryfikujacy jest bledny. Sprawdz czy skopiowales go 46 | dobrze i sprobuj jeszcze raz. 47 | already-validated: Twoje konto już jest zatwierdzone. 48 | user-info: 49 | usage: '/{command} [nazwa użytkownika]' 50 | output: 51 | username: 'Nick: ' 52 | uuid: 'UUID: ' 53 | validated: 'Konto zweryfikowane: ' 54 | banned: 'Zbanowany: ' 55 | registered-date: Zarejestrowany 56 | displayname: 'Wyswietlany nick: ' 57 | uuid-unknown: nieznany 58 | all-groups: 'Wszystkie grupy: ' 59 | primary-group: 'Podstawowa grupa: ' 60 | description: Zdobadz informacje o uzytkowniku 61 | subcommands: {} 62 | plugin: 63 | usage: / 'reload'/'rl'/'last_error' 64 | description: Polecenia administracyjne dla wtyczki NamelessMC 65 | output: 66 | reload-successful: Wtyczka przeładowana pomyślnie. 67 | join-not-registered: Nie posiadasz jeszcze konta na stronie. Prosimy sie zarejestrowac 68 | przy uzyciu /register. 69 | error: 70 | minecraft-uuid-not-exist: Żaden użytkownik nie posiada takiego UUID Minecrafta. 71 | target-no-website-account: Podany gracz nie posiada konta na stronie. 72 | website-username-not-exist: Żaden użytkownik strony nie istnieje z taką nazwą. 73 | website-connection: Wystąpił błąd podczas łączenia się ze stroną. 74 | discord-username-not-exist: Żaden użytkownik strony nie istnieje z taką nazwą na 75 | Discordzie. 76 | username-not-online: Nazwa użytkownika nie jest prawidłowa lub użytkownik jest offline. 77 | boolean: 78 | no-positive: Nie 79 | yes-positive: Tak 80 | yes-negative: Nie 81 | no-negative: Nie 82 | -------------------------------------------------------------------------------- /common/resources/languages/sr_RS.yaml: -------------------------------------------------------------------------------- 1 | error: 2 | website-username-not-exist: Ne postoji korisnik pod ovim imenom. 3 | discord-username-not-exist: Ne postoji korisnik pod ovim Diskord imenom. 4 | -------------------------------------------------------------------------------- /common/resources/languages/sv_SE.yaml: -------------------------------------------------------------------------------- 1 | player: 2 | other: {} 3 | self: 4 | not-registered: Du måste registrera ett konto för att utföra detta. 5 | command-banned: Du kan inte utföra detta kommando, du är bannlyst från hemsidan. 6 | command: 7 | not-a-player: Du måste vara en spelare för att utföra detta kommando. 8 | no-permission: Du har inte tillåtelse att utföra detta kommando. 9 | notifications: 10 | usage: /{command} 11 | description: Visar en lista över notifikationer. 12 | output: 13 | no-notifications: Du har inte några icke lästa notifikationer. 14 | notification: "> 15 | report: 16 | output: 17 | fail: 18 | already-open: Du kan inte anmäla den här spelaren, eftersom du redan har en 19 | öppen anmälning om honom. 20 | report-self: Du kan inte anmäla dig själv. 21 | success: Tack för att du anmälde den här spelaren. 22 | usage: /{command} 23 | description: Anmäl en spelare 24 | register: 25 | usage: /{command} 26 | description: Skapa ett webbplatskonto 27 | output: 28 | success: 29 | email: Kontrollera din inkorg för att slutföra registreringen. 30 | link: ">Registrera 31 | dig genom att gå till . 32 | fail: 33 | email-used: Den här e-postadressen används redan för ett annat användarkonto. 34 | email-invalid: Den angivna e-postadressen är ogiltig. 35 | username-invalid: Det angivna användarnamnet är ogiltigt. 36 | cannot-send-email: Det går inte att skicka ett registreringsmeddelande, kontakta 37 | en administratör för att aktivera ditt konto. 38 | username-used: Ditt användarnamn används redan. 39 | validate: 40 | usage: /{command} 41 | description: Validerar användarens webbplatskonto med hjälp av den angivna koden. 42 | output: 43 | success: Ditt konto har godkänts. 44 | fail: 45 | invalid-code: Din valideringskod är felaktig. Kontrollera om du har kopierat 46 | koden korrekt och försök igen. 47 | already-validated: Ditt konto har redan godkänts. 48 | user-info: 49 | usage: /{command} [användarnamn] 50 | description: Hämta information om en webbplatsanvändare 51 | output: 52 | displayname: 'Smeknamn: ' 53 | uuid: 'UUID: ' 54 | uuid-unknown: 'UUID: okänd' 55 | primary-group: 'Primärgrupp: ' 56 | all-groups: 'Alla grupper: ' 57 | registered-date: Registrerad 58 | validated: 'Konto validerat: ' 59 | banned: 'Bannlyst: ' 60 | username: 'Användarnamn: ' 61 | plugin: 62 | output: 63 | reload-successful: Plugin har laddats om. 64 | description: Administrativa kommandon för NamelessMC plugin 65 | website-announcement: 'Meddelande från webbplatsen: ' 66 | user-sync-kick: Du är bannlyst från vår server efter att ha bannlysts från ert konto 67 | på webbplatsen. 68 | join-not-registered: Du har ännu inget konto på vår webbplats. Registrera dig med 69 | hjälp av /register. 70 | error: 71 | website-username-not-exist: Ingen användare med detta användarnamnet existerar 72 | website-connection: Ett fel uppstod när du försökte ansluta till webbplatsen. 73 | username-not-online: Det angivna användarnamnet är ogiltigt eller så är spelaren 74 | inte online. 75 | boolean: 76 | yes-positive: Ja 77 | no-positive: Nej 78 | yes-negative: Ja 79 | no-negative: Nej 80 | -------------------------------------------------------------------------------- /common/resources/languages/tr_TR.yaml: -------------------------------------------------------------------------------- 1 | command: 2 | validate: 3 | output: 4 | fail: 5 | invalid-code: Doğrulama kodunuz yanlış. Lütfen doğru kopyalayıp kopyalamadığınızı 6 | kontrol edin ve tekrar deneyin. 7 | already-validated: Hesabınız zaten doğrulandı. 8 | success: Hesabınız doğrulandı. 9 | usage: '/{command} ' 10 | description: Verilen kodu kullanarak kullanıcının web sitesi hesabını doğrular. 11 | user-info: 12 | output: 13 | uuid: 'UUID: ' 14 | uuid-unknown: 'UUD: bilinmiyor' 15 | displayname: 'Görünen ad: ' 16 | username: 'Kullanıcı Adı: ' 17 | registered-date: 'Kayıt Tarihi : ' 18 | validated: 'Doğrulanmış Hesap: ' 19 | banned: 'Yasaklı: ' 20 | primary-group: 'Birincil grup: ' 21 | all-groups: 'Tüm gruplar: ' 22 | description: Bir web sitesi kullanıcısı hakkında bilgi alın 23 | usage: '/{command} [kullanıcı adı]' 24 | no-permission: Bu komutu yürütme izniniz yok. 25 | notifications: 26 | usage: '/{command}' 27 | output: 28 | no-notifications: Okunmamış bildiriminiz yok. 29 | notification: "> 30 | description: Web sitesi bildirimlerinin bir listesini görüntüler. 31 | register: 32 | description: Bir hesap oluşturur 33 | output: 34 | success: 35 | email: Kaydı tamamlamak için lütfen gelen kutunuzu kontrol edin. 36 | link: ">Lütfen 37 | kayıt sürecini tamamlamak için adresine gidiniz. 38 | fail: 39 | email-used: Bu e-posta adresi zaten farklı bir kullanıcı hesabı için kullanılıyor. 40 | email-invalid: Girdiğiniz e-posta adresi geçersiz. 41 | username-invalid: Sağlanan kullanıcı adı geçersiz. 42 | cannot-send-email: Kayıt e-postası gönderilemiyor, hesabınızı etkinleştirmek 43 | için lütfen bir yöneticiyle iletişime geçin. 44 | usage: '/{command} ' 45 | report: 46 | description: Bir oyuncuyu rapor et 47 | usage: '/{command} ' 48 | output: 49 | success: Bu oyuncuyu bildirdiğiniz için teşekkür ederiz. 50 | fail: 51 | already-open: Bu oyuncuyu şikayet edemezsiniz, onlar için zaten açık bir raporunuz 52 | var. 53 | report-self: Kendi kendini şikayet edemezsin. 54 | subcommands: {} 55 | not-a-player: Bu komutu gerçekleştirmek için oyuncu olmalısınız. 56 | player: 57 | other: {} 58 | self: 59 | not-registered: Bu eylemi gerçekleştirmek için bir hesap açmalısınız. 60 | command-banned: Bu komutu çalıştıramazsınız, siteden yasaklanırsınız. 61 | join-not-registered: Henüz web sitemizde bir hesabınız yok. Lütfen / register kullanarak 62 | kaydolun. 63 | website-announcement: 'Site duyurusu: ' 64 | user-sync-kick: Bu sunucuda uzaklaştırılmışsınız. 65 | error: 66 | website-username-not-exist: Bu kullanıcı adına sahip website kullanıcısı yok. 67 | discord-username-not-exist: Bu kullanıcı adına sahip Discord kullanıcısı yok. 68 | -------------------------------------------------------------------------------- /common/resources/languages/zh_CN.yaml: -------------------------------------------------------------------------------- 1 | player: 2 | other: {} 3 | self: 4 | not-registered: 您必须先注册一个帐号才能执行此操作。 5 | command-banned: 您已经被网站封禁,无法使用此指令。 6 | command: 7 | notifications: 8 | output: 9 | no-notifications: 您没有任何未读通知。 10 | notification: 11 | "> 12 | description: 显示网站通知列表。 13 | usage: '/' 14 | report: 15 | output: 16 | success: 感谢您举报此玩家。 17 | fail: 18 | already-open: 由于您已经有尚未处理的关于此玩家的举报,您无法举报此玩家。 19 | report-self: 您不能举报您自己。 20 | usage: '/ \<用户名/uuid> \<原因>' 21 | description: 举报 22 | user-info: 23 | output: 24 | registered-date: '注册时间: ' 25 | username: '用户名: ' 26 | displayname: '显示名: ' 27 | uuid: 'UUID: ' 28 | validated: '帐号是否已验证: ' 29 | banned: '是否被封禁: ' 30 | uuid-unknown: 'UUID: 未知' 31 | primary-group: 主要群组: 32 | all-groups: 全部群组: 33 | custom-field: "自定义字段 '': " 34 | integrations: 35 | identifier: 'ID: ' 36 | header: '集成:' 37 | username: '用户名: ' 38 | linked-date: '链接日期: ' 39 | verified: '已验证: ' 40 | usage: '/ [用户名]' 41 | description: 获得一个网站用户的信息 42 | not-a-player: 您必须是玩家才能执行此命令。 43 | no-permission: 您不能执行该指令,因为您没有该指令的权限 44 | register: 45 | usage: '/ \<用户名> \<邮箱>' 46 | output: 47 | success: 48 | email: 请查看您的收件箱来完成注册。 49 | link: 请前往 "> 50 | 完成注册. 51 | fail: 52 | email-used: 此邮箱已被另一个帐号使用了。 53 | email-invalid: 提供的邮箱地址无效。 54 | username-invalid: 提供的用户名无效。 55 | cannot-send-email: 无法发送注册邮件,请联系管理员来激活您的账户。 56 | username-used: 你的用户名已被使用. 57 | minecraft-used: 您的 Minecraft 帐户已关联到其他网站用户. 58 | custom-username-disabled: 不允许使用您的 Minecraft 用户名以外的用户名进行注册. 59 | console-must-specify-username: 从控制台运行注册命令时,必须指定用户名. 60 | description: 注册 61 | validate: 62 | usage: '/ \<验证码>' 63 | description: 使用给定的验证码来验证用户的网站帐号。 64 | output: 65 | success: 成功验证了您的帐号。 66 | fail: 67 | invalid-code: 您的验证码不正确。请检查您是否正确的拷贝了它,随后再试一次。 68 | already-validated: 您的账号已被验证过了。 69 | minecraft-account-linked: 此Minecraft帐户已链接到网站帐户. 70 | subcommands: {} 71 | plugin: 72 | description: NamelessMC 插件的管理命令 73 | output: 74 | reload-successful: 插件重载成功. 75 | usage: / '重新加载的指令是'/'rl'/'最后一个错误' 76 | store-change-credits: 77 | description: 为用户添加或删除商店积分 78 | output: 79 | nothing: 无需执行任何操作. 80 | store-view-credits: 81 | description: 查看商店积分 82 | output: 83 | no-permission-other: 您无权查看除您自己以外的玩家的积分. 84 | console-must-provide-target: 从控制台运行此命令时,必须提供目标玩家. 85 | suggest: 86 | description: 创建建议 87 | output: 88 | too-short: 提供的建议太短,请使用更多词语来描述您的建议. 89 | join-not-registered: 您在我们的网站上没有帐号。请使用 /register 来注册。 90 | website-announcement: '网站公告: ' 91 | user-sync-kick: 您因为网站账号被封禁而被在服务器上一并封禁。 92 | error: 93 | website-username-not-exist: 网站中没有此用户名 94 | website-connection: 试图连接到网站时发生了未知错误. 95 | username-not-online: 提供的玩家用户名无效或不在线. 96 | discord-username-not-exist: 没有可以使用的 Discord账户 97 | minecraft-uuid-not-exist: 没有用户存在这个Minecraft UUID。 98 | target-no-website-account: 提供的玩家没有网站帐户 99 | boolean: 100 | yes-positive: 101 | yes-negative: 102 | no-positive: 103 | no-negative: 104 | join-notifications: 您收到了网站通知,请运行 / 了解详情。 105 | -------------------------------------------------------------------------------- /common/resources/modules.yaml: -------------------------------------------------------------------------------- 1 | # Integration with Supercrafter100's Websend module. Do not enable if the 'Websend' module is not installed. 2 | websend: 3 | # Poll the Websend module for commands to execute 4 | command-executor: 5 | enabled: false 6 | interval: PT5S 7 | # Send server logs to the Websend module 8 | send-logs: 9 | enabled: false 10 | interval: PT2S 11 | 12 | # Integration with Partydragen's Store module. Do not enable if the 'Store' module is not installed. 13 | # Store module commands need to be enabled separately in commands.yaml 14 | store: 15 | # The connection id can be obtained from the store module in StaffCP 16 | connection-id: 0 17 | # Enable the command executor to periodically fetch pending commands from the Store module, and run them 18 | # in your Minecraft server. 19 | command-executor: 20 | enabled: false 21 | # Delay between fetching commands: https://en.wikipedia.org/wiki/ISO_8601#Durations 22 | interval: PT1M 23 | -------------------------------------------------------------------------------- /common/src/filtered/com/namelessmc/plugin/common/MavenConstants.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common; 2 | 3 | public class MavenConstants { 4 | 5 | public static final String PROJECT_VERSION = "${project.version}"; 6 | 7 | } 8 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/AbstractPermissions.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common; 2 | 3 | import com.google.gson.JsonArray; 4 | import com.google.gson.JsonObject; 5 | import com.google.gson.JsonPrimitive; 6 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 7 | import org.checkerframework.checker.nullness.qual.NonNull; 8 | import org.checkerframework.checker.nullness.qual.Nullable; 9 | 10 | import java.util.Collection; 11 | import java.util.Set; 12 | 13 | public abstract class AbstractPermissions 14 | implements AbstractDataSender.InfoProvider, AbstractDataSender.PlayerInfoProvider, Reloadable { 15 | 16 | public abstract boolean isUsable(); 17 | 18 | public abstract Set getGroups(); 19 | 20 | public abstract @Nullable Set getPlayerGroups(final @NonNull NamelessPlayer player); 21 | 22 | private @NonNull JsonArray toJsonArray(final @NonNull Collection coll) { 23 | final JsonArray json = new JsonArray(coll.size()); 24 | coll.stream().map(JsonPrimitive::new).forEach(json::add); 25 | return json; 26 | } 27 | 28 | @Override 29 | public void addInfoToJson(@NonNull JsonObject json) { 30 | json.add("groups", this.toJsonArray(this.getGroups())); 31 | } 32 | 33 | @Override 34 | public void addInfoToJson(@NonNull JsonObject json, @NonNull NamelessPlayer player) { 35 | final Collection groups = this.getPlayerGroups(player); 36 | if (groups != null) { 37 | json.add("groups", this.toJsonArray(groups)); 38 | } 39 | } 40 | 41 | protected class ProviderNotUsableException extends IllegalStateException { 42 | 43 | private static final long serialVersionUID = 1L; 44 | 45 | public ProviderNotUsableException() { 46 | super("Provider was called un unusable state"); 47 | } 48 | 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/AnnouncementTask.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common; 2 | 3 | import com.namelessmc.java_api.Announcement; 4 | import com.namelessmc.java_api.NamelessAPI; 5 | import com.namelessmc.java_api.exception.NamelessException; 6 | import com.namelessmc.java_api.NamelessUser; 7 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 8 | import com.namelessmc.plugin.common.command.AbstractScheduledTask; 9 | import net.kyori.adventure.text.Component; 10 | import org.checkerframework.checker.nullness.qual.NonNull; 11 | import org.checkerframework.checker.nullness.qual.Nullable; 12 | import org.spongepowered.configurate.CommentedConfigurationNode; 13 | import xyz.derkades.derkutils.ListUtils; 14 | 15 | import java.time.Duration; 16 | import java.util.List; 17 | import java.util.stream.Collectors; 18 | 19 | import static com.namelessmc.plugin.common.LanguageHandler.Term.WEBSITE_ANNOUNCEMENT; 20 | 21 | public class AnnouncementTask implements Runnable, Reloadable { 22 | 23 | private final @NonNull NamelessPlugin plugin; 24 | 25 | private @Nullable AbstractScheduledTask task; 26 | 27 | AnnouncementTask(final @NonNull NamelessPlugin plugin) { 28 | this.plugin = plugin; 29 | } 30 | 31 | @Override 32 | public void unload() { 33 | if (task != null) { 34 | task.cancel(); 35 | task = null; 36 | } 37 | } 38 | 39 | @Override 40 | public void load() { 41 | final CommentedConfigurationNode config = this.plugin.config().main().node("announcements"); 42 | if (config.node("enabled").getBoolean()) { 43 | final Duration interval = ConfigurationHandler.getDuration(config.node("interval")); 44 | if (interval != null) { 45 | this.task = this.plugin.scheduler().runTimer(this, interval); 46 | } else { 47 | this.plugin.logger().warning("Invalid announcements interval"); 48 | } 49 | } 50 | } 51 | 52 | @Override 53 | public void run() { 54 | final CommentedConfigurationNode config = this.plugin.config().main().node("announcements"); 55 | final NamelessAPI api = this.plugin.apiProvider().api(); 56 | if (api == null) { 57 | return; 58 | } 59 | final @Nullable String filterDisplay = config.node("display").getString(); 60 | Duration delay = Duration.ZERO; 61 | for (final NamelessPlayer player : this.plugin.audiences().onlinePlayers()) { 62 | // add delay so requests are spread out a bit 63 | this.plugin.scheduler().runDelayed(() -> { 64 | this.plugin.scheduler().runAsync(() -> { 65 | List announcements; 66 | try { 67 | final NamelessUser user = api.userByMinecraftUuid(player.uuid()); 68 | if (user != null) { 69 | announcements = user.announcements(); 70 | } else { 71 | announcements = api.announcements(); 72 | } 73 | } catch (NamelessException e) { 74 | this.plugin.logger().logException(e); 75 | return; 76 | } 77 | if (filterDisplay != null) { 78 | announcements = announcements.stream().filter(a -> a.displayedPages().contains(filterDisplay)).collect(Collectors.toList()); 79 | } 80 | if (!announcements.isEmpty()) { 81 | Announcement announcement = ListUtils.choice(announcements); 82 | String announcementMessage = announcement.message(); 83 | this.plugin.scheduler().runSync(() -> { 84 | final NamelessPlayer player2 = this.plugin.audiences().player(player.uuid()); 85 | if (player2 == null) { 86 | // Player left 87 | return; 88 | } 89 | final Component message = this.plugin.language().get( 90 | WEBSITE_ANNOUNCEMENT, "message", announcementMessage); 91 | player2.sendMessage(message); 92 | }); 93 | } 94 | }); 95 | }, delay); 96 | delay = delay.plusMillis(250); // 4 requests per second 97 | } 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/ConfigurationHandler.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common; 2 | 3 | import com.namelessmc.plugin.common.logger.AbstractLogger; 4 | import org.checkerframework.checker.nullness.qual.NonNull; 5 | import org.checkerframework.checker.nullness.qual.Nullable; 6 | import org.spongepowered.configurate.CommentedConfigurationNode; 7 | import org.spongepowered.configurate.ConfigurationNode; 8 | import org.spongepowered.configurate.yaml.YamlConfigurationLoader; 9 | import xyz.derkades.derkutils.FileUtils; 10 | 11 | import java.io.IOException; 12 | import java.nio.file.Files; 13 | import java.nio.file.Path; 14 | import java.time.Duration; 15 | import java.time.format.DateTimeParseException; 16 | import java.util.HashMap; 17 | import java.util.Map; 18 | 19 | public class ConfigurationHandler implements Reloadable { 20 | 21 | private static final @NonNull String[] ALL_CONFIG_NAMES = { 22 | "commands", 23 | "main", 24 | "modules", 25 | }; 26 | 27 | private final @NonNull Path dataDirectory; 28 | private final @NonNull Map configs = new HashMap<>(); 29 | 30 | public ConfigurationHandler(final @NonNull Path dataDirectory) { 31 | this.dataDirectory = dataDirectory; 32 | } 33 | 34 | public @NonNull CommentedConfigurationNode commands() { 35 | return this.getConfig("commands"); 36 | } 37 | 38 | public @NonNull CommentedConfigurationNode main() { 39 | return this.getConfig("main"); 40 | } 41 | 42 | public @NonNull CommentedConfigurationNode modules() { 43 | return this.getConfig("modules"); 44 | } 45 | 46 | private @NonNull CommentedConfigurationNode getConfig(final String name) { 47 | final CommentedConfigurationNode config = this.configs.get(name); 48 | if (config == null) { 49 | throw new IllegalStateException(name + " config requested before it was loaded"); 50 | } 51 | return config; 52 | } 53 | 54 | @Override 55 | public void unload() { 56 | 57 | } 58 | 59 | @Override 60 | public void load() { 61 | if (Files.exists(this.dataDirectory.resolve("config.yml"))) { 62 | throw new RuntimeException("Plugin directory contains config.yml. This is an old config file from the 2.x.x plugin versions. Please delete the plugin configuration directory or move it elsewhere to get new configuration files."); 63 | } 64 | 65 | try { 66 | Files.createDirectories(dataDirectory); 67 | for (final String configName : ALL_CONFIG_NAMES) { 68 | this.configs.put(configName, copyFromJarAndLoad(configName + ".yaml")); 69 | } 70 | } catch (final IOException e) { 71 | throw new RuntimeException(e); 72 | } 73 | } 74 | 75 | public void postLoadChecks(AbstractLogger logger) { 76 | 77 | } 78 | 79 | private CommentedConfigurationNode copyFromJarAndLoad(final @NonNull String name) throws IOException { 80 | Path path = dataDirectory.resolve(name); 81 | FileUtils.copyOutOfJar(ConfigurationHandler.class, name, path); 82 | return YamlConfigurationLoader.builder().path(path).build().load(); 83 | } 84 | 85 | public static @Nullable Duration getDuration(final ConfigurationNode node) { 86 | String string = node.getString(); 87 | if (string == null) { 88 | return null; 89 | } 90 | try { 91 | return Duration.parse(string); 92 | } catch (final DateTimeParseException e) { 93 | return null; 94 | } 95 | } 96 | 97 | public static class PostLoadChecker implements Reloadable { 98 | 99 | private final ConfigurationHandler config; 100 | private final AbstractLogger logger; 101 | 102 | public PostLoadChecker(final ConfigurationHandler config, final AbstractLogger logger) { 103 | this.config = config; 104 | this.logger = logger; 105 | } 106 | 107 | @Override 108 | public void unload() { 109 | 110 | } 111 | 112 | @Override 113 | public void load() { 114 | if (!this.config.main().hasChild("api", "server-id")) { 115 | this.logger.warning("Your config file is missing the server-id option. If you upgraded from an older plugin version, it is recommended to delete main.yaml to let the plugin generate an up-to-date file."); 116 | } 117 | } 118 | } 119 | 120 | } 121 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/DateFormatter.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common; 2 | 3 | import org.checkerframework.checker.nullness.qual.Nullable; 4 | 5 | import java.text.DateFormat; 6 | import java.text.SimpleDateFormat; 7 | import java.util.Date; 8 | 9 | public class DateFormatter implements Reloadable { 10 | 11 | private final ConfigurationHandler config; 12 | 13 | private @Nullable DateFormat formatter; 14 | 15 | DateFormatter(final ConfigurationHandler config) { 16 | this.config = config; 17 | } 18 | 19 | @Override 20 | public void unload() { 21 | this.formatter = null; 22 | } 23 | 24 | @Override 25 | public void load() { 26 | final String format = config.main().node("datetime-format").getString(); 27 | if (format != null) { 28 | this.formatter = new SimpleDateFormat(format); 29 | } else { 30 | this.formatter = new SimpleDateFormat(); 31 | } 32 | } 33 | 34 | public String format(final Date date) { 35 | if (this.formatter == null) { 36 | throw new IllegalStateException("Cannot format dates before DateFormatter is initialized"); 37 | } 38 | return formatter.format(date); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/JoinNotRegisteredMessage.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common; 2 | 3 | import com.namelessmc.java_api.NamelessAPI; 4 | import com.namelessmc.java_api.exception.NamelessException; 5 | import com.namelessmc.java_api.NamelessUser; 6 | import com.namelessmc.plugin.common.event.NamelessJoinEvent; 7 | import net.kyori.adventure.audience.Audience; 8 | import net.kyori.adventure.text.Component; 9 | import net.kyori.event.EventSubscription; 10 | import org.checkerframework.checker.nullness.qual.NonNull; 11 | import org.checkerframework.checker.nullness.qual.Nullable; 12 | import org.spongepowered.configurate.ConfigurationNode; 13 | 14 | import java.util.UUID; 15 | 16 | import static com.namelessmc.plugin.common.LanguageHandler.Term.JOIN_NOT_REGISTERED; 17 | 18 | public class JoinNotRegisteredMessage implements Reloadable { 19 | 20 | private final @NonNull NamelessPlugin plugin; 21 | 22 | private @Nullable EventSubscription subscription; 23 | private @Nullable String registerCommand; 24 | 25 | JoinNotRegisteredMessage(final @NonNull NamelessPlugin plugin) { 26 | this.plugin = plugin; 27 | } 28 | 29 | @Override 30 | public void unload() { 31 | if (subscription != null) { 32 | subscription.unsubscribe(); 33 | subscription = null; 34 | } 35 | } 36 | 37 | @Override 38 | public void load() { 39 | 40 | final ConfigurationNode conf = this.plugin.config().main(); 41 | 42 | if (!conf.node("not-registered-join-message").getBoolean()) { 43 | return; 44 | } 45 | 46 | ConfigurationNode commands = this.plugin.config().commands(); 47 | if (!commands.hasChild("register")) { 48 | this.plugin.logger().warning("not-registered-join-message is enabled, but the register command is disabled"); 49 | return; 50 | } 51 | 52 | this.registerCommand = commands.node("register").getString(); 53 | 54 | this.subscription = this.plugin.events().subscribe(NamelessJoinEvent.class, event -> 55 | onJoin(event.player().uuid())); 56 | } 57 | 58 | private void onJoin(final @NonNull UUID uuid) { 59 | String registerCommand = this.registerCommand; 60 | if (registerCommand == null) { 61 | throw new IllegalStateException("Register command cannot be null"); 62 | } 63 | 64 | this.plugin.scheduler().runAsync(() -> { 65 | final NamelessAPI api = this.plugin.apiProvider().api(); 66 | if (api == null) { 67 | return; 68 | } 69 | 70 | NamelessUser user; 71 | try { 72 | user = api.userByMinecraftUuid(uuid); 73 | } catch (final NamelessException e) { 74 | this.plugin.logger().logException(e); 75 | return; 76 | } 77 | 78 | if (user == null) { 79 | this.plugin.scheduler().runSync(() -> { 80 | Audience audience = this.plugin.audiences().player(uuid); 81 | if (audience != null) { 82 | final Component message = this.plugin.language().get(JOIN_NOT_REGISTERED, 83 | "register_command", registerCommand); 84 | audience.sendMessage(message); 85 | } 86 | }); 87 | } 88 | }); 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/JoinNotificationsMessage.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common; 2 | 3 | import com.namelessmc.java_api.NamelessAPI; 4 | import com.namelessmc.java_api.exception.NamelessException; 5 | import com.namelessmc.java_api.NamelessUser; 6 | import com.namelessmc.plugin.common.event.NamelessJoinEvent; 7 | import net.kyori.adventure.audience.Audience; 8 | import net.kyori.adventure.text.Component; 9 | import net.kyori.event.EventSubscription; 10 | import org.checkerframework.checker.nullness.qual.NonNull; 11 | import org.checkerframework.checker.nullness.qual.Nullable; 12 | 13 | import java.util.UUID; 14 | 15 | import static com.namelessmc.plugin.common.LanguageHandler.Term.JOIN_NOTIFICATIONS; 16 | 17 | public class JoinNotificationsMessage implements Reloadable { 18 | 19 | private final @NonNull NamelessPlugin plugin; 20 | 21 | private @Nullable EventSubscription subscription; 22 | 23 | JoinNotificationsMessage(final @NonNull NamelessPlugin plugin) { 24 | this.plugin = plugin; 25 | } 26 | 27 | @Override 28 | public void unload() { 29 | if (this.subscription != null) { 30 | this.subscription.unsubscribe(); 31 | this.subscription = null; 32 | } 33 | } 34 | 35 | @Override 36 | public void load() { 37 | if (this.plugin.config().main().node("join-notifications").getBoolean()) { 38 | this.subscription = this.plugin.events().subscribe(NamelessJoinEvent.class, event -> 39 | onJoin(event.player().uuid())); 40 | } 41 | } 42 | 43 | private void onJoin(final @NonNull UUID uuid) { 44 | this.plugin.scheduler().runAsync(() -> { 45 | final NamelessAPI api = this.plugin.apiProvider().api(); 46 | if (api == null) { 47 | return; 48 | } 49 | try { 50 | final NamelessUser user = api.userByMinecraftUuid(uuid); 51 | if (user == null) { 52 | return; 53 | } 54 | 55 | int notifications = user.notificationCount(); 56 | if (notifications == 0) { 57 | return; 58 | } 59 | 60 | this.plugin.scheduler().runSync(() -> { 61 | final String notificationsCommand = this.plugin.config().commands() 62 | .node("get-notifications").getString(); 63 | if (notificationsCommand == null) { 64 | this.plugin.logger().warning("Notifications command must be enabled for join-notifications feature"); 65 | return; 66 | } 67 | 68 | final Audience audience = this.plugin.audiences().player(uuid); 69 | 70 | if (audience == null) { 71 | this.plugin.logger().warning("Player left before we were able to send notifications message"); 72 | return; 73 | } 74 | 75 | final Component message = this.plugin.language() 76 | .get(JOIN_NOTIFICATIONS, "notifications_command", notificationsCommand); 77 | audience.sendMessage(message); 78 | }); 79 | 80 | } catch (final NamelessException e) { 81 | this.plugin.logger().logException(e); 82 | } 83 | }); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/LuckPermsPermissions.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common; 2 | 3 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 4 | import net.luckperms.api.LuckPerms; 5 | import net.luckperms.api.LuckPermsProvider; 6 | import net.luckperms.api.model.group.Group; 7 | import net.luckperms.api.model.user.User; 8 | import net.luckperms.api.node.NodeType; 9 | import net.luckperms.api.node.types.InheritanceNode; 10 | import org.checkerframework.checker.nullness.qual.Nullable; 11 | 12 | import java.util.Set; 13 | import java.util.stream.Collectors; 14 | 15 | public class LuckPermsPermissions extends AbstractPermissions { 16 | 17 | private @Nullable LuckPerms api; 18 | 19 | @Override 20 | public void unload() { 21 | this.api = null; 22 | } 23 | 24 | @Override 25 | public void load() { 26 | try { 27 | this.api = LuckPermsProvider.get(); 28 | } catch (IllegalStateException | NoClassDefFoundError e) {} 29 | } 30 | 31 | @Override 32 | public boolean isUsable() { 33 | return this.api != null; 34 | } 35 | 36 | @Override 37 | public Set getGroups() { 38 | if (this.api == null) { 39 | throw new ProviderNotUsableException(); 40 | } 41 | return this.api.getGroupManager().getLoadedGroups().stream() 42 | .map(Group::getName) 43 | .collect(Collectors.toUnmodifiableSet()); 44 | } 45 | 46 | @Override 47 | public @Nullable Set getPlayerGroups(NamelessPlayer player) { 48 | if (this.api == null) { 49 | throw new ProviderNotUsableException(); 50 | } 51 | final User user = this.api.getUserManager().getUser(player.uuid()); 52 | if (user == null) { 53 | return null; 54 | } 55 | return user.getNodes().stream() 56 | .filter(NodeType.INHERITANCE::matches) 57 | .map(NodeType.INHERITANCE::cast) 58 | .map(InheritanceNode::getGroupName) 59 | .collect(Collectors.toSet()); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/Permission.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common; 2 | 3 | import org.checkerframework.checker.nullness.qual.NonNull; 4 | 5 | public enum Permission { 6 | 7 | COMMAND_GET_NOTIFICATIONS("namelessmc.command.getnotifications"), 8 | COMMAND_REGISTER("namelessmc.command.register"), 9 | COMMAND_REPORT("namelessmc.command.report"), 10 | COMMAND_REPORT_NOTIFY_BROADCAST("namelessmc.report.notify-broadcast"), 11 | COMMAND_STORE_CHANGE_CREDITS("namelessmc.command.store-change-credits"), 12 | COMMAND_STORE_VIEW_CREDITS("namelessmc.command.store-view-credits"), 13 | COMMAND_STORE_VIEW_CREDITS_OTHERS("namelessmc.command.store-view-credits.others"), 14 | COMMAND_SET_GROUP("namelessmc.command.setgroup"), 15 | COMMAND_SUGGEST("namelessmc.command.suggest"), 16 | COMMAND_USER_INFO("namelessmc.command.userinfo"), 17 | COMMAND_VERIFY("namelessmc.command.verify"), 18 | 19 | COMMAND_PLUGIN("namelessmc.command.nameless"), 20 | 21 | ; 22 | 23 | private final @NonNull String permissionString; 24 | 25 | Permission(final @NonNull String permissionString){ 26 | this.permissionString = permissionString; 27 | } 28 | 29 | @Override 30 | public @NonNull String toString() { 31 | return this.permissionString; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/Reloadable.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common; 2 | 3 | public interface Reloadable { 4 | 5 | void unload(); 6 | 7 | void load(); 8 | 9 | public static enum Order { 10 | 11 | FIRST, NORMAL, LAST; 12 | 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/SyncBanToWebsite.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common; 2 | 3 | import com.namelessmc.java_api.NamelessAPI; 4 | import com.namelessmc.java_api.exception.NamelessException; 5 | import com.namelessmc.java_api.NamelessUser; 6 | import com.namelessmc.plugin.common.event.NamelessPlayerBanEvent; 7 | import net.kyori.event.EventSubscription; 8 | import org.checkerframework.checker.nullness.qual.Nullable; 9 | 10 | import java.util.UUID; 11 | 12 | public class SyncBanToWebsite implements Reloadable { 13 | 14 | private final NamelessPlugin plugin; 15 | 16 | private @Nullable EventSubscription subscription; 17 | 18 | SyncBanToWebsite(final NamelessPlugin plugin) { 19 | this.plugin = plugin; 20 | } 21 | 22 | @Override 23 | public void unload() { 24 | if (this.subscription != null) { 25 | this.subscription.unsubscribe(); 26 | this.subscription = null; 27 | } 28 | } 29 | 30 | @Override 31 | public void load() { 32 | if (!this.plugin.config().main().node("sync-ban-to-website").getBoolean()) { 33 | return; 34 | } 35 | 36 | this.plugin.events().subscribe(NamelessPlayerBanEvent.class, event -> { 37 | final UUID uuid = event.uuid(); 38 | 39 | this.plugin.scheduler().runAsync(() -> { 40 | final NamelessAPI api = this.plugin.apiProvider().api(); 41 | if (api == null) { 42 | this.plugin.logger().warning("Skipped trying to ban user, website connection is not working properly."); 43 | return; 44 | } 45 | 46 | try { 47 | final NamelessUser user = api.userByMinecraftUuid(uuid); 48 | if (user != null) { 49 | if (user.isBanned()) { 50 | this.plugin.logger().info("User " + user.username() + " is already banned"); 51 | } else { 52 | user.banUser(); 53 | this.plugin.logger().info("Banned user on website"); 54 | } 55 | } 56 | } catch (final NamelessException e) { 57 | this.plugin.logger().warning("Failed to ban player on website"); 58 | this.plugin.logger().logException(e); 59 | } 60 | }); 61 | }); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/UserCache.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common; 2 | 3 | import com.namelessmc.java_api.NamelessAPI; 4 | import com.namelessmc.java_api.NamelessUser; 5 | import com.namelessmc.java_api.exception.NamelessException; 6 | import com.namelessmc.plugin.common.command.AbstractScheduledTask; 7 | import org.checkerframework.checker.nullness.qual.Nullable; 8 | 9 | import java.time.Duration; 10 | import java.util.ArrayList; 11 | import java.util.Collection; 12 | import java.util.Collections; 13 | import java.util.List; 14 | import java.util.stream.Collectors; 15 | 16 | public class UserCache implements Reloadable { 17 | 18 | private final NamelessPlugin plugin; 19 | 20 | private @Nullable AbstractScheduledTask task; 21 | private List usernames = Collections.emptyList(); 22 | private List minecraftUsernames = Collections.emptyList(); 23 | 24 | UserCache(final NamelessPlugin plugin) { 25 | this.plugin = plugin; 26 | } 27 | 28 | @Override 29 | public void unload() { 30 | if (this.task != null) { 31 | this.task.cancel(); 32 | this.task = null; 33 | } 34 | this.usernames = Collections.emptyList(); 35 | } 36 | 37 | @Override 38 | public void load() { 39 | task = this.plugin.scheduler().runTimer(this::update, Duration.ofMinutes(5)); 40 | } 41 | 42 | private void update() { 43 | this.plugin.scheduler().runAsync(() -> { 44 | this.plugin.logger().fine("Refreshing user cache"); 45 | final NamelessAPI api = this.plugin.apiProvider().api(); 46 | if (api == null) { 47 | return; 48 | } 49 | 50 | try { 51 | final List users = api.users().makeRequest(); 52 | 53 | final List usernames = new ArrayList<>(users.size()); 54 | final List minecraftUsernames = new ArrayList<>(users.size()); 55 | 56 | for (NamelessUser user : users) { 57 | usernames.add(user.username()); 58 | if (user.minecraftUsername() != null) { 59 | minecraftUsernames.add(user.minecraftUsername()); 60 | } 61 | } 62 | 63 | this.usernames = usernames; 64 | this.minecraftUsernames = minecraftUsernames; 65 | } catch (NamelessException e) { 66 | this.plugin.logger().logException(e); 67 | } 68 | }); 69 | } 70 | 71 | private List search(Collection original, @Nullable String part) { 72 | if (part == null) { 73 | return Collections.emptyList(); 74 | } 75 | return original.stream().filter(s -> s.startsWith(part)).collect(Collectors.toUnmodifiableList()); 76 | } 77 | 78 | public List usernames() { 79 | return this.usernames; 80 | } 81 | 82 | public List usernamesSearch(@Nullable String part) { 83 | return this.search(this.usernames, part); 84 | } 85 | 86 | public List minecraftUsernames() { 87 | return this.minecraftUsernames; 88 | } 89 | 90 | public List minecraftUsernamesSearch(@Nullable String part) { 91 | return this.search(this.minecraftUsernames, part); 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/audiences/AbstractAudienceProvider.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common.audiences; 2 | 3 | import net.kyori.adventure.audience.Audience; 4 | import org.checkerframework.checker.nullness.qual.NonNull; 5 | import org.checkerframework.checker.nullness.qual.Nullable; 6 | 7 | import java.util.Collection; 8 | import java.util.UUID; 9 | 10 | public abstract class AbstractAudienceProvider { 11 | 12 | public abstract @NonNull NamelessConsole console(); 13 | 14 | public abstract @NonNull Audience broadcast(); 15 | 16 | public abstract @Nullable NamelessPlayer player(final @NonNull UUID uuid); 17 | 18 | public abstract @Nullable NamelessPlayer playerByUsername(final @NonNull String username); 19 | 20 | public abstract @NonNull Collection<@NonNull NamelessPlayer> onlinePlayers(); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/audiences/NamelessCommandSender.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common.audiences; 2 | 3 | import com.namelessmc.plugin.common.Permission; 4 | import net.kyori.adventure.audience.Audience; 5 | import net.kyori.adventure.audience.MessageType; 6 | import net.kyori.adventure.identity.Identity; 7 | import net.kyori.adventure.text.Component; 8 | import org.checkerframework.checker.nullness.qual.NonNull; 9 | 10 | public abstract class NamelessCommandSender implements Audience { 11 | 12 | private final @NonNull Audience audience; 13 | 14 | public NamelessCommandSender(final @NonNull Audience audience) { 15 | this.audience = audience; 16 | } 17 | 18 | public abstract boolean hasPermission(Permission permission); 19 | 20 | @Override 21 | public void sendMessage(final @NonNull Identity source, 22 | final @NonNull Component message, 23 | final @NonNull MessageType type) { 24 | this.audience.sendMessage(source, message, type); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/audiences/NamelessConsole.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common.audiences; 2 | 3 | import com.namelessmc.plugin.common.Permission; 4 | import net.kyori.adventure.audience.Audience; 5 | 6 | public abstract class NamelessConsole extends NamelessCommandSender { 7 | 8 | public NamelessConsole(final Audience audience) { 9 | super(audience); 10 | } 11 | 12 | public abstract void dispatchCommand(String command); 13 | 14 | @Override 15 | public boolean hasPermission(Permission permission) { 16 | return true; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/audiences/NamelessPlayer.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common.audiences; 2 | 3 | import com.namelessmc.plugin.common.ConfigurationHandler; 4 | import net.kyori.adventure.audience.Audience; 5 | 6 | import java.nio.charset.StandardCharsets; 7 | import java.util.UUID; 8 | 9 | public abstract class NamelessPlayer extends NamelessCommandSender { 10 | 11 | private final UUID uuid; 12 | private final String username; 13 | 14 | public NamelessPlayer(final ConfigurationHandler config, 15 | final Audience audience, 16 | final UUID uuid, 17 | final String username) { 18 | super(audience); 19 | if (config.main().node("api", "offline-uuids").getBoolean()) { 20 | this.uuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" + username).getBytes(StandardCharsets.UTF_8)); 21 | } else { 22 | this.uuid = uuid; 23 | } 24 | this.username = username; 25 | } 26 | 27 | public UUID uuid() { 28 | return this.uuid; 29 | } 30 | 31 | public String username() { 32 | return this.username; 33 | } 34 | 35 | public boolean isVanished() { 36 | return false; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/command/AbstractScheduledTask.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common.command; 2 | 3 | public abstract class AbstractScheduledTask { 4 | 5 | public abstract void cancel(); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/command/AbstractScheduler.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common.command; 2 | 3 | import java.time.Duration; 4 | 5 | import org.checkerframework.checker.nullness.qual.NonNull; 6 | import org.checkerframework.checker.nullness.qual.Nullable; 7 | 8 | public abstract class AbstractScheduler { 9 | 10 | public abstract void runAsync(final @NonNull Runnable runnable); 11 | 12 | public abstract void runSync(final @NonNull Runnable runnable); 13 | 14 | public abstract @Nullable AbstractScheduledTask runTimer(final @NonNull Runnable runnable, final @NonNull Duration interval); 15 | 16 | public abstract @Nullable AbstractScheduledTask runDelayed(final @NonNull Runnable runnable, final @NonNull Duration delay); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/command/CommonCommand.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common.command; 2 | 3 | import com.namelessmc.plugin.common.ApiProvider; 4 | import com.namelessmc.plugin.common.LanguageHandler; 5 | import com.namelessmc.plugin.common.NamelessPlugin; 6 | import com.namelessmc.plugin.common.Permission; 7 | import com.namelessmc.plugin.common.audiences.NamelessCommandSender; 8 | import com.namelessmc.plugin.common.logger.AbstractLogger; 9 | import net.kyori.adventure.text.Component; 10 | import org.checkerframework.checker.initialization.qual.UnknownInitialization; 11 | import org.checkerframework.checker.nullness.qual.NonNull; 12 | import org.checkerframework.checker.nullness.qual.Nullable; 13 | import org.spongepowered.configurate.CommentedConfigurationNode; 14 | 15 | import java.util.Collections; 16 | import java.util.List; 17 | 18 | import static com.namelessmc.plugin.common.LanguageHandler.Term.COMMAND_NO_PERMISSION; 19 | 20 | public abstract class CommonCommand { 21 | 22 | private final @NonNull NamelessPlugin plugin; 23 | private final LanguageHandler.@NonNull Term usageTerm; 24 | private final LanguageHandler.@NonNull Term descriptionTerm; 25 | private final @NonNull Permission permission; 26 | private final @Nullable String actualName; 27 | 28 | public CommonCommand(final @NonNull NamelessPlugin plugin, 29 | final @NonNull String configName, 30 | final LanguageHandler.@NonNull Term usageTerm, 31 | final LanguageHandler.@NonNull Term descriptionTerm, 32 | final @NonNull Permission permission) { 33 | this.plugin = plugin; 34 | this.usageTerm = usageTerm; 35 | this.descriptionTerm = descriptionTerm; 36 | this.permission = permission; 37 | final CommentedConfigurationNode config = plugin.config().commands(); 38 | this.actualName = config.node(configName).getString(); 39 | } 40 | 41 | public @Nullable String actualName(@UnknownInitialization(CommonCommand.class) CommonCommand this) { 42 | return this.actualName; 43 | } 44 | 45 | public Component usage() { 46 | if (this.actualName == null) { 47 | throw new IllegalStateException("Cannot get usage for disabled command"); 48 | } 49 | return this.language().get(this.usageTerm, "command", this.actualName); 50 | } 51 | 52 | public Component description() { 53 | return this.language().get(this.descriptionTerm); 54 | } 55 | 56 | public @NonNull Permission permission() { 57 | return this.permission; 58 | } 59 | 60 | protected @NonNull NamelessPlugin plugin() { 61 | return this.plugin; 62 | } 63 | 64 | protected @NonNull AbstractScheduler scheduler() { 65 | return this.plugin.scheduler(); 66 | } 67 | 68 | protected @NonNull LanguageHandler language() { 69 | return this.plugin.language(); 70 | } 71 | 72 | protected @NonNull ApiProvider apiProvider() { 73 | return this.plugin.apiProvider(); 74 | } 75 | 76 | protected @NonNull AbstractLogger logger() { return this.plugin.logger(); } 77 | 78 | protected abstract void execute(final @NonNull NamelessCommandSender sender, final @NonNull String@NonNull[] args); 79 | 80 | public void verifyPermissionThenExecute(NamelessCommandSender sender, String[] args) { 81 | if (!sender.hasPermission(this.permission)) { 82 | sender.sendMessage(this.language().get(COMMAND_NO_PERMISSION)); 83 | return; 84 | } 85 | 86 | this.execute(sender, args); 87 | } 88 | 89 | public List complete(final @NonNull NamelessCommandSender sender, final @NonNull String@NonNull[] args) { 90 | return Collections.emptyList(); 91 | } 92 | 93 | public static List commands(final @NonNull NamelessPlugin plugin) { 94 | return List.of( 95 | new GetNotificationsCommand(plugin), 96 | new NamelessPluginCommand(plugin), 97 | new RegisterCommand(plugin), 98 | new ReportCommand(plugin), 99 | new UserInfoCommand(plugin), 100 | new StoreChangeCreditsCommand(plugin), 101 | new StoreViewCreditsCommand(plugin), 102 | new SuggestCommand(plugin), 103 | new VerifyCommand(plugin) 104 | ); 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/command/GetNotificationsCommand.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common.command; 2 | 3 | import com.namelessmc.java_api.NamelessAPI; 4 | import com.namelessmc.java_api.exception.NamelessException; 5 | import com.namelessmc.java_api.NamelessUser; 6 | import com.namelessmc.java_api.Notification; 7 | import com.namelessmc.plugin.common.NamelessPlugin; 8 | import com.namelessmc.plugin.common.Permission; 9 | import com.namelessmc.plugin.common.audiences.NamelessCommandSender; 10 | import com.namelessmc.plugin.common.audiences.NamelessConsole; 11 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 12 | import org.checkerframework.checker.nullness.qual.NonNull; 13 | 14 | import java.util.List; 15 | import java.util.stream.Collectors; 16 | 17 | import static com.namelessmc.plugin.common.LanguageHandler.Term.*; 18 | 19 | public class GetNotificationsCommand extends CommonCommand { 20 | 21 | public GetNotificationsCommand(final @NonNull NamelessPlugin plugin) { 22 | super(plugin, 23 | "get-notifications", 24 | COMMAND_NOTIFICATIONS_USAGE, 25 | COMMAND_NOTIFICATIONS_DESCRIPTION, 26 | Permission.COMMAND_GET_NOTIFICATIONS); 27 | } 28 | 29 | @Override 30 | public void execute(final @NonNull NamelessCommandSender sender, final @NonNull String@NonNull[] args) { 31 | if (args.length != 0) { 32 | sender.sendMessage(this.usage()); 33 | return; 34 | } 35 | 36 | if (sender instanceof NamelessConsole) { 37 | sender.sendMessage(language().get(COMMAND_NOT_A_PLAYER)); 38 | return; 39 | } 40 | 41 | scheduler().runAsync(() -> { 42 | final NamelessAPI api = this.apiProvider().api(); 43 | if (api == null) { 44 | sender.sendMessage(language().get(ERROR_WEBSITE_CONNECTION)); 45 | return; 46 | } 47 | 48 | try { 49 | final NamelessUser user = api.userByMinecraftUuid(((NamelessPlayer) sender).uuid()); 50 | 51 | if (user == null) { 52 | sender.sendMessage(language().get(PLAYER_SELF_NOT_REGISTERED)); 53 | return; 54 | } 55 | 56 | final List notifications = user.notifications() 57 | .stream() 58 | .sorted((n1, n2) -> n2.type().ordinal() - n1.type().ordinal()) 59 | .collect(Collectors.toUnmodifiableList()); 60 | 61 | if (notifications.size() == 0) { 62 | sender.sendMessage(language().get(COMMAND_NOTIFICATIONS_OUTPUT_NO_NOTIFICATIONS)); 63 | return; 64 | } 65 | 66 | scheduler().runSync(() -> { 67 | notifications.forEach((notification) -> { 68 | sender.sendMessage(language().get(COMMAND_NOTIFICATIONS_OUTPUT_NOTIFICATION, 69 | "url", notification.url(), 70 | "message", notification.message())); 71 | }); 72 | }); 73 | } catch (final NamelessException e) { 74 | sender.sendMessage(language().get(ERROR_WEBSITE_CONNECTION)); 75 | logger().logException(e); 76 | } 77 | }); 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/command/NamelessPluginCommand.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common.command; 2 | 3 | import com.namelessmc.plugin.common.NamelessPlugin; 4 | import com.namelessmc.plugin.common.Permission; 5 | import com.namelessmc.plugin.common.audiences.NamelessCommandSender; 6 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 7 | import net.kyori.adventure.text.Component; 8 | import org.checkerframework.checker.nullness.qual.NonNull; 9 | 10 | import java.util.Arrays; 11 | import java.util.Collections; 12 | import java.util.List; 13 | import java.util.stream.Collectors; 14 | 15 | import static com.namelessmc.plugin.common.LanguageHandler.Term.*; 16 | 17 | public class NamelessPluginCommand extends CommonCommand { 18 | 19 | public NamelessPluginCommand(final @NonNull NamelessPlugin plugin) { 20 | super( 21 | plugin, 22 | "plugin", 23 | COMMAND_PLUGIN_USAGE, 24 | COMMAND_PLUGIN_DESCRIPTION, 25 | Permission.COMMAND_PLUGIN 26 | ); 27 | 28 | if (this.actualName() == null) { 29 | plugin.logger().warning("The commands config file is missing the plugin command"); 30 | } 31 | } 32 | 33 | @Override 34 | public void execute(final @NonNull NamelessCommandSender sender, final @NonNull String@NonNull[] args) { 35 | if (args.length == 1) { 36 | switch(args[0]) { 37 | case "reload": 38 | case "rl": 39 | this.plugin().unload(); 40 | this.plugin().load(); 41 | sender.sendMessage(this.language().get(COMMAND_PLUGIN_OUTPUT_RELOAD_SUCCESSFUL)); 42 | return; 43 | case "last_error": 44 | final String stackTrace = this.plugin().logger().getLastExceptionStackTrace(); 45 | if (stackTrace == null) { 46 | sender.sendMessage(Component.text("No error since last plugin reload.")); 47 | return; 48 | } 49 | 50 | this.plugin().logger().warning(stackTrace); 51 | 52 | if (sender instanceof NamelessPlayer) { 53 | sender.sendMessage(Component.text("Last error has been printed to the console")); 54 | } 55 | return; 56 | } 57 | } 58 | 59 | sender.sendMessage(this.usage()); 60 | } 61 | 62 | @Override 63 | public List complete(@NonNull NamelessCommandSender sender, @NonNull String @NonNull [] args) { 64 | if (args.length == 1) { 65 | return Arrays.stream(new String[]{"reload", "rl", "last_api_error"}).filter(s -> s.startsWith(args[0])).collect(Collectors.toList()); 66 | } 67 | return Collections.emptyList(); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/command/StoreChangeCreditsCommand.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common.command; 2 | 3 | import com.namelessmc.java_api.NamelessAPI; 4 | import com.namelessmc.java_api.NamelessUser; 5 | import com.namelessmc.java_api.exception.NamelessException; 6 | import com.namelessmc.plugin.common.NamelessPlugin; 7 | import com.namelessmc.plugin.common.Permission; 8 | import com.namelessmc.plugin.common.audiences.NamelessCommandSender; 9 | import org.checkerframework.checker.nullness.qual.NonNull; 10 | 11 | import java.util.Collections; 12 | import java.util.List; 13 | 14 | import static com.namelessmc.plugin.common.LanguageHandler.Term.*; 15 | import static com.namelessmc.plugin.common.LanguageHandler.Term.COMMAND_STORE_CHANGE_CREDITS_OUTPUT_REMOVED; 16 | 17 | public class StoreChangeCreditsCommand extends CommonCommand { 18 | 19 | public StoreChangeCreditsCommand(final @NonNull NamelessPlugin plugin) { 20 | super(plugin, 21 | "store-change-credits", 22 | COMMAND_STORE_CHANGE_CREDITS_USAGE, 23 | COMMAND_STORE_CHANGE_CREDITS_DESCRIPTION, 24 | Permission.COMMAND_STORE_CHANGE_CREDITS); 25 | } 26 | 27 | @Override 28 | public void execute(final NamelessCommandSender sender, final String[] args) { 29 | if (args.length != 2) { 30 | sender.sendMessage(this.usage()); 31 | return; 32 | } 33 | 34 | final int credits; 35 | try { 36 | try { 37 | credits = Integer.parseInt(args[1]); 38 | } catch (NumberFormatException ignored) { 39 | sender.sendMessage(this.usage()); 40 | return; 41 | } 42 | } catch (NumberFormatException e) { 43 | sender.sendMessage(this.usage()); 44 | return; 45 | } 46 | 47 | if (credits == 0) { 48 | sender.sendMessage(this.language().get(COMMAND_STORE_CHANGE_CREDITS_OUTPUT_NOTHING)); 49 | return; 50 | } 51 | 52 | this.plugin().scheduler().runAsync(() -> { 53 | final NamelessAPI api = this.apiProvider().api();; 54 | 55 | if (api == null) { 56 | this.scheduler().runSync(() -> sender.sendMessage(this.language().get(ERROR_WEBSITE_CONNECTION))); 57 | return; 58 | } 59 | 60 | try { 61 | final NamelessUser user = api.userByMinecraftUsername(args[0]); 62 | 63 | if (user == null) { 64 | this.scheduler().runSync(() -> sender.sendMessage(this.language().get(ERROR_TARGET_NO_WEBSITE_ACCOUNT))); 65 | return; 66 | } 67 | 68 | final String namelessUsername = user.username(); 69 | 70 | if (credits > 0) { 71 | user.store().addCredits(credits); 72 | sender.sendMessage(this.language().get(COMMAND_STORE_CHANGE_CREDITS_OUTPUT_ADDED, 73 | "credits", String.format("%.2f", credits / 100f), "username", namelessUsername)); 74 | } else if (credits < 0) { 75 | user.store().removeCredits(-credits); 76 | sender.sendMessage(this.language().get(COMMAND_STORE_CHANGE_CREDITS_OUTPUT_REMOVED, 77 | "credits", String.format("%.2f", -credits / 100f), "username", namelessUsername)); 78 | } else { 79 | throw new IllegalStateException(); 80 | } 81 | } catch (NamelessException e) { 82 | this.logger().logException(e); 83 | } 84 | }); 85 | 86 | } 87 | 88 | @Override 89 | public List complete(final NamelessCommandSender sender, final String[] args) { 90 | if (args.length == 1) { 91 | return this.plugin().userCache().minecraftUsernamesSearch(args[0]); 92 | } 93 | return Collections.emptyList(); 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/command/StoreViewCreditsCommand.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common.command; 2 | 3 | import com.namelessmc.java_api.NamelessAPI; 4 | import com.namelessmc.java_api.NamelessUser; 5 | import com.namelessmc.java_api.exception.NamelessException; 6 | import com.namelessmc.plugin.common.NamelessPlugin; 7 | import com.namelessmc.plugin.common.Permission; 8 | import com.namelessmc.plugin.common.audiences.NamelessCommandSender; 9 | import com.namelessmc.plugin.common.audiences.NamelessConsole; 10 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 11 | 12 | import java.util.Collections; 13 | import java.util.List; 14 | 15 | import static com.namelessmc.plugin.common.LanguageHandler.Term.*; 16 | 17 | public class StoreViewCreditsCommand extends CommonCommand { 18 | 19 | public StoreViewCreditsCommand(NamelessPlugin plugin) { 20 | super( 21 | plugin, 22 | "store-view-credits", 23 | COMMAND_STORE_VIEW_CREDITS_USAGE, 24 | COMMAND_STORE_VIEW_CREDITS_DESCRIPTION, 25 | Permission.COMMAND_STORE_VIEW_CREDITS 26 | ); 27 | } 28 | 29 | @Override 30 | public void execute(NamelessCommandSender sender, String[] args) { 31 | if (args.length > 1) { 32 | sender.sendMessage(this.usage()); 33 | return; 34 | } 35 | 36 | if (sender instanceof NamelessConsole && args.length == 0) { 37 | sender.sendMessage(this.language().get(COMMAND_STORE_VIEW_CREDITS_OUTPUT_CONSOLE_MUST_PROVIDE_TARGET)); 38 | return; 39 | } 40 | 41 | if (args.length == 1 && !sender.hasPermission(Permission.COMMAND_STORE_VIEW_CREDITS_OTHERS)) { 42 | sender.sendMessage(this.language().get(COMMAND_STORE_VIEW_CREDITS_OUTPUT_NO_PERMISSION_OTHER)); 43 | return; 44 | } 45 | 46 | this.scheduler().runAsync(() -> { 47 | try { 48 | NamelessAPI api = this.apiProvider().api(); 49 | if (api == null) { 50 | sender.sendMessage(this.language().get(ERROR_WEBSITE_CONNECTION)); 51 | return; 52 | } 53 | 54 | NamelessUser user; 55 | 56 | if (args.length == 1) { 57 | user = api.userByMinecraftUsername(args[0]); 58 | if (user == null) { 59 | sender.sendMessage(this.language().get(ERROR_TARGET_NO_WEBSITE_ACCOUNT)); 60 | return; 61 | } 62 | } else { 63 | user = api.userByMinecraftUuid(((NamelessPlayer) sender).uuid()); 64 | if (user == null) { 65 | sender.sendMessage(this.language().get(PLAYER_SELF_NOT_REGISTERED)); 66 | return; 67 | } 68 | } 69 | 70 | final String credits = user.store().creditsDisplay(); 71 | sender.sendMessage(this.language().get(COMMAND_STORE_VIEW_CREDITS_OUTPUT_CREDITS, 72 | "credits", credits)); 73 | } catch (NamelessException e) { 74 | sender.sendMessage(this.language().get(ERROR_WEBSITE_CONNECTION)); 75 | this.logger().logException(e); 76 | } 77 | }); 78 | } 79 | 80 | @Override 81 | public List complete(final NamelessCommandSender sender, final String[] args) { 82 | if (args.length == 1) { 83 | return this.plugin().userCache().minecraftUsernamesSearch(args[0]); 84 | } 85 | return Collections.emptyList(); 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/command/SuggestCommand.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common.command; 2 | 3 | import com.namelessmc.java_api.NamelessAPI; 4 | import com.namelessmc.java_api.NamelessUser; 5 | import com.namelessmc.java_api.exception.NamelessException; 6 | import com.namelessmc.java_api.modules.suggestions.Suggestion; 7 | import com.namelessmc.plugin.common.NamelessPlugin; 8 | import com.namelessmc.plugin.common.Permission; 9 | import com.namelessmc.plugin.common.audiences.NamelessCommandSender; 10 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 11 | 12 | import static com.namelessmc.plugin.common.LanguageHandler.Term.*; 13 | 14 | public class SuggestCommand extends CommonCommand { 15 | 16 | public SuggestCommand(NamelessPlugin plugin) { 17 | super( 18 | plugin, 19 | "suggest", 20 | COMMAND_SUGGEST_USAGE, 21 | COMMAND_SUGGEST_DESCRIPTION, 22 | Permission.COMMAND_SUGGEST 23 | ); 24 | } 25 | 26 | @Override 27 | protected void execute(NamelessCommandSender sender, String[] args) { 28 | final String suggestionTitle = String.join(" ", args); 29 | if (suggestionTitle.length() < 6) { 30 | sender.sendMessage(this.language().get(COMMAND_SUGGEST_OUTPUT_TOO_SHORT)); 31 | return; 32 | } 33 | 34 | NamelessAPI api = this.apiProvider().api(); 35 | 36 | if (api == null) { 37 | sender.sendMessage(this.language().get(ERROR_WEBSITE_CONNECTION)); 38 | return; 39 | } 40 | 41 | if (!(sender instanceof NamelessPlayer)) { 42 | sender.sendMessage(this.language().get(COMMAND_NOT_A_PLAYER)); 43 | return; 44 | } 45 | 46 | this.scheduler().runAsync(() -> { 47 | try { 48 | NamelessUser user = api.userByMinecraftUuid(((NamelessPlayer) sender).uuid()); 49 | if (user == null) { 50 | this.scheduler().runSync(() -> 51 | sender.sendMessage(this.language().get(PLAYER_SELF_NOT_REGISTERED))); 52 | return; 53 | } 54 | Suggestion suggestion = user.suggestions().createSuggestion(suggestionTitle, suggestionTitle); 55 | String url = suggestion.url().toString(); 56 | this.scheduler().runSync(() -> 57 | sender.sendMessage(this.language().get(COMMAND_SUGGEST_OUTPUT_SUCCESS, "url", url))); 58 | } catch (NamelessException e) { 59 | this.scheduler().runSync(() -> 60 | sender.sendMessage(this.language().get(ERROR_WEBSITE_CONNECTION))); 61 | } 62 | }); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/command/VerifyCommand.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common.command; 2 | 3 | import com.namelessmc.java_api.NamelessAPI; 4 | import com.namelessmc.java_api.exception.ApiException; 5 | import com.namelessmc.java_api.exception.NamelessException; 6 | import com.namelessmc.java_api.integrations.IntegrationData; 7 | import com.namelessmc.java_api.integrations.MinecraftIntegrationData; 8 | import com.namelessmc.plugin.common.NamelessPlugin; 9 | import com.namelessmc.plugin.common.Permission; 10 | import com.namelessmc.plugin.common.audiences.NamelessCommandSender; 11 | import com.namelessmc.plugin.common.audiences.NamelessConsole; 12 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 13 | import org.checkerframework.checker.nullness.qual.NonNull; 14 | 15 | import static com.namelessmc.plugin.common.LanguageHandler.Term.*; 16 | 17 | public class VerifyCommand extends CommonCommand { 18 | 19 | public VerifyCommand(final @NonNull NamelessPlugin plugin) { 20 | super(plugin, 21 | "verify", 22 | COMMAND_VALIDATE_USAGE, 23 | COMMAND_VALIDATE_DESCRIPTION, 24 | Permission.COMMAND_VERIFY); 25 | } 26 | 27 | @Override 28 | public void execute(final @NonNull NamelessCommandSender sender, final @NonNull String@NonNull[] args) { 29 | if (args.length != 1) { 30 | sender.sendMessage(this.usage()); 31 | return; 32 | } 33 | 34 | if (sender instanceof NamelessConsole) { 35 | sender.sendMessage(language().get(COMMAND_NOT_A_PLAYER)); 36 | return; 37 | } 38 | 39 | this.scheduler().runAsync(() -> { 40 | final NamelessAPI api = this.apiProvider().api(); 41 | if (api == null) { 42 | sender.sendMessage(language().get(ERROR_WEBSITE_CONNECTION)); 43 | return; 44 | } 45 | 46 | try { 47 | final String code = args[0]; 48 | final NamelessPlayer player = (NamelessPlayer) sender; 49 | final IntegrationData integrationData = new MinecraftIntegrationData(player.uuid(), player.username()); 50 | api.verifyIntegration(integrationData, code); 51 | sender.sendMessage(language().get(COMMAND_VALIDATE_OUTPUT_SUCCESS)); 52 | this.plugin().groupSync().resetGroups(player); 53 | } catch (ApiException e) { 54 | switch(e.apiError()) { 55 | case CORE_INVALID_CODE: 56 | sender.sendMessage(language().get(COMMAND_VALIDATE_OUTPUT_FAIL_INVALID_CODE)); 57 | return; 58 | case CORE_INTEGRATION_ALREADY_VERIFIED: 59 | sender.sendMessage(language().get(COMMAND_VALIDATE_OUTPUT_FAIL_ALREADY_VALIDATED)); 60 | return; 61 | case CORE_INTEGRATION_IDENTIFIER_ERROR: 62 | case CORE_INTEGRATION_USERNAME_ERROR: 63 | sender.sendMessage(language().get(COMMAND_VALIDATE_OUTPUT_FAIL_MINECRAFT_ACCOUNT_LINKED)); 64 | return; 65 | default: 66 | sender.sendMessage(language().get(ERROR_WEBSITE_CONNECTION)); 67 | logger().logException(e); 68 | } 69 | } catch (final NamelessException e) { 70 | sender.sendMessage(language().get(ERROR_WEBSITE_CONNECTION)); 71 | logger().logException(e); 72 | } 73 | }); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/event/NamelessEvent.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common.event; 2 | 3 | public class NamelessEvent { 4 | } 5 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/event/NamelessJoinEvent.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common.event; 2 | 3 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 4 | import org.checkerframework.checker.nullness.qual.NonNull; 5 | 6 | public class NamelessJoinEvent extends NamelessEvent { 7 | 8 | private final @NonNull NamelessPlayer player; 9 | 10 | public NamelessJoinEvent(final @NonNull NamelessPlayer player) { 11 | this.player = player; 12 | } 13 | 14 | public @NonNull NamelessPlayer player() { 15 | return this.player; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/event/NamelessOfflinePlayerEvent.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common.event; 2 | 3 | import org.checkerframework.checker.nullness.qual.NonNull; 4 | 5 | import java.util.UUID; 6 | 7 | public class NamelessOfflinePlayerEvent extends NamelessEvent { 8 | 9 | private final @NonNull UUID uuid; 10 | 11 | public NamelessOfflinePlayerEvent(final @NonNull UUID uuid) { 12 | this.uuid = uuid; 13 | } 14 | 15 | public @NonNull UUID uuid() { 16 | return this.uuid; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/event/NamelessPlayerBanEvent.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common.event; 2 | 3 | import org.checkerframework.checker.nullness.qual.NonNull; 4 | 5 | import java.util.UUID; 6 | 7 | public class NamelessPlayerBanEvent extends NamelessOfflinePlayerEvent { 8 | 9 | public NamelessPlayerBanEvent(final @NonNull UUID uuid) { 10 | super(uuid); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/event/NamelessPlayerEvent.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common.event; 2 | 3 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 4 | import org.checkerframework.checker.nullness.qual.NonNull; 5 | 6 | public class NamelessPlayerEvent extends NamelessOfflinePlayerEvent { 7 | 8 | private final @NonNull NamelessPlayer player; 9 | 10 | public NamelessPlayerEvent(final @NonNull NamelessPlayer player) { 11 | super(player.uuid()); 12 | this.player = player; 13 | } 14 | 15 | public @NonNull NamelessPlayer player() { 16 | return this.player; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/event/NamelessPlayerQuitEvent.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common.event; 2 | 3 | import org.checkerframework.checker.nullness.qual.NonNull; 4 | 5 | import java.util.UUID; 6 | 7 | public class NamelessPlayerQuitEvent extends NamelessOfflinePlayerEvent { 8 | 9 | public NamelessPlayerQuitEvent(final @NonNull UUID uuid) { 10 | super(uuid); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /common/src/main/com/namelessmc/plugin/common/logger/JulLogger.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.common.logger; 2 | 3 | import com.namelessmc.plugin.common.ConfigurationHandler; 4 | import org.checkerframework.checker.nullness.qual.NonNull; 5 | 6 | import java.util.function.Supplier; 7 | import java.util.logging.Logger; 8 | 9 | public class JulLogger extends AbstractLogger { 10 | 11 | private final @NonNull Logger logger; 12 | 13 | public JulLogger(final @NonNull ConfigurationHandler config, 14 | final @NonNull Logger logger) { 15 | super(config); 16 | this.logger = logger; 17 | } 18 | 19 | @Override 20 | public void info(String string) { 21 | this.logger.info(string); 22 | } 23 | 24 | @Override 25 | public void warning(String string) { 26 | this.logger.warning(string); 27 | } 28 | 29 | @Override 30 | public void severe(String string) { 31 | this.logger.severe(string); 32 | } 33 | 34 | @Override 35 | public void info(Supplier stringSupplier) { 36 | this.logger.info(stringSupplier); 37 | } 38 | 39 | @Override 40 | public void warning(Supplier stringSupplier) { 41 | this.logger.warning(stringSupplier); 42 | } 43 | 44 | @Override 45 | public void severe(Supplier stringSupplier) { 46 | this.logger.severe(stringSupplier); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /common/src/test/java/LanguageHandlerTest.java: -------------------------------------------------------------------------------- 1 | import com.namelessmc.plugin.common.LanguageHandler; 2 | import org.junit.jupiter.api.Assertions; 3 | import org.junit.jupiter.api.Test; 4 | import org.spongepowered.configurate.ConfigurateException; 5 | import org.spongepowered.configurate.ConfigurationNode; 6 | import org.spongepowered.configurate.yaml.YamlConfigurationLoader; 7 | 8 | import java.io.IOException; 9 | import java.lang.reflect.Field; 10 | import java.nio.file.Files; 11 | import java.nio.file.Path; 12 | import java.nio.file.Paths; 13 | import java.util.Arrays; 14 | import java.util.Set; 15 | 16 | public class LanguageHandlerTest { 17 | 18 | @Test 19 | void ensureAllFilesInLanguageSet() throws IllegalAccessException, NoSuchFieldException, IOException { 20 | Field field = LanguageHandler.class.getDeclaredField("LANGUAGES"); 21 | field.setAccessible(true); 22 | Set languageCodes = (Set) field.get(null);; 23 | Path languagesDir = Path.of( "resources", "languages"); 24 | Files.list(languagesDir).forEach(path -> { 25 | String name = path.getFileName().toString(); 26 | String languageCode = name.substring(0, name.length() - 5); 27 | Assertions.assertTrue(languageCodes.contains(languageCode), "missing language " + languageCode); 28 | }); 29 | } 30 | 31 | @Test 32 | void ensureTermsPresentInBase() throws ConfigurateException { 33 | Path path = Path.of("resources", "languages", "en_UK.yaml"); 34 | ConfigurationNode config = YamlConfigurationLoader.builder().path(path).build().load(); 35 | for (LanguageHandler.Term term : LanguageHandler.Term.values()) { 36 | Assertions.assertTrue(config.hasChild(term.path()), "base file en_UK missing term " + Arrays.toString(term.path())); 37 | } 38 | } 39 | 40 | @Test 41 | void ensureLanguageFilesPresent() { 42 | for (String language : LanguageHandler.LANGUAGES) { 43 | Assertions.assertTrue(Files.isRegularFile(Paths.get("resources", "languages", language + ".yaml"))); 44 | } 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /oldbukkit/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | name: NamelessMC 2 | main: com.namelessmc.plugin.oldbukkit.OldBukkitNamelessPlugin 3 | author: Derkades 4 | website: https://plugin.namelessmc.com/ 5 | version: '@project.version@' 6 | softdepend: [Vault, PlaceholderAPI, Maintenance, LuckPerms] 7 | -------------------------------------------------------------------------------- /oldbukkit/src/main/com/namelessmc/plugin/oldbukkit/OldBukkitDataSender.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.oldbukkit; 2 | 3 | import com.namelessmc.plugin.bukkit.BukkitDataSender; 4 | import com.namelessmc.plugin.bukkit.BukkitNamelessPlugin; 5 | import com.namelessmc.plugin.common.NamelessPlugin; 6 | import org.bukkit.Bukkit; 7 | import org.checkerframework.checker.nullness.qual.NonNull; 8 | 9 | public class OldBukkitDataSender extends BukkitDataSender { 10 | 11 | protected OldBukkitDataSender(@NonNull NamelessPlugin plugin, @NonNull BukkitNamelessPlugin bukkitPlugin) { 12 | super(plugin, bukkitPlugin); 13 | } 14 | 15 | @Override 16 | protected void registerCustomProviders() { 17 | super.registerCustomProviders(); 18 | 19 | this.registerGlobalInfoProvider(json -> { 20 | json.addProperty("motd", Bukkit.getServer().getMotd()); 21 | }); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /oldbukkit/src/main/com/namelessmc/plugin/oldbukkit/OldBukkitNamelessPlugin.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.oldbukkit; 2 | 3 | import com.namelessmc.plugin.bukkit.BukkitNamelessPlugin; 4 | import com.namelessmc.plugin.common.LanguageHandler; 5 | import com.namelessmc.plugin.oldbukkit.audiences.OldBukkitAudienceProvider; 6 | import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; 7 | import org.bukkit.entity.Player; 8 | import org.checkerframework.checker.nullness.qual.NonNull; 9 | 10 | public class OldBukkitNamelessPlugin extends BukkitNamelessPlugin { 11 | 12 | public OldBukkitNamelessPlugin() { 13 | super("oldbukkit"); 14 | this.plugin.logger().warning("Please note that the 'Old Bukkit' version of the Nameless Plugin is not supported and may contain broken functionality."); 15 | 16 | this.plugin.registerReloadable(new OldBukkitDataSender(this.plugin, this)); 17 | } 18 | 19 | @Override 20 | protected void configureAudiences() { 21 | this.plugin.setAudienceProvider(new OldBukkitAudienceProvider(this.plugin.config())); 22 | } 23 | 24 | @Override 25 | public void kickPlayer(final @NonNull Player player, 26 | final LanguageHandler.@NonNull Term term) { 27 | final String legacyMessage = LegacyComponentSerializer.legacySection().serialize( 28 | this.plugin.language().get(term)); 29 | player.kickPlayer(legacyMessage); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /oldbukkit/src/main/com/namelessmc/plugin/oldbukkit/audiences/LegacyCommandSenderAudience.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.oldbukkit.audiences; 2 | 3 | import net.kyori.adventure.audience.Audience; 4 | import net.kyori.adventure.audience.MessageType; 5 | import net.kyori.adventure.identity.Identity; 6 | import net.kyori.adventure.text.Component; 7 | import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; 8 | import org.bukkit.command.CommandSender; 9 | 10 | public class LegacyCommandSenderAudience implements Audience { 11 | 12 | private static final LegacyComponentSerializer SERIALIZER = LegacyComponentSerializer.legacySection(); 13 | 14 | private CommandSender sender; 15 | 16 | LegacyCommandSenderAudience(final CommandSender sender) { 17 | this.sender = sender; 18 | } 19 | 20 | @Override 21 | public void sendMessage(final Identity source, 22 | final Component message, 23 | final MessageType type) { 24 | this.sender.sendMessage(SERIALIZER.serialize(message)); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /oldbukkit/src/main/com/namelessmc/plugin/oldbukkit/audiences/OldBukkitAudienceProvider.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.oldbukkit.audiences; 2 | 3 | import com.namelessmc.plugin.bukkit.audiences.BukkitNamelessConsole; 4 | import com.namelessmc.plugin.common.ConfigurationHandler; 5 | import com.namelessmc.plugin.common.audiences.AbstractAudienceProvider; 6 | import com.namelessmc.plugin.common.audiences.NamelessConsole; 7 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 8 | import net.kyori.adventure.audience.Audience; 9 | import org.bukkit.Bukkit; 10 | import org.bukkit.entity.Player; 11 | import org.checkerframework.checker.nullness.qual.NonNull; 12 | import org.checkerframework.checker.nullness.qual.Nullable; 13 | 14 | import java.util.*; 15 | import java.util.stream.Collectors; 16 | 17 | public class OldBukkitAudienceProvider extends AbstractAudienceProvider { 18 | 19 | private final ConfigurationHandler config; 20 | 21 | public OldBukkitAudienceProvider(final ConfigurationHandler config) { 22 | this.config = config; 23 | } 24 | 25 | private void dispatchCommand(final @NonNull String command) { 26 | Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command); 27 | } 28 | 29 | @Override 30 | public @NonNull NamelessConsole console() { 31 | return new BukkitNamelessConsole(new LegacyCommandSenderAudience(Bukkit.getConsoleSender())); 32 | } 33 | 34 | @Override 35 | public Audience broadcast() { 36 | final Player[] bukkitPlayers = Bukkit.getOnlinePlayers(); 37 | final List audiences = new ArrayList<>(bukkitPlayers.length + 1); 38 | for (Player player : bukkitPlayers) { 39 | audiences.add(new LegacyCommandSenderAudience(player)); 40 | } 41 | audiences.add(new LegacyCommandSenderAudience(Bukkit.getConsoleSender())); 42 | return Audience.audience(audiences); 43 | } 44 | 45 | public @Nullable NamelessPlayer bukkitToNamelessPlayer(final Player bukkitPlayer) { 46 | return bukkitPlayer == null 47 | ? null 48 | : new OldBukkitNamelessPlayer(this.config, bukkitPlayer); 49 | } 50 | 51 | @Override 52 | public @Nullable NamelessPlayer player(@NonNull UUID uuid) { 53 | for (Player player : Bukkit.getOnlinePlayers()) { 54 | if (player.getUniqueId().equals(uuid)) { 55 | return bukkitToNamelessPlayer(player); 56 | } 57 | } 58 | return null; 59 | } 60 | 61 | @Override 62 | public @Nullable NamelessPlayer playerByUsername(String username) { 63 | return bukkitToNamelessPlayer(Bukkit.getPlayerExact(username)); 64 | } 65 | 66 | @Override 67 | public @NonNull Collection<@NonNull NamelessPlayer> onlinePlayers() { 68 | return Arrays.stream(Bukkit.getOnlinePlayers()) 69 | .map(p -> new OldBukkitNamelessPlayer(this.config, p)) 70 | .collect(Collectors.toUnmodifiableList()); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /oldbukkit/src/main/com/namelessmc/plugin/oldbukkit/audiences/OldBukkitNamelessPlayer.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.oldbukkit.audiences; 2 | 3 | import org.bukkit.entity.Player; 4 | 5 | import com.namelessmc.plugin.bukkit.audiences.BukkitNamelessPlayer; 6 | import com.namelessmc.plugin.common.ConfigurationHandler; 7 | 8 | public class OldBukkitNamelessPlayer extends BukkitNamelessPlayer { 9 | 10 | public OldBukkitNamelessPlayer(final ConfigurationHandler config, 11 | final Player player) { 12 | super(config, new LegacyCommandSenderAudience(player), player); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /paper/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | name: NamelessMC 2 | main: com.namelessmc.plugin.paper.PaperNamelessPlugin 3 | author: Derkades 4 | website: https://plugin.namelessmc.com/ 5 | version: '@project.version@' 6 | api-version: 1.18 7 | softdepend: [Vault, PlaceholderAPI, Maintenance, LuckPerms] 8 | -------------------------------------------------------------------------------- /paper/src/main/com/namelessmc/plugin/paper/PaperAudienceProvider.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.paper; 2 | 3 | import com.namelessmc.plugin.bukkit.audiences.BukkitNamelessConsole; 4 | import com.namelessmc.plugin.bukkit.audiences.BukkitNamelessPlayer; 5 | import com.namelessmc.plugin.common.ConfigurationHandler; 6 | import com.namelessmc.plugin.common.audiences.AbstractAudienceProvider; 7 | import com.namelessmc.plugin.common.audiences.NamelessConsole; 8 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 9 | import net.kyori.adventure.audience.Audience; 10 | import org.bukkit.Bukkit; 11 | import org.bukkit.entity.Player; 12 | import org.checkerframework.checker.nullness.qual.NonNull; 13 | import org.checkerframework.checker.nullness.qual.Nullable; 14 | 15 | import java.util.ArrayList; 16 | import java.util.Collection; 17 | import java.util.List; 18 | import java.util.UUID; 19 | 20 | public class PaperAudienceProvider extends AbstractAudienceProvider { 21 | 22 | private ConfigurationHandler config; 23 | 24 | PaperAudienceProvider(ConfigurationHandler config) { 25 | this.config = config; 26 | } 27 | 28 | private void dispatchCommand(final @NonNull String command) { 29 | Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command); 30 | } 31 | 32 | @Override 33 | public @NonNull NamelessConsole console() { 34 | return new BukkitNamelessConsole(Bukkit.getConsoleSender()); 35 | } 36 | 37 | @Override 38 | public @NonNull Audience broadcast() { 39 | final Collection bukkitPlayers = Bukkit.getOnlinePlayers(); 40 | final List audiences = new ArrayList<>(bukkitPlayers.size() + 1); 41 | audiences.addAll(bukkitPlayers); 42 | audiences.add(Bukkit.getConsoleSender()); 43 | return Audience.audience(audiences); 44 | } 45 | 46 | @SuppressWarnings("nullness") // Checker framework thinks bukkitPlayer.getName() is nullable 47 | public @Nullable NamelessPlayer bukkitToNamelessPlayer(final @Nullable Player bukkitPlayer) { 48 | return bukkitPlayer == null 49 | ? null 50 | : new BukkitNamelessPlayer(this.config, bukkitPlayer, bukkitPlayer); 51 | } 52 | 53 | @Override 54 | public @Nullable NamelessPlayer player(@NonNull UUID uuid) { 55 | return bukkitToNamelessPlayer(Bukkit.getPlayer(uuid)); 56 | } 57 | 58 | @Override 59 | public @Nullable NamelessPlayer playerByUsername(@NonNull String username) { 60 | return bukkitToNamelessPlayer(Bukkit.getPlayerExact(username)); 61 | } 62 | 63 | @Override 64 | public @NonNull Collection<@NonNull NamelessPlayer> onlinePlayers() { 65 | return Bukkit.getOnlinePlayers().stream() 66 | .map(p -> (NamelessPlayer) new BukkitNamelessPlayer(this.config, p, p)) 67 | .toList(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /paper/src/main/com/namelessmc/plugin/paper/PaperDataSender.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.paper; 2 | 3 | import com.destroystokyo.paper.profile.PlayerProfile; 4 | import com.google.gson.JsonObject; 5 | import com.namelessmc.plugin.bukkit.BukkitDataSender; 6 | import com.namelessmc.plugin.bukkit.audiences.BukkitNamelessPlayer; 7 | import com.namelessmc.plugin.common.NamelessPlugin; 8 | import net.kyori.adventure.text.Component; 9 | import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; 10 | import org.bukkit.Bukkit; 11 | import org.bukkit.entity.Player; 12 | import org.bukkit.profile.PlayerTextures; 13 | import org.checkerframework.checker.nullness.qual.NonNull; 14 | 15 | import java.net.URL; 16 | 17 | public class PaperDataSender extends BukkitDataSender { 18 | 19 | protected PaperDataSender(@NonNull NamelessPlugin plugin, @NonNull PaperNamelessPlugin bukkitPlugin) { 20 | super(plugin, bukkitPlugin); 21 | } 22 | 23 | @Override 24 | protected void registerCustomProviders() { 25 | super.registerCustomProviders(); 26 | 27 | this.registerPlayerInfoProvider((json, namelessPlayer) -> { 28 | Player player = ((BukkitNamelessPlayer) namelessPlayer).bukkitPlayer(); 29 | if (player == null) { 30 | throw new IllegalStateException(); 31 | } 32 | 33 | PlayerProfile profile = player.getPlayerProfile(); 34 | PlayerTextures textures = profile.getTextures(); 35 | JsonObject skinJson = new JsonObject(); 36 | skinJson.addProperty("model", textures.getSkinModel().toString().toLowerCase()); 37 | URL skin = textures.getSkin(); 38 | URL cape = textures.getCape(); 39 | if (skin != null) { 40 | skinJson.addProperty("skin", skin.toString()); 41 | } 42 | if (cape != null) { 43 | skinJson.addProperty("cape", cape.toString()); 44 | } 45 | json.add("skin", skinJson); 46 | }); 47 | 48 | this.registerGlobalInfoProvider(json -> { 49 | final Component motd = Bukkit.getServer().motd(); 50 | final String legacyMotd = LegacyComponentSerializer.legacySection().serialize(motd); 51 | json.addProperty("motd", legacyMotd); 52 | }); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /paper/src/main/com/namelessmc/plugin/paper/PaperNamelessPlugin.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.paper; 2 | 3 | import com.namelessmc.plugin.bukkit.BukkitDataSender; 4 | import com.namelessmc.plugin.bukkit.BukkitNamelessPlugin; 5 | import com.namelessmc.plugin.common.LanguageHandler; 6 | import org.bukkit.entity.Player; 7 | import org.checkerframework.checker.nullness.qual.NonNull; 8 | 9 | public class PaperNamelessPlugin extends BukkitNamelessPlugin { 10 | 11 | public PaperNamelessPlugin() { 12 | super("paper"); 13 | 14 | this.plugin.unregisterReloadable(BukkitDataSender.class); 15 | this.plugin.registerReloadable(new PaperDataSender(this.plugin, this)); 16 | } 17 | 18 | @Override 19 | public void configureAudiences() { 20 | this.plugin.setAudienceProvider(new PaperAudienceProvider(this.plugin.config())); 21 | } 22 | 23 | @Override 24 | public void kickPlayer(final @NonNull Player player, final LanguageHandler.@NonNull Term term) { 25 | player.kick(this.plugin.language().get(term)); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /spigot/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | name: NamelessMC 2 | main: com.namelessmc.plugin.spigot.SpigotNamelessPlugin 3 | author: Derkades 4 | website: https://plugin.namelessmc.com/ 5 | version: '@project.version@' 6 | api-version: 1.13 7 | softdepend: [Vault, PlaceholderAPI, Maintenance, LuckPerms] 8 | -------------------------------------------------------------------------------- /spigot/src/main/com/namelessmc/plugin/spigot/SpigotAudienceProvider.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.spigot; 2 | 3 | import com.namelessmc.plugin.bukkit.BukkitNamelessPlugin; 4 | import com.namelessmc.plugin.bukkit.audiences.BukkitNamelessConsole; 5 | import com.namelessmc.plugin.bukkit.audiences.BukkitNamelessPlayer; 6 | import com.namelessmc.plugin.common.ConfigurationHandler; 7 | import com.namelessmc.plugin.common.audiences.AbstractAudienceProvider; 8 | import com.namelessmc.plugin.common.audiences.NamelessConsole; 9 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 10 | import net.kyori.adventure.audience.Audience; 11 | import net.kyori.adventure.platform.bukkit.BukkitAudiences; 12 | import org.bukkit.Bukkit; 13 | import org.bukkit.entity.Player; 14 | import org.checkerframework.checker.nullness.qual.NonNull; 15 | import org.checkerframework.checker.nullness.qual.Nullable; 16 | 17 | import java.util.Collection; 18 | import java.util.UUID; 19 | import java.util.stream.Collectors; 20 | 21 | public class SpigotAudienceProvider extends AbstractAudienceProvider { 22 | 23 | private final ConfigurationHandler config; 24 | private final BukkitAudiences audiences; 25 | 26 | SpigotAudienceProvider(final ConfigurationHandler config, 27 | final BukkitNamelessPlugin bukkitPlugin) { 28 | this.config = config; 29 | this.audiences = BukkitAudiences.create(bukkitPlugin); 30 | } 31 | 32 | @Override 33 | public @NonNull NamelessConsole console() { 34 | return new BukkitNamelessConsole(audiences.console()); 35 | } 36 | 37 | @Override 38 | public @NonNull Audience broadcast() { 39 | return audiences.all(); 40 | } 41 | 42 | public @Nullable NamelessPlayer bukkitToNamelessPlayer(final Player bukkitPlayer) { 43 | return bukkitPlayer == null 44 | ? null 45 | : new BukkitNamelessPlayer(this.config, this.audiences.player(bukkitPlayer), bukkitPlayer); 46 | } 47 | 48 | @Override 49 | public @Nullable NamelessPlayer player(@NonNull UUID uuid) { 50 | return bukkitToNamelessPlayer(Bukkit.getPlayer(uuid)); 51 | } 52 | 53 | @Override 54 | public @Nullable NamelessPlayer playerByUsername(@NonNull String username) { 55 | return bukkitToNamelessPlayer(Bukkit.getPlayerExact(username)); 56 | } 57 | 58 | @Override 59 | public @NonNull Collection<@NonNull NamelessPlayer> onlinePlayers() { 60 | return Bukkit.getOnlinePlayers().stream() 61 | .map(p -> new BukkitNamelessPlayer(this.config, this.audiences.player(p), p)) 62 | .collect(Collectors.toUnmodifiableList()); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /spigot/src/main/com/namelessmc/plugin/spigot/SpigotDataSender.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.spigot; 2 | 3 | import com.namelessmc.plugin.bukkit.BukkitDataSender; 4 | import com.namelessmc.plugin.bukkit.BukkitNamelessPlugin; 5 | import com.namelessmc.plugin.common.NamelessPlugin; 6 | import org.bukkit.Bukkit; 7 | import org.checkerframework.checker.nullness.qual.NonNull; 8 | 9 | public class SpigotDataSender extends BukkitDataSender { 10 | 11 | protected SpigotDataSender(@NonNull NamelessPlugin plugin, @NonNull BukkitNamelessPlugin bukkitPlugin) { 12 | super(plugin, bukkitPlugin); 13 | } 14 | 15 | @Override 16 | protected void registerCustomProviders() { 17 | super.registerCustomProviders(); 18 | 19 | this.registerGlobalInfoProvider(json -> { 20 | json.addProperty("motd", Bukkit.getServer().getMotd()); 21 | }); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /spigot/src/main/com/namelessmc/plugin/spigot/SpigotNamelessPlugin.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.spigot; 2 | 3 | import com.namelessmc.plugin.bukkit.BukkitNamelessPlugin; 4 | import com.namelessmc.plugin.common.LanguageHandler; 5 | import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; 6 | import org.bukkit.entity.Player; 7 | import org.checkerframework.checker.nullness.qual.NonNull; 8 | 9 | public class SpigotNamelessPlugin extends BukkitNamelessPlugin { 10 | 11 | public SpigotNamelessPlugin() { 12 | super("spigot"); 13 | 14 | this.plugin.registerReloadable(new SpigotDataSender(this.plugin, this)); 15 | } 16 | 17 | @Override 18 | protected void configureAudiences() { 19 | this.plugin.setAudienceProvider(new SpigotAudienceProvider(this.plugin.config(), this)); 20 | } 21 | 22 | @Override 23 | public void kickPlayer(final @NonNull Player player, 24 | final LanguageHandler.@NonNull Term term) { 25 | final String legacyMessage = LegacyComponentSerializer.legacySection().serialize( 26 | this.plugin.language().get(term)); 27 | player.kickPlayer(legacyMessage); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /sponge10/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | plugin-sponge10 7 | Nameless-Plugin-Sponge10 8 | 9 | 10 | com.namelessmc 11 | plugin 12 | ${revision} 13 | ../pom.xml 14 | 15 | 16 | 17 | src/main 18 | 19 | 20 | 21 | resources 22 | true 23 | 24 | 25 | 26 | 27 | 28 | org.apache.maven.plugins 29 | maven-shade-plugin 30 | 31 | 32 | 33 | com.github.mizosoft.methanol 34 | com.namelessmc.plugin.lib.methanol 35 | 36 | 37 | com.namelessmc.java_api 38 | com.namelessmc.plugin.lib.nameless-api 39 | 40 | 41 | net.kyori.event 42 | com.namelessmc.plugin.lib.event 43 | 44 | 45 | org.checkerframework 46 | com.namelessmc.plugin.lib.checker-framework 47 | 48 | 49 | xyz.derkades.derkutils 50 | com.namelessmc.plugin.lib.derkutils 51 | 52 | 53 | 54 | 55 | 56 | package 57 | 58 | shade 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | com.namelessmc 70 | plugin-sponge9 71 | ${revision} 72 | 73 | 74 | org.spongepowered 75 | spongeapi 76 | 77 | 78 | 79 | 80 | 81 | org.spongepowered 82 | spongeapi 83 | 10.0.0 84 | jar 85 | provided 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /sponge10/resources/sponge_plugins.json: -------------------------------------------------------------------------------- 1 | { 2 | "loader": { 3 | "name": "java_plain", 4 | "version": "1.0" 5 | }, 6 | "license": "MIT", 7 | "global": { 8 | "version": "@project.version@", 9 | "links": { 10 | "homepage": "https://namelessmc.com", 11 | "source": "https://github.com/NamelessMC/Nameless-Plugin/", 12 | "issues": "https://github.com/NamelessMC/Nameless-Plugin/issues" 13 | }, 14 | "contributors": [ 15 | { 16 | "name": "Derkades", 17 | "description": "Lead Developer" 18 | } 19 | ], 20 | "dependencies": [ 21 | { 22 | "id": "spongeapi", 23 | "version": "10.0.0" 24 | } 25 | ] 26 | }, 27 | "plugins": [ 28 | { 29 | "id": "namelessmc", 30 | "name": "NamelessMC", 31 | "entrypoint": "com.namelessmc.plugin.sponge10.SpongeNamelessPlugin", 32 | "description": "Integration with NamelessMC websites" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /sponge10/src/main/com/namelessmc/plugin/sponge10/SpongeNamelessPlugin.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge10; 2 | 3 | import com.google.inject.Inject; 4 | import org.apache.logging.log4j.Logger; 5 | import org.spongepowered.api.config.ConfigDir; 6 | import org.spongepowered.plugin.PluginContainer; 7 | import org.spongepowered.plugin.builtin.jvm.Plugin; 8 | 9 | import java.nio.file.Path; 10 | 11 | @Plugin("namelessmc") 12 | public class SpongeNamelessPlugin extends com.namelessmc.plugin.sponge9.SpongeNamelessPlugin { 13 | 14 | @Inject 15 | public SpongeNamelessPlugin(final @ConfigDir(sharedRoot = false) Path dataDirectory, 16 | final Logger logger, 17 | final PluginContainer container) { 18 | super(dataDirectory, logger, container); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /sponge7/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | plugin-sponge7 7 | Nameless-Plugin-Sponge7 8 | 9 | 10 | ../pom.xml 11 | com.namelessmc 12 | plugin 13 | ${revision} 14 | 15 | 16 | 17 | src/main 18 | 19 | 20 | 21 | org.apache.maven.plugins 22 | maven-shade-plugin 23 | 24 | 25 | 26 | com.google.errorprone.annotations 27 | com.namelessmc.plugin.lib.errorprone-annotations 28 | 29 | 30 | net.kyori.adventure 31 | com.namelessmc.plugin.lib.adventure 32 | 33 | 34 | net.kyori.examination 35 | com.namelessmc.plugin.lib.examination 36 | 37 | 38 | org.checkerframework 39 | com.namelessmc.plugin.lib.checker-framework 40 | 41 | 42 | org.intellij.lang.annotations 43 | com.namelessmc.plugin.lib.intellij-annotations 44 | 45 | 46 | org.jetbrains.annotations 47 | com.namelessmc.plugin.lib.jetbrains-annotations 48 | 49 | 50 | 51 | org.spongepowered.configurate 52 | com.namelessmc.plugin.lib.configurate 53 | 54 | 55 | io.leangen.geantyref 56 | com.namelessmc.plugin.lib.geantyref 57 | 58 | 59 | 60 | 61 | 62 | package 63 | 64 | shade 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | com.namelessmc 76 | plugin-common 77 | 78 | 81 | 82 | org.yaml 83 | snakeyaml 84 | 85 | 86 | 87 | com.google.code.gson 88 | gson 89 | 90 | 91 | 92 | com.google.guava 93 | guava 94 | 95 | 96 | 97 | 98 | 99 | org.spongepowered 100 | spongeapi 101 | 7.4.0 102 | jar 103 | provided 104 | 105 | 106 | 107 | net.kyori 108 | adventure-platform-spongeapi 109 | 4.2.0 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /sponge7/src/main/com/namelessmc/plugin/sponge7/Slf4jLogger.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge7; 2 | 3 | import com.namelessmc.plugin.common.ConfigurationHandler; 4 | import com.namelessmc.plugin.common.logger.AbstractLogger; 5 | import org.checkerframework.checker.nullness.qual.NonNull; 6 | import org.slf4j.Logger; 7 | 8 | import java.util.function.Supplier; 9 | 10 | public class Slf4jLogger extends AbstractLogger { 11 | 12 | private final @NonNull Logger logger; 13 | 14 | public Slf4jLogger(final @NonNull ConfigurationHandler config, 15 | final @NonNull Logger logger) { 16 | super(config); 17 | this.logger = logger; 18 | } 19 | 20 | @Override 21 | public void info(final String string) { 22 | this.logger.info(string); 23 | } 24 | 25 | @Override 26 | public void warning(final String string) { 27 | this.logger.warn(string); 28 | } 29 | 30 | @Override 31 | public void severe(final String string) { 32 | this.logger.error(string); 33 | } 34 | 35 | @Override 36 | public void info(final Supplier stringSupplier) { 37 | if (this.logger.isInfoEnabled()) { 38 | this.logger.info(stringSupplier.get()); 39 | } 40 | } 41 | 42 | @Override 43 | public void warning(final Supplier stringSupplier) { 44 | if (this.logger.isWarnEnabled()) { 45 | this.logger.warn(stringSupplier.get()); 46 | } 47 | } 48 | 49 | @Override 50 | public void severe(final Supplier stringSupplier) { 51 | if (this.logger.isErrorEnabled()) { 52 | this.logger.error(stringSupplier.get()); 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /sponge7/src/main/com/namelessmc/plugin/sponge7/SpongeCommandProxy.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge7; 2 | 3 | import com.namelessmc.plugin.common.NamelessPlugin; 4 | import com.namelessmc.plugin.common.audiences.NamelessCommandSender; 5 | import com.namelessmc.plugin.common.command.CommonCommand; 6 | import net.kyori.adventure.text.serializer.spongeapi.SpongeComponentSerializer; 7 | import org.checkerframework.checker.nullness.qual.NonNull; 8 | import org.checkerframework.checker.nullness.qual.Nullable; 9 | import org.spongepowered.api.Sponge; 10 | import org.spongepowered.api.command.CommandCallable; 11 | import org.spongepowered.api.command.CommandManager; 12 | import org.spongepowered.api.command.CommandResult; 13 | import org.spongepowered.api.command.CommandSource; 14 | import org.spongepowered.api.entity.living.player.Player; 15 | import org.spongepowered.api.text.Text; 16 | import org.spongepowered.api.world.Location; 17 | import org.spongepowered.api.world.World; 18 | 19 | import java.util.Collections; 20 | import java.util.List; 21 | import java.util.Optional; 22 | 23 | public class SpongeCommandProxy { 24 | 25 | static void registerCommands(final NamelessPlugin plugin, final SpongeNamelessPlugin spongePlugin) { 26 | final CommandManager manager = Sponge.getCommandManager(); 27 | 28 | CommonCommand.commands(plugin).forEach(command -> { 29 | final String name = command.actualName(); 30 | if (name == null) { 31 | // Command is disabled 32 | return; 33 | } 34 | 35 | final String permission = command.permission().toString(); 36 | final SpongeComponentSerializer ser = SpongeComponentSerializer.get(); 37 | final Text usage = ser.serialize(command.usage()); 38 | final Text description = ser.serialize(command.description()); 39 | 40 | CommandCallable spongeCommand = new CommandCallable() { 41 | @Override 42 | public @NonNull CommandResult process(final @NonNull CommandSource source, 43 | final @NonNull String arguments) { 44 | String[] args = arguments.split(" "); 45 | final NamelessCommandSender namelessCommandSender; 46 | if (source instanceof Player) { 47 | namelessCommandSender = plugin.audiences().player(((Player) source).getUniqueId()); 48 | } else { 49 | namelessCommandSender = plugin.audiences().console(); 50 | } 51 | 52 | if (namelessCommandSender == null) { 53 | source.sendMessage(Text.of("ERROR: Cannot obtain audience for command sender")); 54 | } 55 | 56 | command.verifyPermissionThenExecute(namelessCommandSender, args); 57 | return CommandResult.success(); 58 | } 59 | 60 | @Override 61 | public List getSuggestions(final @NonNull CommandSource source, 62 | final @NonNull String arguments, 63 | final @Nullable Location targetPosition) { 64 | return Collections.emptyList(); 65 | } 66 | 67 | @Override 68 | public boolean testPermission(final CommandSource source) { 69 | return source.hasPermission(permission); 70 | } 71 | 72 | @Override 73 | public Optional getShortDescription(final @NonNull CommandSource source) { 74 | return Optional.of(description); 75 | } 76 | 77 | @Override 78 | public Optional getHelp(final @NonNull CommandSource source) { 79 | return Optional.empty(); 80 | } 81 | 82 | @Override 83 | public Text getUsage(final @NonNull CommandSource source) { 84 | return usage; 85 | } 86 | }; 87 | 88 | manager.register(spongePlugin, spongeCommand, command.actualName()); 89 | }); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /sponge7/src/main/com/namelessmc/plugin/sponge7/SpongeDataSender.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge7; 2 | 3 | import com.namelessmc.plugin.common.AbstractDataSender; 4 | import com.namelessmc.plugin.common.NamelessPlugin; 5 | import org.checkerframework.checker.nullness.qual.NonNull; 6 | 7 | public class SpongeDataSender extends AbstractDataSender { 8 | 9 | protected SpongeDataSender(@NonNull NamelessPlugin plugin) { 10 | super(plugin); 11 | } 12 | 13 | @Override 14 | protected void registerCustomProviders() {} 15 | 16 | } 17 | -------------------------------------------------------------------------------- /sponge7/src/main/com/namelessmc/plugin/sponge7/SpongeEventProxy.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge7; 2 | 3 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 4 | import com.namelessmc.plugin.common.NamelessPlugin; 5 | import com.namelessmc.plugin.common.event.NamelessJoinEvent; 6 | import com.namelessmc.plugin.common.event.NamelessPlayerQuitEvent; 7 | import org.checkerframework.checker.nullness.qual.NonNull; 8 | import org.spongepowered.api.event.Listener; 9 | import org.spongepowered.api.event.network.ClientConnectionEvent; 10 | 11 | public class SpongeEventProxy { 12 | 13 | private final @NonNull NamelessPlugin plugin; 14 | 15 | SpongeEventProxy(final @NonNull NamelessPlugin plugin) { 16 | this.plugin = plugin; 17 | } 18 | 19 | @Listener 20 | public void onJoin(ClientConnectionEvent.Join event) { 21 | final NamelessPlayer player = plugin.audiences().player(event.getTargetEntity().getUniqueId()); 22 | if (player == null) { 23 | this.plugin.logger().severe("Skipped join event for player " + event.getTargetEntity().getName() + 24 | ", Audience is null"); 25 | return; 26 | } 27 | final NamelessJoinEvent event2 = new NamelessJoinEvent(player); 28 | this.plugin.events().post(event2); 29 | } 30 | 31 | @Listener 32 | public void onQuit(ClientConnectionEvent.Disconnect event) { 33 | final NamelessPlayerQuitEvent event2 = new NamelessPlayerQuitEvent(event.getTargetEntity().getUniqueId()); 34 | this.plugin.events().post(event2); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /sponge7/src/main/com/namelessmc/plugin/sponge7/SpongeNamelessPlugin.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge7; 2 | 3 | import com.google.inject.Inject; 4 | import com.namelessmc.plugin.common.MavenConstants; 5 | import com.namelessmc.plugin.common.NamelessPlugin; 6 | import com.namelessmc.plugin.sponge7.audiences.SpongeAudienceProvider; 7 | import net.kyori.adventure.platform.spongeapi.SpongeAudiences; 8 | import org.checkerframework.checker.nullness.qual.NonNull; 9 | import org.slf4j.Logger; 10 | import org.spongepowered.api.Game; 11 | import org.spongepowered.api.Sponge; 12 | import org.spongepowered.api.config.ConfigDir; 13 | import org.spongepowered.api.event.Listener; 14 | import org.spongepowered.api.event.game.GameReloadEvent; 15 | import org.spongepowered.api.event.game.state.GameStartedServerEvent; 16 | import org.spongepowered.api.plugin.Plugin; 17 | 18 | import java.nio.file.Path; 19 | 20 | @Plugin(id = "namelessmc", 21 | name = "NamelessMC", 22 | version = MavenConstants.PROJECT_VERSION, 23 | description = "Integration with NamelessMC websites") 24 | public class SpongeNamelessPlugin { 25 | 26 | private final @NonNull NamelessPlugin plugin; 27 | 28 | @Inject 29 | public SpongeNamelessPlugin(final @NonNull SpongeAudiences audiences, 30 | final @ConfigDir(sharedRoot = false) @NonNull Path dataDirectory, 31 | final @NonNull Logger logger, 32 | final @NonNull Game game) { 33 | this.plugin = new NamelessPlugin( 34 | dataDirectory, 35 | new SpongeScheduler(this), 36 | config -> new Slf4jLogger(config, logger), 37 | Path.of("logs", "latest.log"), 38 | "sponge7", 39 | Sponge.getPlatform().getMinecraftVersion().getName() 40 | ); 41 | this.plugin.setAudienceProvider(new SpongeAudienceProvider(this.plugin.config(), audiences, game.getServer())); 42 | this.plugin.registerReloadable(new SpongeDataSender(this.plugin)); 43 | Sponge.getEventManager().registerListeners(this, new SpongeEventProxy(this.plugin)); 44 | } 45 | 46 | @Listener 47 | public void onServerStart(final GameStartedServerEvent event) { 48 | this.plugin.load(); 49 | SpongeCommandProxy.registerCommands(this.plugin, this); 50 | } 51 | 52 | @Listener 53 | public void reload(final GameReloadEvent event) { 54 | this.plugin.unload(); 55 | this.plugin.load(); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /sponge7/src/main/com/namelessmc/plugin/sponge7/SpongeScheduler.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge7; 2 | 3 | import com.namelessmc.plugin.common.command.AbstractScheduledTask; 4 | import com.namelessmc.plugin.common.command.AbstractScheduler; 5 | import org.checkerframework.checker.nullness.qual.NonNull; 6 | import org.spongepowered.api.scheduler.Task; 7 | 8 | import java.time.Duration; 9 | import java.util.concurrent.TimeUnit; 10 | 11 | public class SpongeScheduler extends AbstractScheduler { 12 | 13 | private final SpongeNamelessPlugin plugin; 14 | 15 | SpongeScheduler(final SpongeNamelessPlugin plugin) { 16 | this.plugin = plugin; 17 | } 18 | 19 | @Override 20 | public void runAsync(@NonNull Runnable runnable) { 21 | Task.builder() 22 | .execute(runnable) 23 | .async() 24 | .submit(this.plugin); 25 | } 26 | 27 | @Override 28 | public void runSync(@NonNull Runnable runnable) { 29 | Task.builder() 30 | .execute(runnable) 31 | .submit(this.plugin); 32 | } 33 | 34 | @Override 35 | public @NonNull SpongeScheduledTask runTimer(@NonNull Runnable runnable, @NonNull Duration interval) { 36 | final Task task = Task.builder() 37 | .execute(runnable) 38 | .delay(interval.toNanos(), TimeUnit.NANOSECONDS) 39 | .interval(interval.toNanos(), TimeUnit.NANOSECONDS) 40 | .submit(this.plugin); 41 | return new SpongeScheduledTask(task); 42 | } 43 | 44 | @Override 45 | public @NonNull SpongeScheduledTask runDelayed(@NonNull Runnable runnable, @NonNull Duration delay) { 46 | final Task task = Task.builder() 47 | .execute(runnable) 48 | .delay(delay.toNanos(), TimeUnit.NANOSECONDS) 49 | .submit(this.plugin); 50 | return new SpongeScheduledTask(task); 51 | } 52 | 53 | public static class SpongeScheduledTask extends AbstractScheduledTask { 54 | 55 | private final @NonNull Task task; 56 | 57 | private SpongeScheduledTask(final @NonNull Task task) { 58 | this.task = task; 59 | } 60 | 61 | @Override 62 | public void cancel() { 63 | this.task.cancel(); 64 | } 65 | 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /sponge7/src/main/com/namelessmc/plugin/sponge7/audiences/SpongeAudienceProvider.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge7.audiences; 2 | 3 | import com.namelessmc.plugin.common.ConfigurationHandler; 4 | import com.namelessmc.plugin.common.audiences.AbstractAudienceProvider; 5 | import com.namelessmc.plugin.common.audiences.NamelessConsole; 6 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 7 | import net.kyori.adventure.audience.Audience; 8 | import net.kyori.adventure.platform.spongeapi.SpongeAudiences; 9 | import org.checkerframework.checker.nullness.qual.NonNull; 10 | import org.checkerframework.checker.nullness.qual.Nullable; 11 | import org.spongepowered.api.Server; 12 | import org.spongepowered.api.entity.living.player.Player; 13 | 14 | import java.util.Collection; 15 | import java.util.Optional; 16 | import java.util.UUID; 17 | import java.util.stream.Collectors; 18 | 19 | public class SpongeAudienceProvider extends AbstractAudienceProvider { 20 | 21 | private final ConfigurationHandler config; 22 | private final SpongeAudiences audiences; 23 | private final Server server; 24 | 25 | public SpongeAudienceProvider(final ConfigurationHandler config, 26 | final SpongeAudiences audiences, 27 | final Server server) { 28 | this.config = config; 29 | this.audiences = audiences; 30 | this.server = server; 31 | } 32 | 33 | @Override 34 | public @NonNull NamelessConsole console() { 35 | return new SpongeNamelessConsole(this.audiences); 36 | } 37 | 38 | @Override 39 | public @NonNull Audience broadcast() { 40 | return this.audiences.all(); 41 | } 42 | 43 | private @Nullable NamelessPlayer spongeToNamelessPlayer(final Optional optionalPlayer) { 44 | if (optionalPlayer.isPresent()) { 45 | final Player player = optionalPlayer.get(); 46 | return new SpongeNamelessPlayer(this.config, this.audiences, player); 47 | } 48 | return null; 49 | } 50 | 51 | @Override 52 | public @Nullable NamelessPlayer player(@NonNull UUID uuid) { 53 | return spongeToNamelessPlayer(this.server.getPlayer(uuid)); 54 | } 55 | 56 | @Override 57 | public @Nullable NamelessPlayer playerByUsername(@NonNull String username) { 58 | return spongeToNamelessPlayer(this.server.getPlayer(username)); 59 | } 60 | 61 | @Override 62 | public @NonNull Collection<@NonNull NamelessPlayer> onlinePlayers() { 63 | return this.server.getOnlinePlayers().stream() 64 | .map(p -> new SpongeNamelessPlayer(this.config, this.audiences, p)) 65 | .collect(Collectors.toUnmodifiableList()); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /sponge7/src/main/com/namelessmc/plugin/sponge7/audiences/SpongeNamelessConsole.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge7.audiences; 2 | 3 | import com.namelessmc.plugin.common.audiences.NamelessConsole; 4 | import net.kyori.adventure.platform.spongeapi.SpongeAudiences; 5 | import org.spongepowered.api.Sponge; 6 | 7 | public class SpongeNamelessConsole extends NamelessConsole { 8 | 9 | public SpongeNamelessConsole(SpongeAudiences audiences) { 10 | super(audiences.console()); 11 | } 12 | 13 | @Override 14 | public void dispatchCommand(String command) { 15 | Sponge.getCommandManager().process(Sponge.getServer().getConsole(), command); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /sponge7/src/main/com/namelessmc/plugin/sponge7/audiences/SpongeNamelessPlayer.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge7.audiences; 2 | 3 | import com.namelessmc.plugin.common.ConfigurationHandler; 4 | import com.namelessmc.plugin.common.Permission; 5 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 6 | import net.kyori.adventure.platform.spongeapi.SpongeAudiences; 7 | import org.spongepowered.api.entity.living.player.Player; 8 | 9 | public class SpongeNamelessPlayer extends NamelessPlayer { 10 | 11 | private final Player player; 12 | 13 | public SpongeNamelessPlayer(final ConfigurationHandler config, 14 | final SpongeAudiences audiences, 15 | final Player player) { 16 | super(config, audiences.player(player), player.getUniqueId(), player.getName()); 17 | this.player = player; 18 | } 19 | 20 | @Override 21 | public boolean hasPermission(Permission permission) { 22 | return this.player.hasPermission(permission.toString()); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /sponge8/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | plugin-sponge8 7 | Nameless-Plugin-Sponge8 8 | 9 | 10 | com.namelessmc 11 | plugin 12 | ${revision} 13 | ../pom.xml 14 | 15 | 16 | 17 | src/main 18 | 19 | 20 | 21 | resources 22 | true 23 | 24 | 25 | 26 | 27 | 28 | org.apache.maven.plugins 29 | maven-shade-plugin 30 | 31 | 32 | 33 | com.github.mizosoft.methanol 34 | com.namelessmc.plugin.lib.methanol 35 | 36 | 37 | com.namelessmc.java_api 38 | com.namelessmc.plugin.lib.nameless-api 39 | 40 | 41 | net.kyori.event 42 | com.namelessmc.plugin.lib.event 43 | 44 | 45 | org.bstats 46 | com.namelessmc.plugin.lib.bstats 47 | 48 | 49 | org.checkerframework 50 | com.namelessmc.plugin.lib.checker-framework 51 | 52 | 53 | xyz.derkades.derkutils 54 | com.namelessmc.plugin.lib.derkutils 55 | 56 | 57 | 58 | 59 | 60 | package 61 | 62 | shade 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | com.namelessmc 74 | plugin-common 75 | 76 | 77 | 78 | net.kyori 79 | adventure-api 80 | 81 | 82 | 83 | net.kyori 84 | adventure-text-minimessage 85 | 86 | 87 | 88 | org.spongepowered 89 | configurate-yaml 90 | 91 | 92 | 93 | com.google.code.gson 94 | gson 95 | 96 | 97 | 98 | com.google.guava 99 | guava 100 | 101 | 102 | 103 | 104 | 105 | org.spongepowered 106 | spongeapi 107 | 8.1.0 108 | jar 109 | provided 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /sponge8/resources/sponge_plugins.json: -------------------------------------------------------------------------------- 1 | { 2 | "loader": { 3 | "name": "java_plain", 4 | "version": "1.0" 5 | }, 6 | "license": "MIT", 7 | "global": { 8 | "version": "@project.version@", 9 | "links": { 10 | "homepage": "https://namelessmc.com", 11 | "source": "https://github.com/NamelessMC/Nameless-Plugin/", 12 | "issues": "https://github.com/NamelessMC/Nameless-Plugin/issues" 13 | }, 14 | "contributors": [ 15 | { 16 | "name": "Derkades", 17 | "description": "Lead Developer" 18 | } 19 | ], 20 | "dependencies": [ 21 | { 22 | "id": "spongeapi", 23 | "version": "8.1.0" 24 | } 25 | ] 26 | }, 27 | "plugins": [ 28 | { 29 | "id": "namelessmc", 30 | "name": "NamelessMC", 31 | "entrypoint": "com.namelessmc.plugin.sponge8.SpongeNamelessPlugin", 32 | "description": "Integration with NamelessMC websites" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /sponge8/src/main/com/namelessmc/plugin/sponge8/Log4jLogger.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge8; 2 | 3 | import com.namelessmc.plugin.common.ConfigurationHandler; 4 | import com.namelessmc.plugin.common.logger.AbstractLogger; 5 | import org.apache.logging.log4j.Logger; 6 | import org.jetbrains.annotations.NotNull; 7 | 8 | import java.util.function.Supplier; 9 | 10 | public class Log4jLogger extends AbstractLogger { 11 | 12 | private final @NotNull Logger logger; 13 | 14 | public Log4jLogger(final @NotNull ConfigurationHandler config, 15 | final @NotNull Logger logger) { 16 | super(config); 17 | this.logger = logger; 18 | } 19 | 20 | @Override 21 | public void info(String string) { 22 | this.logger.info(string); 23 | } 24 | 25 | @Override 26 | public void warning(String string) { 27 | this.logger.warn(string); 28 | } 29 | 30 | @Override 31 | public void severe(String string) { 32 | this.logger.error(string); 33 | } 34 | 35 | @Override 36 | public void info(Supplier stringSupplier) { 37 | this.logger.info(stringSupplier); 38 | } 39 | 40 | @Override 41 | public void warning(Supplier stringSupplier) { 42 | this.logger.warn(stringSupplier); 43 | } 44 | 45 | @Override 46 | public void severe(Supplier stringSupplier) { 47 | this.logger.error(stringSupplier); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /sponge8/src/main/com/namelessmc/plugin/sponge8/SpongeDataSender.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge8; 2 | 3 | import com.namelessmc.plugin.common.AbstractDataSender; 4 | import com.namelessmc.plugin.common.NamelessPlugin; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | public class SpongeDataSender extends AbstractDataSender { 8 | 9 | protected SpongeDataSender(@NotNull NamelessPlugin plugin) { 10 | super(plugin); 11 | } 12 | 13 | @Override 14 | protected void registerCustomProviders() {} 15 | 16 | } 17 | -------------------------------------------------------------------------------- /sponge8/src/main/com/namelessmc/plugin/sponge8/SpongeEventProxy.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge8; 2 | 3 | import com.namelessmc.plugin.common.NamelessPlugin; 4 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 5 | import com.namelessmc.plugin.common.event.NamelessJoinEvent; 6 | import com.namelessmc.plugin.sponge8.audiences.SpongeNamelessPlayer; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.spongepowered.api.event.Listener; 9 | import org.spongepowered.api.event.network.ServerSideConnectionEvent; 10 | 11 | public class SpongeEventProxy { 12 | 13 | private final @NotNull NamelessPlugin plugin; 14 | 15 | SpongeEventProxy(final @NotNull NamelessPlugin plugin) { 16 | this.plugin = plugin; 17 | } 18 | 19 | @Listener 20 | public void onJoin(ServerSideConnectionEvent.Join event) { 21 | final NamelessPlayer player = new SpongeNamelessPlayer(this.plugin.config(), event.player()); 22 | this.plugin.events().post(new NamelessJoinEvent(player)); 23 | } 24 | 25 | // TODO quit event 26 | 27 | } 28 | -------------------------------------------------------------------------------- /sponge8/src/main/com/namelessmc/plugin/sponge8/SpongeNamelessPlugin.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge8; 2 | 3 | import com.google.inject.Inject; 4 | import com.namelessmc.plugin.common.NamelessPlugin; 5 | import com.namelessmc.plugin.sponge8.audiences.SpongeAudienceProvider; 6 | import org.apache.logging.log4j.Logger; 7 | import org.spongepowered.api.Server; 8 | import org.spongepowered.api.Sponge; 9 | import org.spongepowered.api.command.Command; 10 | import org.spongepowered.api.config.ConfigDir; 11 | import org.spongepowered.api.event.Listener; 12 | import org.spongepowered.api.event.lifecycle.RefreshGameEvent; 13 | import org.spongepowered.api.event.lifecycle.RegisterCommandEvent; 14 | import org.spongepowered.api.event.lifecycle.StartedEngineEvent; 15 | import org.spongepowered.plugin.PluginContainer; 16 | import org.spongepowered.plugin.builtin.jvm.Plugin; 17 | 18 | import java.nio.file.Path; 19 | 20 | @Plugin("namelessmc") 21 | public class SpongeNamelessPlugin { 22 | 23 | private final NamelessPlugin plugin; 24 | private final PluginContainer container; 25 | 26 | @Inject 27 | public SpongeNamelessPlugin(final @ConfigDir(sharedRoot = false) Path dataDirectory, 28 | final Logger logger, 29 | final PluginContainer container) { 30 | this.container = container; 31 | this.plugin = new NamelessPlugin( 32 | dataDirectory, 33 | new SpongeScheduler(container), 34 | config -> new Log4jLogger(config, logger), 35 | Path.of("logs", "latest.log"), 36 | "sponge8", 37 | Sponge.platform().minecraftVersion().name() 38 | ); 39 | this.plugin.setAudienceProvider(new SpongeAudienceProvider(this.plugin.config())); 40 | this.plugin.registerReloadable(new SpongeDataSender(this.plugin)); 41 | Sponge.eventManager().registerListeners(container, new SpongeEventProxy(this.plugin)); 42 | } 43 | 44 | @Listener 45 | public void registerCommands(final RegisterCommandEvent event) { 46 | SpongeCommandProxy commandProxy = new SpongeCommandProxy(this.plugin); 47 | commandProxy.registerCommands(event, this.container); 48 | } 49 | 50 | @Listener 51 | public void onStarted(final StartedEngineEvent event) { 52 | this.plugin.load(); 53 | } 54 | 55 | @Listener 56 | public void reload(final RefreshGameEvent event) { 57 | this.plugin.unload(); 58 | this.plugin.load(); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /sponge8/src/main/com/namelessmc/plugin/sponge8/SpongeScheduler.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge8; 2 | 3 | import com.namelessmc.plugin.common.command.AbstractScheduledTask; 4 | import com.namelessmc.plugin.common.command.AbstractScheduler; 5 | import org.checkerframework.checker.nullness.qual.NonNull; 6 | import org.spongepowered.api.Sponge; 7 | import org.spongepowered.api.scheduler.ScheduledTask; 8 | import org.spongepowered.api.scheduler.Task; 9 | import org.spongepowered.plugin.PluginContainer; 10 | 11 | import java.time.Duration; 12 | import java.util.concurrent.ExecutorService; 13 | import java.util.concurrent.Executors; 14 | import java.util.concurrent.TimeUnit; 15 | 16 | public class SpongeScheduler extends AbstractScheduler { 17 | 18 | private final PluginContainer spongePlugin; 19 | private final ExecutorService executor = Executors.newCachedThreadPool(); 20 | 21 | SpongeScheduler(final PluginContainer spongePlugin) { 22 | this.spongePlugin = spongePlugin; 23 | } 24 | 25 | @Override 26 | public void runAsync(final @NonNull Runnable runnable) { 27 | // Sponge probably provides an API for async tasks, but I couldn't find it. Use Java ExecutorService instead. 28 | executor.submit(runnable); 29 | } 30 | 31 | @Override 32 | public void runSync(final @NonNull Runnable runnable) { 33 | final Task task = Task.builder() 34 | .plugin(spongePlugin) 35 | .execute(runnable) 36 | .build(); 37 | Sponge.server().scheduler().submit(task); 38 | } 39 | 40 | @Override 41 | public @NonNull SpongeScheduledTask runTimer(@NonNull Runnable runnable, @NonNull Duration interval) { 42 | final Task task = Task.builder() 43 | .plugin(spongePlugin) 44 | .execute(runnable) 45 | .delay(interval.toNanos(), TimeUnit.NANOSECONDS) 46 | .interval(interval.toNanos(), TimeUnit.NANOSECONDS) 47 | .build(); 48 | return new SpongeScheduledTask(Sponge.server().scheduler().submit(task)); 49 | } 50 | 51 | @Override 52 | public @NonNull SpongeScheduledTask runDelayed(@NonNull Runnable runnable, @NonNull Duration delay) { 53 | final Task task = Task.builder() 54 | .plugin(spongePlugin) 55 | .execute(runnable) 56 | .delay(delay.toNanos(), TimeUnit.NANOSECONDS) 57 | .build(); 58 | return new SpongeScheduledTask(Sponge.server().scheduler().submit(task)); 59 | } 60 | 61 | public static class SpongeScheduledTask extends AbstractScheduledTask { 62 | 63 | private final ScheduledTask task; 64 | 65 | private SpongeScheduledTask(final ScheduledTask task) { 66 | this.task = task; 67 | } 68 | 69 | @Override 70 | public void cancel() { 71 | this.task.cancel(); 72 | } 73 | 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /sponge8/src/main/com/namelessmc/plugin/sponge8/audiences/SpongeAudienceProvider.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge8.audiences; 2 | 3 | import com.namelessmc.plugin.common.ConfigurationHandler; 4 | import com.namelessmc.plugin.common.audiences.AbstractAudienceProvider; 5 | import com.namelessmc.plugin.common.audiences.NamelessConsole; 6 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 7 | import net.kyori.adventure.audience.Audience; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.jetbrains.annotations.Nullable; 10 | import org.spongepowered.api.Sponge; 11 | import org.spongepowered.api.entity.living.player.server.ServerPlayer; 12 | 13 | import java.util.Collection; 14 | import java.util.Optional; 15 | import java.util.UUID; 16 | import java.util.stream.Collectors; 17 | 18 | public class SpongeAudienceProvider extends AbstractAudienceProvider { 19 | 20 | private final ConfigurationHandler config; 21 | 22 | public SpongeAudienceProvider(final ConfigurationHandler config) { 23 | this.config = config; 24 | } 25 | 26 | @Override 27 | public @NotNull NamelessConsole console() { 28 | return new SpongeNamelessConsole(); 29 | } 30 | 31 | @Override 32 | public @NotNull Audience broadcast() { 33 | return Sponge.server().broadcastAudience(); 34 | } 35 | 36 | private @Nullable NamelessPlayer spongeToNamelessPlayer(final Optional optionalPlayer) { 37 | if (optionalPlayer.isPresent()) { 38 | final ServerPlayer player = optionalPlayer.get(); 39 | return new SpongeNamelessPlayer(this.config, player); 40 | } 41 | return null; 42 | } 43 | 44 | @Override 45 | public @Nullable NamelessPlayer player(final @NotNull UUID uuid) { 46 | return spongeToNamelessPlayer(Sponge.server().player(uuid)); 47 | } 48 | 49 | @Override 50 | public @Nullable NamelessPlayer playerByUsername(final @NotNull String username) { 51 | return spongeToNamelessPlayer(Sponge.server().player(username)); 52 | } 53 | 54 | @Override 55 | public @NotNull Collection<@NotNull NamelessPlayer> onlinePlayers() { 56 | return Sponge.server().onlinePlayers().stream() 57 | .map(p -> new SpongeNamelessPlayer(this.config, p)) 58 | .collect(Collectors.toUnmodifiableList()); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /sponge8/src/main/com/namelessmc/plugin/sponge8/audiences/SpongeNamelessConsole.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge8.audiences; 2 | 3 | import com.namelessmc.plugin.common.audiences.NamelessConsole; 4 | import org.spongepowered.api.Sponge; 5 | import org.spongepowered.api.command.exception.CommandException; 6 | 7 | public class SpongeNamelessConsole extends NamelessConsole { 8 | 9 | public SpongeNamelessConsole() { 10 | super(Sponge.systemSubject()); 11 | } 12 | 13 | @Override 14 | public void dispatchCommand(String command) { 15 | try { 16 | Sponge.server().commandManager().process(Sponge.systemSubject(), command); 17 | } catch (CommandException e) { 18 | throw new RuntimeException(e); 19 | } 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /sponge8/src/main/com/namelessmc/plugin/sponge8/audiences/SpongeNamelessPlayer.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge8.audiences; 2 | 3 | import com.namelessmc.plugin.common.ConfigurationHandler; 4 | import com.namelessmc.plugin.common.Permission; 5 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 6 | import org.apache.commons.lang3.NotImplementedException; 7 | import org.spongepowered.api.entity.living.player.Player; 8 | 9 | public class SpongeNamelessPlayer extends NamelessPlayer { 10 | 11 | private final Player player; 12 | 13 | public SpongeNamelessPlayer(final ConfigurationHandler config, 14 | final Player player) { 15 | super(config, player, player.uniqueId(), player.name()); 16 | this.player = player; 17 | } 18 | 19 | @Override 20 | public boolean hasPermission(Permission permission) { 21 | throw new NotImplementedException("How to check for permissions in sponge?"); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /sponge9/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | plugin-sponge9 7 | Nameless-Plugin-Sponge9 8 | 9 | 10 | com.namelessmc 11 | plugin 12 | ${revision} 13 | ../pom.xml 14 | 15 | 16 | 17 | src/main 18 | 19 | 20 | 21 | resources 22 | true 23 | 24 | 25 | 26 | 27 | 28 | org.apache.maven.plugins 29 | maven-shade-plugin 30 | 31 | 32 | 33 | com.github.mizosoft.methanol 34 | com.namelessmc.plugin.lib.methanol 35 | 36 | 37 | com.namelessmc.java_api 38 | com.namelessmc.plugin.lib.nameless-api 39 | 40 | 41 | net.kyori.event 42 | com.namelessmc.plugin.lib.event 43 | 44 | 45 | org.bstats 46 | com.namelessmc.plugin.lib.bstats 47 | 48 | 49 | org.checkerframework 50 | com.namelessmc.plugin.lib.checker-framework 51 | 52 | 53 | xyz.derkades.derkutils 54 | com.namelessmc.plugin.lib.derkutils 55 | 56 | 57 | 58 | 59 | 60 | package 61 | 62 | shade 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | com.namelessmc 74 | plugin-common 75 | 76 | 77 | 78 | net.kyori 79 | adventure-api 80 | 81 | 82 | net.kyori 83 | adventure-text-minimessage 84 | 85 | 86 | 87 | org.spongepowered 88 | configurate-yaml 89 | 90 | 91 | 92 | com.google.code.gson 93 | gson 94 | 95 | 96 | 97 | com.google.guava 98 | guava 99 | 100 | 101 | 102 | 103 | 104 | org.spongepowered 105 | spongeapi 106 | 9.0.0 107 | jar 108 | provided 109 | 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /sponge9/resources/sponge_plugins.json: -------------------------------------------------------------------------------- 1 | { 2 | "loader": { 3 | "name": "java_plain", 4 | "version": "1.0" 5 | }, 6 | "license": "MIT", 7 | "global": { 8 | "version": "@project.version@", 9 | "links": { 10 | "homepage": "https://namelessmc.com", 11 | "source": "https://github.com/NamelessMC/Nameless-Plugin/", 12 | "issues": "https://github.com/NamelessMC/Nameless-Plugin/issues" 13 | }, 14 | "contributors": [ 15 | { 16 | "name": "Derkades", 17 | "description": "Lead Developer" 18 | } 19 | ], 20 | "dependencies": [ 21 | { 22 | "id": "spongeapi", 23 | "version": "9.0.0" 24 | } 25 | ] 26 | }, 27 | "plugins": [ 28 | { 29 | "id": "namelessmc", 30 | "name": "NamelessMC", 31 | "entrypoint": "com.namelessmc.plugin.sponge9.SpongeNamelessPlugin", 32 | "description": "Integration with NamelessMC websites" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /sponge9/src/main/com/namelessmc/plugin/sponge9/Log4jLogger.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge9; 2 | 3 | import com.namelessmc.plugin.common.ConfigurationHandler; 4 | import com.namelessmc.plugin.common.logger.AbstractLogger; 5 | import org.apache.logging.log4j.Logger; 6 | import org.jetbrains.annotations.NotNull; 7 | 8 | import java.util.function.Supplier; 9 | 10 | public class Log4jLogger extends AbstractLogger { 11 | 12 | private final @NotNull Logger logger; 13 | 14 | public Log4jLogger(final @NotNull ConfigurationHandler config, 15 | final @NotNull Logger logger) { 16 | super(config); 17 | this.logger = logger; 18 | } 19 | 20 | @Override 21 | public void info(String string) { 22 | this.logger.info(string); 23 | } 24 | 25 | @Override 26 | public void warning(String string) { 27 | this.logger.warn(string); 28 | } 29 | 30 | @Override 31 | public void severe(String string) { 32 | this.logger.error(string); 33 | } 34 | 35 | @Override 36 | public void info(Supplier stringSupplier) { 37 | this.logger.info(stringSupplier); 38 | } 39 | 40 | @Override 41 | public void warning(Supplier stringSupplier) { 42 | this.logger.warn(stringSupplier); 43 | } 44 | 45 | @Override 46 | public void severe(Supplier stringSupplier) { 47 | this.logger.error(stringSupplier); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /sponge9/src/main/com/namelessmc/plugin/sponge9/SpongeDataSender.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge9; 2 | 3 | import com.namelessmc.plugin.common.AbstractDataSender; 4 | import com.namelessmc.plugin.common.NamelessPlugin; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | public class SpongeDataSender extends AbstractDataSender { 8 | 9 | protected SpongeDataSender(@NotNull NamelessPlugin plugin) { 10 | super(plugin); 11 | } 12 | 13 | @Override 14 | protected void registerCustomProviders() {} 15 | 16 | } 17 | -------------------------------------------------------------------------------- /sponge9/src/main/com/namelessmc/plugin/sponge9/SpongeEventProxy.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge9; 2 | 3 | import com.namelessmc.plugin.common.NamelessPlugin; 4 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 5 | import com.namelessmc.plugin.common.event.NamelessJoinEvent; 6 | import com.namelessmc.plugin.sponge9.audiences.SpongeNamelessPlayer; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.spongepowered.api.event.Listener; 9 | import org.spongepowered.api.event.network.ServerSideConnectionEvent; 10 | 11 | public class SpongeEventProxy { 12 | 13 | private final @NotNull NamelessPlugin plugin; 14 | 15 | SpongeEventProxy(final @NotNull NamelessPlugin plugin) { 16 | this.plugin = plugin; 17 | } 18 | 19 | @Listener 20 | public void onJoin(ServerSideConnectionEvent.Join event) { 21 | final NamelessPlayer player = new SpongeNamelessPlayer(this.plugin.config(), event.player()); 22 | this.plugin.events().post(new NamelessJoinEvent(player)); 23 | } 24 | 25 | // TODO quit event 26 | 27 | } 28 | -------------------------------------------------------------------------------- /sponge9/src/main/com/namelessmc/plugin/sponge9/SpongeNamelessPlugin.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge9; 2 | 3 | import com.google.inject.Inject; 4 | import com.namelessmc.plugin.common.NamelessPlugin; 5 | import com.namelessmc.plugin.sponge9.audiences.SpongeAudienceProvider; 6 | import org.apache.logging.log4j.Logger; 7 | import org.spongepowered.api.Server; 8 | import org.spongepowered.api.Sponge; 9 | import org.spongepowered.api.command.Command; 10 | import org.spongepowered.api.config.ConfigDir; 11 | import org.spongepowered.api.event.Listener; 12 | import org.spongepowered.api.event.lifecycle.RefreshGameEvent; 13 | import org.spongepowered.api.event.lifecycle.RegisterCommandEvent; 14 | import org.spongepowered.api.event.lifecycle.StartedEngineEvent; 15 | import org.spongepowered.plugin.PluginContainer; 16 | import org.spongepowered.plugin.builtin.jvm.Plugin; 17 | 18 | import java.nio.file.Path; 19 | 20 | @Plugin("namelessmc") 21 | public class SpongeNamelessPlugin { 22 | 23 | private final NamelessPlugin plugin; 24 | private final PluginContainer container; 25 | 26 | @Inject 27 | public SpongeNamelessPlugin(final @ConfigDir(sharedRoot = false) Path dataDirectory, 28 | final Logger logger, 29 | final PluginContainer container) { 30 | this.container = container; 31 | this.plugin = new NamelessPlugin( 32 | dataDirectory, 33 | new SpongeScheduler(container), 34 | config -> new Log4jLogger(config, logger), 35 | Path.of("logs", "latest.log"), 36 | "sponge9", 37 | Sponge.platform().minecraftVersion().name() 38 | ); 39 | this.plugin.setAudienceProvider(new SpongeAudienceProvider(this.plugin.config())); 40 | this.plugin.registerReloadable(new SpongeDataSender(this.plugin)); 41 | Sponge.eventManager().registerListeners(container, new SpongeEventProxy(this.plugin)); 42 | } 43 | 44 | @Listener 45 | public void registerCommands(final RegisterCommandEvent event) { 46 | SpongeCommandProxy commandProxy = new SpongeCommandProxy(this.plugin); 47 | commandProxy.registerCommands(event, this.container); 48 | } 49 | 50 | @Listener 51 | public void onStarted(final StartedEngineEvent event) { 52 | this.plugin.load(); 53 | } 54 | 55 | @Listener 56 | public void reload(final RefreshGameEvent event) { 57 | this.plugin.unload(); 58 | this.plugin.load(); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /sponge9/src/main/com/namelessmc/plugin/sponge9/SpongeScheduler.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge9; 2 | 3 | import com.namelessmc.plugin.common.command.AbstractScheduledTask; 4 | import com.namelessmc.plugin.common.command.AbstractScheduler; 5 | import org.checkerframework.checker.nullness.qual.NonNull; 6 | import org.spongepowered.api.Sponge; 7 | import org.spongepowered.api.scheduler.ScheduledTask; 8 | import org.spongepowered.api.scheduler.Task; 9 | import org.spongepowered.plugin.PluginContainer; 10 | 11 | import java.time.Duration; 12 | import java.util.concurrent.ExecutorService; 13 | import java.util.concurrent.Executors; 14 | import java.util.concurrent.TimeUnit; 15 | 16 | public class SpongeScheduler extends AbstractScheduler { 17 | 18 | private final PluginContainer spongePlugin; 19 | private final ExecutorService executor = Executors.newCachedThreadPool(); 20 | 21 | SpongeScheduler(final PluginContainer spongePlugin) { 22 | this.spongePlugin = spongePlugin; 23 | } 24 | 25 | @Override 26 | public void runAsync(final @NonNull Runnable runnable) { 27 | // Sponge probably provides an API for async tasks, but I couldn't find it. Use Java ExecutorService instead. 28 | executor.submit(runnable); 29 | } 30 | 31 | @Override 32 | public void runSync(final @NonNull Runnable runnable) { 33 | final Task task = Task.builder() 34 | .plugin(spongePlugin) 35 | .execute(runnable) 36 | .build(); 37 | Sponge.server().scheduler().submit(task); 38 | } 39 | 40 | @Override 41 | public @NonNull SpongeScheduledTask runTimer(@NonNull Runnable runnable, @NonNull Duration interval) { 42 | final Task task = Task.builder() 43 | .plugin(spongePlugin) 44 | .execute(runnable) 45 | .delay(interval.toNanos(), TimeUnit.NANOSECONDS) 46 | .interval(interval.toNanos(), TimeUnit.NANOSECONDS) 47 | .build(); 48 | return new SpongeScheduledTask(Sponge.server().scheduler().submit(task)); 49 | } 50 | 51 | @Override 52 | public @NonNull SpongeScheduledTask runDelayed(@NonNull Runnable runnable, @NonNull Duration delay) { 53 | final Task task = Task.builder() 54 | .plugin(spongePlugin) 55 | .execute(runnable) 56 | .delay(delay.toNanos(), TimeUnit.NANOSECONDS) 57 | .build(); 58 | return new SpongeScheduledTask(Sponge.server().scheduler().submit(task)); 59 | } 60 | 61 | public static class SpongeScheduledTask extends AbstractScheduledTask { 62 | 63 | private final ScheduledTask task; 64 | 65 | private SpongeScheduledTask(final ScheduledTask task) { 66 | this.task = task; 67 | } 68 | 69 | @Override 70 | public void cancel() { 71 | this.task.cancel(); 72 | } 73 | 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /sponge9/src/main/com/namelessmc/plugin/sponge9/audiences/SpongeAudienceProvider.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge9.audiences; 2 | 3 | import com.namelessmc.plugin.common.ConfigurationHandler; 4 | import com.namelessmc.plugin.common.audiences.AbstractAudienceProvider; 5 | import com.namelessmc.plugin.common.audiences.NamelessConsole; 6 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 7 | import net.kyori.adventure.audience.Audience; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.jetbrains.annotations.Nullable; 10 | import org.spongepowered.api.Sponge; 11 | import org.spongepowered.api.entity.living.player.server.ServerPlayer; 12 | 13 | import java.util.Collection; 14 | import java.util.Optional; 15 | import java.util.UUID; 16 | import java.util.stream.Collectors; 17 | 18 | public class SpongeAudienceProvider extends AbstractAudienceProvider { 19 | 20 | private final ConfigurationHandler config; 21 | 22 | public SpongeAudienceProvider(final ConfigurationHandler config) { 23 | this.config = config; 24 | } 25 | 26 | @Override 27 | public @NotNull NamelessConsole console() { 28 | return new SpongeNamelessConsole(); 29 | } 30 | 31 | @Override 32 | public @NotNull Audience broadcast() { 33 | return Sponge.server().broadcastAudience(); 34 | } 35 | 36 | private @Nullable NamelessPlayer spongeToNamelessPlayer(final Optional optionalPlayer) { 37 | if (optionalPlayer.isPresent()) { 38 | final ServerPlayer player = optionalPlayer.get(); 39 | return new SpongeNamelessPlayer(this.config, player); 40 | } 41 | return null; 42 | } 43 | 44 | @Override 45 | public @Nullable NamelessPlayer player(final @NotNull UUID uuid) { 46 | return spongeToNamelessPlayer(Sponge.server().player(uuid)); 47 | } 48 | 49 | @Override 50 | public @Nullable NamelessPlayer playerByUsername(final @NotNull String username) { 51 | return spongeToNamelessPlayer(Sponge.server().player(username)); 52 | } 53 | 54 | @Override 55 | public @NotNull Collection<@NotNull NamelessPlayer> onlinePlayers() { 56 | return Sponge.server().onlinePlayers().stream() 57 | .map(p -> new SpongeNamelessPlayer(this.config, p)) 58 | .collect(Collectors.toUnmodifiableList()); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /sponge9/src/main/com/namelessmc/plugin/sponge9/audiences/SpongeNamelessConsole.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge9.audiences; 2 | 3 | import com.namelessmc.plugin.common.audiences.NamelessConsole; 4 | import org.spongepowered.api.Sponge; 5 | import org.spongepowered.api.command.exception.CommandException; 6 | 7 | public class SpongeNamelessConsole extends NamelessConsole { 8 | 9 | public SpongeNamelessConsole() { 10 | super(Sponge.systemSubject()); 11 | } 12 | 13 | @Override 14 | public void dispatchCommand(String command) { 15 | try { 16 | Sponge.server().commandManager().process(Sponge.systemSubject(), command); 17 | } catch (CommandException e) { 18 | throw new RuntimeException(e); 19 | } 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /sponge9/src/main/com/namelessmc/plugin/sponge9/audiences/SpongeNamelessPlayer.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.sponge9.audiences; 2 | 3 | import com.namelessmc.plugin.common.ConfigurationHandler; 4 | import com.namelessmc.plugin.common.Permission; 5 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 6 | import org.apache.commons.lang3.NotImplementedException; 7 | import org.spongepowered.api.entity.living.player.Player; 8 | 9 | public class SpongeNamelessPlayer extends NamelessPlayer { 10 | 11 | private final Player player; 12 | 13 | public SpongeNamelessPlayer(final ConfigurationHandler config, 14 | final Player player) { 15 | super(config, player, player.uniqueId(), player.name()); 16 | this.player = player; 17 | } 18 | 19 | @Override 20 | public boolean hasPermission(Permission permission) { 21 | throw new NotImplementedException("How to check for permissions in sponge?"); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /velocity/src/main/com/namelessmc/plugin/velocity/Slf4jLogger.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.velocity; 2 | 3 | import com.namelessmc.plugin.common.ConfigurationHandler; 4 | import com.namelessmc.plugin.common.logger.AbstractLogger; 5 | import org.checkerframework.checker.nullness.qual.NonNull; 6 | import org.slf4j.Logger; 7 | 8 | import java.util.function.Supplier; 9 | 10 | public class Slf4jLogger extends AbstractLogger { 11 | 12 | private final @NonNull Logger logger; 13 | 14 | public Slf4jLogger(final @NonNull ConfigurationHandler config, 15 | final @NonNull Logger logger) { 16 | super(config); 17 | this.logger = logger; 18 | } 19 | 20 | @Override 21 | public void info(String string) { 22 | this.logger.info(string); 23 | } 24 | 25 | @Override 26 | public void warning(String string) { 27 | this.logger.warn(string); 28 | } 29 | 30 | @Override 31 | public void severe(String string) { 32 | this.logger.error(string); 33 | } 34 | 35 | @Override 36 | public void info(Supplier stringSupplier) { 37 | if (this.logger.isInfoEnabled()) { 38 | this.logger.info(stringSupplier.get()); 39 | } 40 | } 41 | 42 | @Override 43 | public void warning(Supplier stringSupplier) { 44 | if (this.logger.isWarnEnabled()) { 45 | this.logger.warn(stringSupplier.get()); 46 | } 47 | } 48 | 49 | @Override 50 | public void severe(Supplier stringSupplier) { 51 | if (this.logger.isErrorEnabled()) { 52 | this.logger.error(stringSupplier.get()); 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /velocity/src/main/com/namelessmc/plugin/velocity/VelocityCommandProxy.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.velocity; 2 | 3 | import com.namelessmc.plugin.common.NamelessPlugin; 4 | import com.namelessmc.plugin.common.audiences.AbstractAudienceProvider; 5 | import com.namelessmc.plugin.common.audiences.NamelessCommandSender; 6 | import com.namelessmc.plugin.common.command.CommonCommand; 7 | import com.velocitypowered.api.command.Command; 8 | import com.velocitypowered.api.command.CommandMeta; 9 | import com.velocitypowered.api.command.CommandSource; 10 | import com.velocitypowered.api.command.SimpleCommand; 11 | import com.velocitypowered.api.proxy.Player; 12 | import com.velocitypowered.api.proxy.ProxyServer; 13 | 14 | import net.kyori.adventure.text.Component; 15 | 16 | public class VelocityCommandProxy { 17 | 18 | static void registerCommands(final VelocityNamelessPlugin velocityPlugin, NamelessPlugin plugin, final ProxyServer server) { 19 | CommonCommand.commands(plugin).forEach(command -> { 20 | final String name = command.actualName(); 21 | if (name == null) { 22 | // Command is disabled 23 | return; 24 | } 25 | 26 | Command velocityCommand = new VelocityCommand(command, plugin.audiences()); 27 | CommandMeta meta = server.getCommandManager().metaBuilder(name).plugin(velocityPlugin).build(); 28 | server.getCommandManager().register(meta, velocityCommand); 29 | }); 30 | } 31 | 32 | private static class VelocityCommand implements SimpleCommand { 33 | 34 | private final CommonCommand command; 35 | private final String permission; 36 | private final AbstractAudienceProvider audiences; 37 | 38 | private VelocityCommand(final CommonCommand command, final AbstractAudienceProvider audiences) { 39 | this.command = command; 40 | this.permission = command.permission().toString(); 41 | this.audiences = audiences; 42 | } 43 | 44 | @Override 45 | public void execute(final SimpleCommand.Invocation invocation) { 46 | final CommandSource source = invocation.source(); 47 | final NamelessCommandSender namelessSender; 48 | if (source instanceof Player) { 49 | namelessSender = this.audiences.player(((Player) source).getUniqueId()); 50 | } else { 51 | namelessSender = this.audiences.console(); 52 | } 53 | 54 | if (namelessSender == null) { 55 | source.sendMessage(Component.text("Couldn't obtain audience for your command source")); 56 | return; 57 | } 58 | 59 | command.verifyPermissionThenExecute(namelessSender, invocation.arguments()); 60 | } 61 | 62 | @Override 63 | public boolean hasPermission(final SimpleCommand.Invocation invocation) { 64 | return invocation.source().hasPermission(this.permission); 65 | } 66 | 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /velocity/src/main/com/namelessmc/plugin/velocity/VelocityDataSender.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.velocity; 2 | 3 | import com.namelessmc.plugin.common.AbstractDataSender; 4 | import com.namelessmc.plugin.common.NamelessPlugin; 5 | import com.velocitypowered.api.proxy.ProxyServer; 6 | 7 | public class VelocityDataSender extends AbstractDataSender { 8 | 9 | private final ProxyServer server; 10 | 11 | protected VelocityDataSender(final NamelessPlugin plugin, final ProxyServer server) { 12 | super(plugin); 13 | this.server = server; 14 | } 15 | 16 | @Override 17 | protected void registerCustomProviders() { 18 | this.registerGlobalInfoProvider(json -> 19 | json.addProperty("max_players", server.getConfiguration().getShowMaxPlayers())); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /velocity/src/main/com/namelessmc/plugin/velocity/VelocityEventProxy.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.velocity; 2 | 3 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 4 | import com.namelessmc.plugin.common.NamelessPlugin; 5 | import com.namelessmc.plugin.common.event.NamelessJoinEvent; 6 | import com.velocitypowered.api.event.Subscribe; 7 | import com.velocitypowered.api.event.player.ServerConnectedEvent; 8 | import org.checkerframework.checker.nullness.qual.NonNull; 9 | 10 | public class VelocityEventProxy { 11 | 12 | private final @NonNull NamelessPlugin plugin; 13 | 14 | VelocityEventProxy(final @NonNull NamelessPlugin plugin) { 15 | this.plugin = plugin; 16 | } 17 | 18 | @Subscribe 19 | public void onJoin(final @NonNull ServerConnectedEvent event) { 20 | final NamelessPlayer player = this.plugin.audiences().player(event.getPlayer().getUniqueId()); 21 | if (player == null) { 22 | this.plugin.logger().severe("Skipped join event for player " + event.getPlayer().getUsername() + 23 | ", Audience is null"); 24 | return; 25 | } 26 | final NamelessJoinEvent event2 = new NamelessJoinEvent(player); 27 | this.plugin.events().post(event2); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /velocity/src/main/com/namelessmc/plugin/velocity/VelocityNamelessPlugin.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.velocity; 2 | 3 | import com.google.inject.Inject; 4 | import com.namelessmc.plugin.common.MavenConstants; 5 | import com.namelessmc.plugin.common.NamelessPlugin; 6 | import com.namelessmc.plugin.velocity.audiences.VelocityAudienceProvider; 7 | import com.velocitypowered.api.event.Subscribe; 8 | import com.velocitypowered.api.event.proxy.ProxyInitializeEvent; 9 | import com.velocitypowered.api.event.proxy.ProxyReloadEvent; 10 | import com.velocitypowered.api.plugin.Plugin; 11 | import com.velocitypowered.api.plugin.annotation.DataDirectory; 12 | import com.velocitypowered.api.proxy.ProxyServer; 13 | import org.bstats.velocity.Metrics; 14 | import org.checkerframework.checker.nullness.qual.NonNull; 15 | import org.slf4j.Logger; 16 | 17 | import java.nio.file.Path; 18 | 19 | @Plugin(id = "namelessmc", 20 | name = "NamelessMC", 21 | version = MavenConstants.PROJECT_VERSION, 22 | url = "https://plugin.namelessmc.com/", 23 | description = "Integration with NamelessMC websites", 24 | authors = {"Derkades"}) 25 | public class VelocityNamelessPlugin { 26 | 27 | private final Metrics.@NonNull Factory metricsFactory; 28 | private final @NonNull ProxyServer server; 29 | private final @NonNull NamelessPlugin plugin; 30 | 31 | @Inject 32 | public VelocityNamelessPlugin(final @NonNull ProxyServer server, 33 | final @NonNull Logger logger, 34 | final @DataDirectory @NonNull Path dataDirectory, 35 | final Metrics.@NonNull Factory metricsFactory) { 36 | this.server = server; 37 | this.metricsFactory = metricsFactory; 38 | this.plugin = new NamelessPlugin( 39 | dataDirectory, 40 | new VelocityScheduler(this, server.getScheduler()), 41 | config -> new Slf4jLogger(config, logger), 42 | Path.of("logs", "latest.log"), 43 | "velocity", 44 | server.getVersion().getVersion() 45 | ); 46 | this.plugin.setAudienceProvider(new VelocityAudienceProvider(this.plugin.config(), server)); 47 | this.plugin.registerReloadable(new VelocityDataSender(this.plugin, this.server)); 48 | } 49 | 50 | @Subscribe 51 | public void onProxyInitialization(final ProxyInitializeEvent event) { 52 | this.plugin.load(); 53 | this.server.getEventManager().register(this, new VelocityEventProxy(this.plugin)); 54 | metricsFactory.make(this, 14863); 55 | VelocityCommandProxy.registerCommands(this, this.plugin, server); 56 | } 57 | 58 | // TODO call unload() when proxy server shuts down 59 | 60 | @Subscribe 61 | public void onReload(final ProxyReloadEvent event) { 62 | this.plugin.unload(); 63 | this.plugin.load(); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /velocity/src/main/com/namelessmc/plugin/velocity/VelocityScheduler.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.velocity; 2 | 3 | import com.namelessmc.plugin.common.command.AbstractScheduledTask; 4 | import com.namelessmc.plugin.common.command.AbstractScheduler; 5 | import com.velocitypowered.api.scheduler.ScheduledTask; 6 | import com.velocitypowered.api.scheduler.Scheduler; 7 | import org.checkerframework.checker.nullness.qual.NonNull; 8 | 9 | import java.time.Duration; 10 | import java.util.concurrent.TimeUnit; 11 | 12 | public class VelocityScheduler extends AbstractScheduler { 13 | 14 | private final @NonNull VelocityNamelessPlugin plugin; 15 | private final @NonNull Scheduler scheduler; 16 | 17 | VelocityScheduler(final @NonNull VelocityNamelessPlugin plugin, 18 | final @NonNull Scheduler scheduler) { 19 | this.plugin = plugin; 20 | this.scheduler = scheduler; 21 | } 22 | 23 | @Override 24 | public void runAsync(final @NonNull Runnable runnable) { 25 | this.scheduler 26 | .buildTask(this.plugin, runnable) 27 | .schedule(); 28 | } 29 | 30 | @Override 31 | public void runSync(final @NonNull Runnable runnable) { 32 | // Velocity has no "main thread", we can just run it in the current thread 33 | runnable.run(); 34 | } 35 | 36 | @Override 37 | public @NonNull VelocityScheduledTask runTimer(@NonNull Runnable runnable, @NonNull Duration interval) { 38 | final ScheduledTask task = this.scheduler 39 | .buildTask(this.plugin, runnable) 40 | .delay(interval.toNanos(), TimeUnit.NANOSECONDS) 41 | .repeat(interval.toNanos(), TimeUnit.NANOSECONDS) 42 | .schedule(); 43 | return new VelocityScheduledTask(task); 44 | } 45 | 46 | @Override 47 | public @NonNull VelocityScheduledTask runDelayed(@NonNull Runnable runnable, @NonNull Duration delay) { 48 | final ScheduledTask task = this.scheduler 49 | .buildTask(this.plugin, runnable) 50 | .delay(delay.toNanos(), TimeUnit.NANOSECONDS) 51 | .schedule(); 52 | return new VelocityScheduledTask(task); 53 | } 54 | 55 | public static class VelocityScheduledTask extends AbstractScheduledTask { 56 | 57 | private final @NonNull ScheduledTask task; 58 | 59 | private VelocityScheduledTask(final @NonNull ScheduledTask task) { 60 | this.task = task; 61 | } 62 | 63 | @Override 64 | public void cancel() { 65 | this.task.cancel(); 66 | } 67 | 68 | } 69 | 70 | 71 | } 72 | -------------------------------------------------------------------------------- /velocity/src/main/com/namelessmc/plugin/velocity/audiences/VelocityAudienceProvider.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.velocity.audiences; 2 | 3 | import com.namelessmc.plugin.common.ConfigurationHandler; 4 | import com.namelessmc.plugin.common.audiences.AbstractAudienceProvider; 5 | import com.namelessmc.plugin.common.audiences.NamelessConsole; 6 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 7 | import com.velocitypowered.api.proxy.Player; 8 | import com.velocitypowered.api.proxy.ProxyServer; 9 | import net.kyori.adventure.audience.Audience; 10 | import org.checkerframework.checker.nullness.qual.NonNull; 11 | import org.checkerframework.checker.nullness.qual.Nullable; 12 | 13 | import java.util.*; 14 | import java.util.stream.Collectors; 15 | 16 | public class VelocityAudienceProvider extends AbstractAudienceProvider { 17 | 18 | private final ConfigurationHandler config; 19 | private final ProxyServer server; 20 | 21 | public VelocityAudienceProvider(final ConfigurationHandler config, 22 | final ProxyServer server) { 23 | this.config = config; 24 | this.server = server; 25 | } 26 | 27 | @Override 28 | public @NonNull NamelessConsole console() { 29 | return new VelocityNamelessConsole(this.server); 30 | } 31 | 32 | @Override 33 | public @NonNull Audience broadcast() { 34 | final Collection players = server.getAllPlayers(); 35 | final List everyone = new ArrayList<>(players.size() + 1); 36 | everyone.addAll(players); 37 | everyone.add(server.getConsoleCommandSource()); 38 | return Audience.audience(everyone); 39 | } 40 | 41 | private @Nullable NamelessPlayer velocityToNamelessPlayer(final Optional optionalPlayer) { 42 | if (optionalPlayer.isEmpty()) { 43 | return null; 44 | } 45 | 46 | Player player = optionalPlayer.get(); 47 | return new VelocityNamelessPlayer(this.config, player); 48 | } 49 | 50 | @Override 51 | public @Nullable NamelessPlayer player(final @NonNull UUID uuid) { 52 | return velocityToNamelessPlayer(server.getPlayer(uuid)); 53 | } 54 | 55 | @Override 56 | public @Nullable NamelessPlayer playerByUsername(@NonNull String username) { 57 | return velocityToNamelessPlayer(server.getPlayer(username)); 58 | } 59 | 60 | @Override 61 | public @NonNull Collection<@NonNull NamelessPlayer> onlinePlayers() { 62 | return server.getAllPlayers().stream() 63 | .map(p -> new VelocityNamelessPlayer(this.config, p)) 64 | .collect(Collectors.toUnmodifiableList()); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /velocity/src/main/com/namelessmc/plugin/velocity/audiences/VelocityNamelessConsole.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.velocity.audiences; 2 | 3 | import com.namelessmc.plugin.common.audiences.NamelessConsole; 4 | import com.velocitypowered.api.permission.Tristate; 5 | import com.velocitypowered.api.proxy.ConsoleCommandSource; 6 | import com.velocitypowered.api.proxy.ProxyServer; 7 | 8 | public class VelocityNamelessConsole extends NamelessConsole implements ConsoleCommandSource { 9 | 10 | private final ProxyServer server; 11 | 12 | public VelocityNamelessConsole(ProxyServer server) { 13 | super(server.getConsoleCommandSource()); 14 | this.server = server; 15 | } 16 | 17 | @Override 18 | public void dispatchCommand(String command) { 19 | this.server.getCommandManager().executeAsync(this, command); 20 | } 21 | 22 | @Override 23 | public Tristate getPermissionValue(String permission) { 24 | return Tristate.TRUE; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /velocity/src/main/com/namelessmc/plugin/velocity/audiences/VelocityNamelessPlayer.java: -------------------------------------------------------------------------------- 1 | package com.namelessmc.plugin.velocity.audiences; 2 | 3 | import com.namelessmc.plugin.common.ConfigurationHandler; 4 | import com.namelessmc.plugin.common.Permission; 5 | import com.namelessmc.plugin.common.audiences.NamelessPlayer; 6 | import com.velocitypowered.api.proxy.Player; 7 | 8 | public class VelocityNamelessPlayer extends NamelessPlayer { 9 | 10 | private final Player player; 11 | 12 | public VelocityNamelessPlayer(final ConfigurationHandler config, 13 | final Player player) { 14 | super(config, player, player.getUniqueId(), player.getUsername()); 15 | this.player = player; 16 | } 17 | 18 | @Override 19 | public boolean hasPermission(Permission permission) { 20 | return this.player.hasPermission(permission.toString()); 21 | } 22 | 23 | } 24 | --------------------------------------------------------------------------------