├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── feature.yml │ └── bug.yml └── workflows │ ├── maven.yml │ └── release.yml ├── src └── main │ ├── resources │ ├── migrations │ │ ├── V2__feature_chat_formatting.sql │ │ └── V1__initial_tables.sql │ ├── plugin.yml │ └── config.yml │ └── java │ └── net │ └── pandadev │ └── nextron │ ├── arguments │ ├── objects │ │ ├── Home.java │ │ ├── Warp.java │ │ ├── Feature.java │ │ ├── Seed.java │ │ ├── Rank.java │ │ ├── Language.java │ │ └── Help.java │ ├── SeedArgument.java │ ├── HelpArgument.java │ ├── WarpArgument.java │ ├── FeatureArgument.java │ ├── GameModeArgument.java │ ├── HomeArgument.java │ ├── RankArgument.java │ └── LanguageArgument.java │ ├── commands │ ├── MenuCommand.java │ ├── HatCommand.java │ ├── InvseeCommand.java │ ├── ReloadCommand.java │ ├── SudoCommand.java │ ├── NickCommand.java │ ├── EnderchestCommand.java │ ├── RenameCommand.java │ ├── TopCommand.java │ ├── TphereCommand.java │ ├── TpdenyCommand.java │ ├── HelpBase.java │ ├── PingCommand.java │ ├── HeadCommand.java │ ├── BackCommand.java │ ├── LanguageCommand.java │ ├── GodCommand.java │ ├── TpacceptCommand.java │ ├── TimeCommand.java │ ├── FlyCommand.java │ ├── NightVisionCommand.java │ ├── GetPosCommand.java │ ├── HealCommand.java │ ├── SpeedCommand.java │ ├── HelpCommand.java │ ├── SpawnCommand.java │ ├── RepairCommand.java │ ├── TpaCommand.java │ ├── TpahereCommand.java │ ├── FeatureCommand.java │ ├── RankCommand.java │ ├── WarpCommands.java │ ├── VanishCommand.java │ ├── HomeCommands.java │ ├── GamemodeCommand.java │ └── WorldCommand.java │ ├── utils │ ├── FileConfig.java │ ├── Utils.java │ ├── Placeholders.java │ ├── ItemBuilder.java │ └── UpdateChecker.java │ ├── listeners │ ├── BackCommandListener.java │ ├── InputListener.java │ ├── ChatEditor.java │ ├── QuitListener.java │ ├── JoinListener.java │ └── ClickableMessages.java │ ├── tablist │ └── TablistManager.java │ ├── database │ ├── Config.java │ └── Migrations.java │ ├── languages │ ├── TextAPI.java │ └── LanguageLoader.java │ ├── apis │ ├── VanishAPI.java │ ├── FeatureAPI.java │ ├── WarpAPI.java │ └── HomeAPI.java │ ├── guis │ └── features │ │ ├── HomeGUIs.java │ │ └── WarpGUIs.java │ └── Main.java ├── LICENCE ├── .gitignore ├── README.md └── pom.xml /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: 0pandadev 2 | -------------------------------------------------------------------------------- /src/main/resources/migrations/V2__feature_chat_formatting.sql: -------------------------------------------------------------------------------- 1 | -- Insert default value for chat_formatting_system 2 | INSERT INTO features (name, state) VALUES ('chat_formatting_system', TRUE); 3 | -------------------------------------------------------------------------------- /src/main/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | name: '${project.artifactId}' 2 | version: '${project.version}' 3 | main: net.pandadev.nextron.Main 4 | api-version: 1.13 5 | authors: [ PandaDEV ] 6 | description: '${project.description}' 7 | website: '${project.url}' 8 | softdepend: [ PlaceholderAPI ] -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/arguments/objects/Home.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.arguments.objects; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public class Home { 7 | private final String name; 8 | 9 | public Home(String name) { 10 | this.name = name; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/arguments/objects/Warp.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.arguments.objects; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public class Warp { 7 | private final String name; 8 | 9 | public Warp(String name) { 10 | this.name = name; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/arguments/objects/Feature.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.arguments.objects; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public class Feature { 7 | private final String name; 8 | 9 | public Feature(String name) { 10 | this.name = name; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/arguments/objects/Seed.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.arguments.objects; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public class Seed { 7 | // Getter 8 | private final long seed; 9 | 10 | public Seed(long seed) { 11 | this.seed = seed; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/arguments/objects/Rank.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.arguments.objects; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public class Rank { 7 | // Getter 8 | private final String name; 9 | 10 | public Rank(String name) { 11 | this.name = name; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/resources/config.yml: -------------------------------------------------------------------------------- 1 | # currently available en, de 2 | language: "en" 3 | 4 | # %p represents the players name 5 | # for a full color pallet take a look here https://htmlcolorcodes.com/minecraft-color-codes/ 6 | join_message: "&2[&a+&2] &7%p" 7 | leave_message: "&4[&c-&4] &7%p" 8 | 9 | # the prefix of the default player rank leave it empty for no prefix 10 | playerRankPrefix: "§9Player §8• §7" -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/arguments/objects/Language.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.arguments.objects; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public class Language { 7 | private final String language; 8 | 9 | public Language(String language) { 10 | this.language = language; 11 | } 12 | 13 | public String getName() { 14 | return language; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature.yml: -------------------------------------------------------------------------------- 1 | name: "\U0001F4A1 Feature request" 2 | description: Suggest an idea for Nextron 3 | labels: [Feature] 4 | assignees: 5 | - 0PandaDEV 6 | body: 7 | # 8 | - type: markdown 9 | attributes: 10 | value: | 11 | Thanks for taking the time to fill out this feature request! 12 | # 13 | - type: textarea 14 | id: description 15 | attributes: 16 | label: Describe your requested feature 17 | description: Give as many details as possible about your feature idea. 18 | validations: 19 | required: true -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/arguments/objects/Help.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.arguments.objects; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public class Help { 7 | private final String command; 8 | private final String name; 9 | private final String description; 10 | private final String usage; 11 | 12 | public Help(String command, String name, String description, String usage) { 13 | this.command = command; 14 | this.name = name; 15 | this.description = description; 16 | this.usage = usage; 17 | } 18 | 19 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/MenuCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.command.Command; 4 | import dev.rollczi.litecommands.annotations.context.Context; 5 | import dev.rollczi.litecommands.annotations.execute.Execute; 6 | import net.pandadev.nextron.guis.GUIs; 7 | import org.bukkit.Sound; 8 | import org.bukkit.entity.Player; 9 | 10 | @Command(name = "menu", aliases = {"m"}) 11 | public class MenuCommand extends HelpBase { 12 | 13 | public MenuCommand() { 14 | super("menu, Opens the menu where you can simply do everything, /menu\n/m"); 15 | } 16 | 17 | @Execute 18 | public void menuCommand(@Context Player player) { 19 | GUIs.mainGui(player); 20 | player.playSound(player.getLocation(), Sound.BLOCK_BARREL_OPEN, 100, 1); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/utils/FileConfig.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.utils; 2 | 3 | import org.bukkit.configuration.InvalidConfigurationException; 4 | import org.bukkit.configuration.file.YamlConfiguration; 5 | 6 | import java.io.IOException; 7 | 8 | public class FileConfig extends YamlConfiguration { 9 | 10 | private final String path; 11 | 12 | public FileConfig(String folder, String filname) { 13 | this.path = "plugins/" + folder + "/" + filname; 14 | 15 | try { 16 | load(this.path); 17 | } catch (InvalidConfigurationException | IOException ex) { 18 | ex.printStackTrace(); 19 | } 20 | } 21 | 22 | public FileConfig(String filname) { 23 | this("LobbySystem", filname); 24 | } 25 | 26 | public void saveConfig() { 27 | try { 28 | save(this.path); 29 | } catch (IOException ex) { 30 | ex.printStackTrace(); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/arguments/SeedArgument.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.arguments; 2 | 3 | import dev.rollczi.litecommands.argument.Argument; 4 | import dev.rollczi.litecommands.argument.parser.ParseResult; 5 | import dev.rollczi.litecommands.argument.resolver.ArgumentResolver; 6 | import dev.rollczi.litecommands.invocation.Invocation; 7 | import net.pandadev.nextron.Main; 8 | import net.pandadev.nextron.arguments.objects.Seed; 9 | import net.pandadev.nextron.languages.TextAPI; 10 | import org.bukkit.command.CommandSender; 11 | 12 | public class SeedArgument extends ArgumentResolver { 13 | 14 | @Override 15 | protected ParseResult parse(Invocation invocation, Argument argument, String s) { 16 | long seed; 17 | try { 18 | seed = Long.parseLong(s); 19 | } catch (NumberFormatException e) { 20 | return ParseResult.failure(Main.getPrefix() + TextAPI.get("world.create.seed.error")); 21 | } 22 | return ParseResult.success(new Seed(seed)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/HatCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.command.Command; 4 | import dev.rollczi.litecommands.annotations.context.Context; 5 | import dev.rollczi.litecommands.annotations.execute.Execute; 6 | import dev.rollczi.litecommands.annotations.permission.Permission; 7 | import net.pandadev.nextron.Main; 8 | import net.pandadev.nextron.languages.TextAPI; 9 | import org.bukkit.entity.Player; 10 | import org.bukkit.inventory.ItemStack; 11 | 12 | @Command(name = "hat", aliases = {"wear"}) 13 | @Permission("nextron.hat") 14 | public class HatCommand extends HelpBase { 15 | 16 | public HatCommand() { 17 | super("hat, Wear the current item in your hand, /hat\n/wear"); 18 | } 19 | 20 | @Execute 21 | public void hatCommand(@Context Player player) { 22 | ItemStack itemStack = player.getInventory().getItemInMainHand(); 23 | 24 | player.getInventory().setHelmet(itemStack); 25 | 26 | player.sendMessage(Main.getPrefix() + TextAPI.get("hat.success")); 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/utils/Utils.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.utils; 2 | 3 | public class Utils { 4 | 5 | public static int countWords(String s) { 6 | 7 | int wordCount = 0; 8 | 9 | boolean word = false; 10 | int endOfLine = s.length() - 1; 11 | 12 | for (int i = 0; i < s.length(); i++) { 13 | // if the char is a letter, word = true. 14 | if (Character.isLetter(s.charAt(i)) && i != endOfLine) { 15 | word = true; 16 | // if char isn't a letter and there have been letters before, 17 | // counter goes up. 18 | } else if (!Character.isLetter(s.charAt(i)) && word) { 19 | wordCount++; 20 | word = false; 21 | // last word of String; if it doesn't end with a non letter, it 22 | // wouldn't count without this. 23 | } else if (Character.isLetter(s.charAt(i)) && i == endOfLine) { 24 | wordCount++; 25 | } 26 | } 27 | return wordCount; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 PandaDEV 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/InvseeCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.argument.Arg; 4 | import dev.rollczi.litecommands.annotations.command.Command; 5 | import dev.rollczi.litecommands.annotations.context.Context; 6 | import dev.rollczi.litecommands.annotations.execute.Execute; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.pandadev.nextron.Main; 9 | import net.pandadev.nextron.languages.TextAPI; 10 | import org.bukkit.entity.Player; 11 | 12 | @Command(name = "invsee") 13 | @Permission("nextron.invsee") 14 | public class InvseeCommand extends HelpBase { 15 | 16 | public InvseeCommand() { 17 | super("invsee, Lets you inspect and control another player's inventory, /invsee "); 18 | } 19 | 20 | @Execute 21 | public void invseeCommand(@Context Player player, @Arg Player target) { 22 | if (target != player) { 23 | player.openInventory(target.getInventory()); 24 | } else { 25 | player.sendMessage(Main.getPrefix() + TextAPI.get("invsee.error")); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/listeners/BackCommandListener.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.listeners; 2 | 3 | import net.pandadev.nextron.apis.SettingsAPI; 4 | import org.bukkit.entity.Player; 5 | import org.bukkit.event.EventHandler; 6 | import org.bukkit.event.Listener; 7 | import org.bukkit.event.entity.PlayerDeathEvent; 8 | import org.bukkit.event.player.PlayerTeleportEvent; 9 | 10 | public class BackCommandListener implements Listener { 11 | 12 | @EventHandler 13 | public void onDeath(PlayerDeathEvent event) { 14 | Player player = event.getEntity(); 15 | SettingsAPI.setLastPosition(player, player.getLocation()); 16 | } 17 | 18 | @EventHandler 19 | public void onTeleport(PlayerTeleportEvent event) { 20 | Player player = event.getPlayer(); 21 | if (event.getCause() != PlayerTeleportEvent.TeleportCause.EXIT_BED && event.getCause() != PlayerTeleportEvent.TeleportCause.DISMOUNT) { 22 | if (!SettingsAPI.getBack(player)) { 23 | SettingsAPI.setLastPosition(player, event.getFrom()); 24 | } 25 | } 26 | if (SettingsAPI.getBack(event.getPlayer())) SettingsAPI.setBack(event.getPlayer(), false); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/ReloadCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.command.Command; 4 | import dev.rollczi.litecommands.annotations.execute.Execute; 5 | import dev.rollczi.litecommands.annotations.permission.Permission; 6 | import net.pandadev.nextron.Main; 7 | import org.bukkit.Bukkit; 8 | 9 | @Command(name = "rl", aliases = {"reload"}) 10 | @Permission("nextron.reload") 11 | public class ReloadCommand extends HelpBase { 12 | 13 | public ReloadCommand() { 14 | super("rl, Reloads the server, /rl\n/reload"); 15 | } 16 | 17 | @Execute 18 | public void reloadCommand() { 19 | Bukkit.broadcastMessage(Main.getPrefix() + "§cReloading server"); 20 | 21 | Bukkit.getScheduler().runTask(Main.getInstance(), () -> { 22 | try { 23 | Bukkit.getServer().reload(); 24 | Bukkit.broadcastMessage(Main.getPrefix() + "§aReload complete"); 25 | } catch (Exception e) { 26 | Bukkit.broadcastMessage(Main.getPrefix() + "§cReload failed. Check console for details."); 27 | e.printStackTrace(); 28 | } 29 | }); 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/listeners/InputListener.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.listeners; 2 | 3 | import org.bukkit.entity.Player; 4 | import org.bukkit.event.EventHandler; 5 | import org.bukkit.event.Listener; 6 | import org.bukkit.event.player.AsyncPlayerChatEvent; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | import java.util.UUID; 11 | import java.util.concurrent.CompletableFuture; 12 | 13 | public class InputListener implements Listener { 14 | private static final Map> listenerMap = new HashMap<>(); 15 | 16 | public static CompletableFuture listen(UUID uuid) { 17 | CompletableFuture future = new CompletableFuture<>(); 18 | listenerMap.put(uuid, future); 19 | return future; 20 | } 21 | 22 | @EventHandler 23 | public void onChat(AsyncPlayerChatEvent event) { 24 | Player player = event.getPlayer(); 25 | UUID uuid = player.getUniqueId(); 26 | 27 | if (listenerMap.containsKey(uuid)) { 28 | event.setCancelled(true); 29 | CompletableFuture future = listenerMap.remove(uuid); 30 | future.complete(event.getMessage()); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/SudoCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.argument.Arg; 4 | import dev.rollczi.litecommands.annotations.command.Command; 5 | import dev.rollczi.litecommands.annotations.context.Context; 6 | import dev.rollczi.litecommands.annotations.execute.Execute; 7 | import dev.rollczi.litecommands.annotations.join.Join; 8 | import dev.rollczi.litecommands.annotations.permission.Permission; 9 | import net.pandadev.nextron.Main; 10 | import net.pandadev.nextron.languages.TextAPI; 11 | import org.bukkit.command.CommandSender; 12 | import org.bukkit.entity.Player; 13 | 14 | @Command(name = "sudo") 15 | @Permission("nextron.sudo") 16 | public class SudoCommand extends HelpBase { 17 | 18 | public SudoCommand() { 19 | super("sudo, Forces a player to execute a command, /sudo "); 20 | } 21 | 22 | @Execute 23 | public void sudoCommand(@Context CommandSender sender, @Arg Player target, @Join String command) { 24 | target.chat("/" + command); 25 | 26 | sender.sendMessage(Main.getPrefix() 27 | + TextAPI.get("sudo.success").replace("%t", target.getName()).replace("%b", command)); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/NickCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.argument.Arg; 4 | import dev.rollczi.litecommands.annotations.command.RootCommand; 5 | import dev.rollczi.litecommands.annotations.context.Context; 6 | import dev.rollczi.litecommands.annotations.execute.Execute; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.pandadev.nextron.apis.SettingsAPI; 9 | import org.bukkit.entity.Player; 10 | 11 | @RootCommand 12 | public class NickCommand extends HelpBase { 13 | 14 | public NickCommand() { 15 | super("nick, Set your nickname, /nick ", 16 | "resetnick, Reset your nickname, /resetnick"); 17 | } 18 | 19 | @Execute(name = "nick") 20 | @Permission("nextron.nick") 21 | public void nickCommand(@Context Player player, @Arg String nick) { 22 | player.setDisplayName(nick); 23 | SettingsAPI.setNick(player, nick); 24 | } 25 | 26 | @Execute(name = "resetnick") 27 | @Permission("nextron.resetnick") 28 | public void resetnickCommand(@Context Player player) { 29 | player.setDisplayName(player.getName()); 30 | SettingsAPI.setNick(player, player.getName()); 31 | } 32 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/EnderchestCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.argument.Arg; 4 | import dev.rollczi.litecommands.annotations.command.Command; 5 | import dev.rollczi.litecommands.annotations.context.Context; 6 | import dev.rollczi.litecommands.annotations.execute.Execute; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.pandadev.nextron.Main; 9 | import org.bukkit.entity.Player; 10 | 11 | import java.util.Optional; 12 | 13 | @Command(name = "enderchest", aliases = "ec") 14 | @Permission("nextron.enderchest") 15 | public class EnderchestCommand extends HelpBase { 16 | 17 | public EnderchestCommand() { 18 | super("enderchest, Opens a GUI where the player can access his enderchest., /enderchest [player]\n/ec [player]"); 19 | } 20 | 21 | @Execute 22 | void enderchestCommand(@Context Player player, @Arg Optional target) { 23 | if (target.isEmpty()) { 24 | player.openInventory(player.getEnderChest()); 25 | } else { 26 | if (!player.hasPermission("nextron.enderchest.other")) { 27 | player.sendMessage(Main.getNoPerm()); 28 | return; 29 | } 30 | player.openInventory(target.get().getEnderChest()); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | name: Nextron Nightly Builds 2 | 3 | on: 4 | push: 5 | branches: 6 | - '*' 7 | - 'dev/**' 8 | pull_request: 9 | branches: 10 | - '*' 11 | - 'dev/**' 12 | workflow_dispatch: 13 | 14 | jobs: 15 | build: 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - uses: actions/checkout@v4 20 | - name: Set up JDK 17 21 | uses: actions/setup-java@v4 22 | with: 23 | java-version: '17' 24 | distribution: 'temurin' 25 | cache: maven 26 | 27 | - name: Cache Maven packages 28 | uses: actions/cache@v4 29 | with: 30 | path: ~/.m2 31 | key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} 32 | restore-keys: ${{ runner.os }}-m2 33 | 34 | - name: Get the version from pom.xml 35 | id: get_version 36 | run: echo "M2_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)" >> $GITHUB_ENV 37 | 38 | - name: Build with Maven 39 | run: mvn -B clean package --file pom.xml 40 | 41 | - name: Update dependency graph 42 | uses: advanced-security/maven-dependency-submission-action@v4 43 | 44 | - name: Upload Artifacts 45 | uses: actions/upload-artifact@v4 46 | with: 47 | name: Nextron-${{ env.M2_VERSION }}_NIGHTLY 48 | path: server/plugins/*.jar -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/RenameCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.command.Command; 4 | import dev.rollczi.litecommands.annotations.context.Context; 5 | import dev.rollczi.litecommands.annotations.execute.Execute; 6 | import dev.rollczi.litecommands.annotations.join.Join; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.pandadev.nextron.Main; 9 | import net.pandadev.nextron.languages.TextAPI; 10 | import org.bukkit.ChatColor; 11 | import org.bukkit.entity.Player; 12 | import org.bukkit.inventory.meta.ItemMeta; 13 | 14 | @Command(name = "rename") 15 | @Permission("nextron.rename") 16 | public class RenameCommand extends HelpBase { 17 | 18 | public RenameCommand() { 19 | super("rename, Renames the item you are currently holding, /rename "); 20 | } 21 | 22 | @Execute 23 | public void renameCommand(@Context Player player, @Join String name) { 24 | ItemMeta itemMeta = player.getInventory().getItemInMainHand().getItemMeta(); 25 | if (itemMeta == null) { 26 | player.sendMessage(Main.getPrefix() + TextAPI.get("rename.error")); 27 | return; 28 | } 29 | 30 | itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', String.valueOf(name))); 31 | player.getInventory().getItemInMainHand().setItemMeta(itemMeta); 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/TopCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.command.Command; 4 | import dev.rollczi.litecommands.annotations.context.Context; 5 | import dev.rollczi.litecommands.annotations.execute.Execute; 6 | import dev.rollczi.litecommands.annotations.permission.Permission; 7 | import net.pandadev.nextron.Main; 8 | import net.pandadev.nextron.apis.SettingsAPI; 9 | import net.pandadev.nextron.languages.TextAPI; 10 | import org.bukkit.Location; 11 | import org.bukkit.entity.Player; 12 | 13 | @Command(name = "top", aliases = {"touchgrass"}) 14 | @Permission("nextron.top") 15 | public class TopCommand extends HelpBase { 16 | 17 | public TopCommand() { 18 | super("top, Teleports you to the highest block above you, /top"); 19 | } 20 | 21 | @Execute 22 | public void topCommand(@Context Player player) { 23 | Location location = player.getLocation(); 24 | int highestY = player.getWorld().getHighestBlockYAt(location); 25 | if (highestY <= location.getBlockY()) { 26 | player.sendMessage(Main.getPrefix() + TextAPI.get("top.no_blocks_above")); 27 | return; 28 | } 29 | location.setY(highestY + 1.0); 30 | player.teleport(location); 31 | if (SettingsAPI.allowsFeedback(player)) 32 | player.sendMessage(Main.getPrefix() + TextAPI.get("top.success")); 33 | } 34 | 35 | 36 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/utils/Placeholders.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.utils; 2 | 3 | import me.clip.placeholderapi.expansion.PlaceholderExpansion; 4 | import net.pandadev.nextron.Main; 5 | import net.pandadev.nextron.apis.HomeAPI; 6 | import net.pandadev.nextron.apis.RankAPI; 7 | import net.pandadev.nextron.apis.WarpAPI; 8 | import org.bukkit.entity.Player; 9 | import org.jetbrains.annotations.NotNull; 10 | 11 | public class Placeholders extends PlaceholderExpansion { 12 | 13 | public Placeholders(Main plugin) { 14 | } 15 | 16 | @Override 17 | public @NotNull String getIdentifier() { 18 | return "Nextron"; 19 | } 20 | 21 | @Override 22 | public @NotNull String getAuthor() { 23 | return "PandaDEV"; 24 | } 25 | 26 | @Override 27 | public @NotNull String getVersion() { 28 | return "1.0.0"; 29 | } 30 | 31 | @Override 32 | public boolean persist() { 33 | return true; 34 | } 35 | 36 | @Override 37 | public String onPlaceholderRequest(Player player, @NotNull String params) { 38 | if (player == null) return ""; 39 | if (params.equalsIgnoreCase("rank")) return RankAPI.getRank(player); 40 | if (params.equalsIgnoreCase("homes_count")) return String.valueOf(HomeAPI.getHomes(player).size()); 41 | if (params.equalsIgnoreCase("warps_count")) return String.valueOf(WarpAPI.getWarps().size()); 42 | return null; 43 | } 44 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/TphereCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.argument.Arg; 4 | import dev.rollczi.litecommands.annotations.command.Command; 5 | import dev.rollczi.litecommands.annotations.context.Context; 6 | import dev.rollczi.litecommands.annotations.execute.Execute; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.pandadev.nextron.Main; 9 | import net.pandadev.nextron.apis.SettingsAPI; 10 | import net.pandadev.nextron.languages.TextAPI; 11 | import org.bukkit.entity.Player; 12 | 13 | import java.util.Objects; 14 | 15 | @Command(name = "tphere", aliases = {"tph"}) 16 | @Permission("nextron.tphere") 17 | public class TphereCommand extends HelpBase { 18 | 19 | public TphereCommand() { 20 | super("tphere, Teleports a player to you, /tphere \n/tph "); 21 | } 22 | 23 | @Execute 24 | public void tphereCommand(@Context Player player, @Arg Player target) { 25 | if (!Objects.equals(target.getName(), player.getName())) { 26 | target.teleport(player.getLocation()); 27 | 28 | if (SettingsAPI.allowsFeedback(player)) { 29 | player.sendMessage( 30 | Main.getPrefix() + TextAPI.get("tphere.success").replace("%t", target.getName())); 31 | } 32 | 33 | } else { 34 | player.sendMessage(Main.getPrefix() + TextAPI.get("tphere.error")); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/TpdenyCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.command.Command; 4 | import dev.rollczi.litecommands.annotations.context.Context; 5 | import dev.rollczi.litecommands.annotations.execute.Execute; 6 | import dev.rollczi.litecommands.annotations.permission.Permission; 7 | import net.pandadev.nextron.Main; 8 | import net.pandadev.nextron.languages.TextAPI; 9 | import org.bukkit.Sound; 10 | import org.bukkit.entity.Player; 11 | 12 | @Command(name = "tpdeny", aliases = {"tpd"}) 13 | @Permission("nextron.tpdeny") 14 | public class TpdenyCommand extends HelpBase { 15 | 16 | public TpdenyCommand() { 17 | super("tpdeny, Denys an incoming tpa request, /tpdeny\n/tpd"); 18 | } 19 | 20 | @Execute 21 | public void tpdenyCommand(@Context Player player) { 22 | Player target = Main.tpa.get(player); 23 | 24 | if (target != null) { 25 | Main.tpa.remove(player); 26 | Main.tpa.remove(target); 27 | 28 | player.sendMessage(Main.getPrefix() + TextAPI.get("tpdeny.player").replace("%p", target.getName())); 29 | target.sendMessage(Main.getPrefix() + TextAPI.get("tpdeny.target").replace("%p", player.getName())); 30 | 31 | target.playSound(target.getLocation(), Sound.ENTITY_PILLAGER_AMBIENT, 100, 0.5f); 32 | 33 | } else { 34 | player.sendMessage(Main.getPrefix() + TextAPI.get("tpaccept.error")); 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/HelpBase.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | 6 | public abstract class HelpBase { 7 | private String command; 8 | 9 | public static HashMap> commands = new HashMap<>(); 10 | 11 | protected HelpBase(String... commandData) { 12 | for (String data : commandData) { 13 | String[] parts = data.split(",", 3); 14 | if (parts.length < 3) 15 | continue; 16 | 17 | String command = parts[0].trim(); 18 | String description = parts[1].trim(); 19 | String usage = parts[2].trim(); 20 | 21 | ArrayList commandInfo = new ArrayList<>(); 22 | commandInfo.add(usage); 23 | commandInfo.add(description); 24 | commands.put(command, commandInfo); 25 | } 26 | } 27 | 28 | public String getCommandName() { 29 | return command; 30 | } 31 | 32 | public static String getName(String name) { 33 | return name; 34 | } 35 | 36 | public static String getDescription(String name) { 37 | ArrayList localCommandInfo = commands.get(name); 38 | return localCommandInfo.get(1); 39 | } 40 | 41 | public static String getUsage(String name) { 42 | ArrayList localCommandInfo = commands.get(name); 43 | String usage = localCommandInfo.get(0); 44 | usage = usage.replace("\\n", "\n"); 45 | return usage; 46 | } 47 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/PingCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.command.Command; 4 | import dev.rollczi.litecommands.annotations.context.Context; 5 | import dev.rollczi.litecommands.annotations.execute.Execute; 6 | import dev.rollczi.litecommands.annotations.argument.Arg; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.pandadev.nextron.Main; 9 | import net.pandadev.nextron.languages.TextAPI; 10 | import org.bukkit.command.CommandSender; 11 | import org.bukkit.entity.Player; 12 | 13 | import java.util.Optional; 14 | 15 | @Command(name = "ping") 16 | @Permission("nextron.ping") 17 | public class PingCommand extends HelpBase { 18 | 19 | public PingCommand() { 20 | super("ping, Returns your current ping ot the server, /ping [player]"); 21 | } 22 | 23 | @Execute 24 | public void pingCommand(@Context CommandSender sender, @Arg Optional target) { 25 | if (target.isPresent()) { 26 | sender.sendMessage(Main.getPrefix() + TextAPI.get("ping.other") 27 | .replace("%t", target.get().getName()) 28 | .replace("%p", String.valueOf(target.get().getPing()))); 29 | return; 30 | } 31 | 32 | if (!(sender instanceof Player player)) { 33 | sender.sendMessage(Main.getCommandInstance()); 34 | return; 35 | } 36 | 37 | player.sendMessage(Main.getPrefix() + TextAPI.get("ping").replace("%p", String.valueOf(player.getPing()))); 38 | } 39 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/HeadCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.argument.Arg; 4 | import dev.rollczi.litecommands.annotations.command.Command; 5 | import dev.rollczi.litecommands.annotations.context.Context; 6 | import dev.rollczi.litecommands.annotations.execute.Execute; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.pandadev.nextron.Main; 9 | import net.pandadev.nextron.apis.SettingsAPI; 10 | import net.pandadev.nextron.languages.TextAPI; 11 | import org.bukkit.Material; 12 | import org.bukkit.entity.Player; 13 | import org.bukkit.inventory.Inventory; 14 | import org.bukkit.inventory.ItemStack; 15 | import org.bukkit.inventory.meta.SkullMeta; 16 | 17 | @Command(name = "head") 18 | @Permission("nextron.head") 19 | public class HeadCommand extends HelpBase { 20 | 21 | public HeadCommand() { 22 | super("head, Gives you the head of any player, /head "); 23 | } 24 | 25 | @Execute 26 | public void headCommand(@Context Player player, @Arg Player target) { 27 | ItemStack item = new ItemStack(Material.PLAYER_HEAD, 1); 28 | SkullMeta meta = (SkullMeta) item.getItemMeta(); 29 | meta.setDisplayName(target.getName()); 30 | meta.setOwningPlayer(target); 31 | item.setItemMeta(meta); 32 | Inventory inventory = player.getInventory(); 33 | inventory.addItem(item); 34 | if (SettingsAPI.allowsFeedback(player)) 35 | player.sendMessage(Main.getPrefix() + TextAPI.get("head.success").replace("%t", target.getName())); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/arguments/HelpArgument.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.arguments; 2 | 3 | import dev.rollczi.litecommands.argument.Argument; 4 | import dev.rollczi.litecommands.argument.parser.ParseResult; 5 | import dev.rollczi.litecommands.argument.resolver.ArgumentResolver; 6 | import dev.rollczi.litecommands.invocation.Invocation; 7 | import dev.rollczi.litecommands.suggestion.SuggestionContext; 8 | import dev.rollczi.litecommands.suggestion.SuggestionResult; 9 | import net.pandadev.nextron.Main; 10 | import net.pandadev.nextron.arguments.objects.Help; 11 | import net.pandadev.nextron.commands.HelpBase; 12 | import net.pandadev.nextron.languages.TextAPI; 13 | import org.bukkit.command.CommandSender; 14 | 15 | import java.util.stream.Collectors; 16 | 17 | public class HelpArgument extends ArgumentResolver { 18 | @Override 19 | protected ParseResult parse(Invocation invocation, Argument argument, String s) { 20 | if (HelpBase.commands.containsKey(s)) { 21 | return ParseResult.success(new Help(s, HelpBase.getName(s), HelpBase.getDescription(s), HelpBase.getUsage(s))); 22 | } 23 | 24 | return ParseResult.failure(Main.getPrefix() + TextAPI.get("help.command.error")); 25 | } 26 | 27 | @Override 28 | public SuggestionResult suggest(Invocation invocation, Argument argument, SuggestionContext context) { 29 | return SuggestionResult.of(HelpBase.commands.keySet().stream().filter(cmd -> cmd.toLowerCase().startsWith(context.getCurrent().toString().toLowerCase())).collect(Collectors.toList())); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/tablist/TablistManager.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.tablist; 2 | 3 | import net.pandadev.nextron.apis.FeatureAPI; 4 | import net.pandadev.nextron.apis.RankAPI; 5 | import net.pandadev.nextron.apis.SettingsAPI; 6 | import org.bukkit.Bukkit; 7 | import org.bukkit.entity.Player; 8 | import org.bukkit.scoreboard.Scoreboard; 9 | import org.bukkit.scoreboard.Team; 10 | 11 | import java.util.Objects; 12 | 13 | public class TablistManager { 14 | 15 | // TODO: Packet ranks 16 | 17 | public void setAllPlayerTeams() { 18 | Bukkit.getOnlinePlayers().forEach(this::setPlayerTeams); 19 | } 20 | 21 | public void setPlayerTeams(Player player) { 22 | Scoreboard scoreboard = Objects.requireNonNull(Bukkit.getScoreboardManager()).getMainScoreboard(); 23 | 24 | for (String rank : RankAPI.getRanks()) { 25 | Team teamRank = scoreboard.getTeam(rank); 26 | if (teamRank == null) teamRank = scoreboard.registerNewTeam(rank); 27 | 28 | if (FeatureAPI.getFeature("rank_system")) { 29 | teamRank.setPrefix(RankAPI.getRankPrefix(rank)); 30 | } else { 31 | teamRank.setPrefix(""); 32 | player.setPlayerListName(SettingsAPI.getNick(player)); 33 | return; 34 | } 35 | 36 | if (RankAPI.getRank(player).equalsIgnoreCase(rank)) { 37 | String displayName = RankAPI.getRankPrefix(rank) + SettingsAPI.getNick(player); 38 | 39 | teamRank.addEntry(player.getName()); 40 | player.setPlayerListName(displayName); 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/arguments/WarpArgument.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.arguments; 2 | 3 | import dev.rollczi.litecommands.argument.Argument; 4 | import dev.rollczi.litecommands.argument.parser.ParseResult; 5 | import dev.rollczi.litecommands.argument.resolver.ArgumentResolver; 6 | import dev.rollczi.litecommands.invocation.Invocation; 7 | import dev.rollczi.litecommands.suggestion.SuggestionContext; 8 | import dev.rollczi.litecommands.suggestion.SuggestionResult; 9 | import net.pandadev.nextron.Main; 10 | import net.pandadev.nextron.apis.WarpAPI; 11 | import net.pandadev.nextron.arguments.objects.Warp; 12 | import net.pandadev.nextron.languages.TextAPI; 13 | import org.bukkit.command.CommandSender; 14 | 15 | import java.util.List; 16 | import java.util.stream.Collectors; 17 | 18 | public class WarpArgument extends ArgumentResolver { 19 | 20 | @Override 21 | protected ParseResult parse(Invocation invocation, Argument argument, String s) { 22 | if (WarpAPI.getWarp(s.toLowerCase()) != null) { 23 | return ParseResult.success(new Warp(s)); 24 | } 25 | return ParseResult.failure(Main.getPrefix() + TextAPI.get("warp.error").replace("%w", s)); 26 | } 27 | 28 | @Override 29 | public SuggestionResult suggest(Invocation invocation, Argument argument, SuggestionContext context) { 30 | List warps = WarpAPI.getWarps(); 31 | return SuggestionResult.of(warps.stream() 32 | .filter(warpName -> warpName.toLowerCase().startsWith(context.getCurrent().toString().toLowerCase())) 33 | .collect(Collectors.toList())); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/listeners/ChatEditor.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.listeners; 2 | 3 | import net.pandadev.nextron.Main; 4 | import net.pandadev.nextron.apis.FeatureAPI; 5 | import net.pandadev.nextron.apis.RankAPI; 6 | import net.pandadev.nextron.apis.SettingsAPI; 7 | import org.bukkit.ChatColor; 8 | import org.bukkit.entity.Player; 9 | import org.bukkit.event.EventHandler; 10 | import org.bukkit.event.Listener; 11 | import org.bukkit.event.player.AsyncPlayerChatEvent; 12 | 13 | public class ChatEditor implements Listener { 14 | 15 | @EventHandler 16 | public void onMessage(AsyncPlayerChatEvent event) { 17 | Player player = event.getPlayer(); 18 | String message = event.getMessage(); 19 | 20 | if (FeatureAPI.getFeature("rank_system")) { 21 | if (RankAPI.getRanks().isEmpty()) { 22 | String playerRankPrefix = Main.getInstance().getConfig().getString("playerRankPrefix"); 23 | player.setDisplayName(playerRankPrefix + ChatColor.WHITE + SettingsAPI.getNick(player)); 24 | } else { 25 | String rank = RankAPI.getRank(player); 26 | String prefix = RankAPI.getRankPrefix(rank); 27 | player.setDisplayName(prefix + ChatColor.WHITE + SettingsAPI.getNick(player)); 28 | } 29 | } else { 30 | player.setDisplayName(SettingsAPI.getNick(player)); 31 | } 32 | 33 | if (FeatureAPI.getFeature("chat_formatting_system")) { 34 | String formattedMessage = ChatColor.translateAlternateColorCodes('&', message); 35 | event.setFormat("%1$s §8» §f%2$s"); 36 | event.setMessage(formattedMessage); 37 | } 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug.yml: -------------------------------------------------------------------------------- 1 | name: "\U0001F41E Bug report" 2 | description: Create a report to help me improve Nextron 3 | labels: [Bug] 4 | assignees: 5 | - 0PandaDEV 6 | body: 7 | # 8 | - type: markdown 9 | attributes: 10 | value: | 11 | Thanks for taking the time to fill out this bug report! 12 | # 13 | - type: textarea 14 | id: description 15 | attributes: 16 | label: Describe the bug 17 | description: A clear and concise description of what the bug is. 18 | validations: 19 | required: true 20 | 21 | - type: textarea 22 | id: reproduce 23 | attributes: 24 | label: Steps to reproduce 25 | description: Steps to reproduce the behavior 26 | value: | 27 | 1. Go to '...' 28 | 2. Click on '....' 29 | 3. Scroll down to '....' 30 | 4. See error 31 | validations: 32 | required: true 33 | 34 | - type: textarea 35 | id: expected 36 | attributes: 37 | label: Expected behavior 38 | description: A clear and concise description of what you expected to happen. 39 | validations: 40 | required: true 41 | 42 | - type: textarea 43 | id: screenshots 44 | attributes: 45 | label: Screenshots 46 | description: If applicable, add screenshots to help explain your problem. 47 | validations: 48 | required: false 49 | 50 | - type: input 51 | id: version 52 | attributes: 53 | label: Version of Nextron 54 | placeholder: e.g. 1.6.0 55 | validations: 56 | required: true 57 | 58 | - type: textarea 59 | id: additional 60 | attributes: 61 | label: Additional context 62 | description: Add any other context about the problem here. 63 | validations: 64 | required: false -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/BackCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.argument.Arg; 4 | import dev.rollczi.litecommands.annotations.command.Command; 5 | import dev.rollczi.litecommands.annotations.context.Context; 6 | import dev.rollczi.litecommands.annotations.execute.Execute; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.pandadev.nextron.Main; 9 | import net.pandadev.nextron.apis.SettingsAPI; 10 | import net.pandadev.nextron.languages.TextAPI; 11 | import org.bukkit.Location; 12 | import org.bukkit.command.CommandSender; 13 | import org.bukkit.entity.Player; 14 | 15 | import java.util.Optional; 16 | 17 | @Command(name = "back") 18 | @Permission("nextron.back") 19 | public class BackCommand extends HelpBase { 20 | 21 | public BackCommand() { 22 | super("back, Teleports the player back to the last (death, tpa, home, warp) position., /back [player]"); 23 | } 24 | 25 | @Execute 26 | void backCommand(@Context CommandSender sender, @Arg Optional target) { 27 | Player player = (Player) sender; 28 | 29 | if (target.isEmpty()) { 30 | teleportBack(player); 31 | } else { 32 | teleportBack(target.get()); 33 | player.sendMessage(Main.getPrefix() + TextAPI.get("back.other.success").replace("%p", target.get().getName())); 34 | } 35 | } 36 | 37 | private void teleportBack(Player player) { 38 | Location lastPosition = SettingsAPI.getLastPosition(player); 39 | if (lastPosition != null) { 40 | SettingsAPI.setBack(player, true); 41 | player.teleport(lastPosition); 42 | } else { 43 | player.sendMessage(Main.getPrefix() + TextAPI.get("back.no_position")); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /src/main/resources/migrations/V1__initial_tables.sql: -------------------------------------------------------------------------------- 1 | -- Create homes table 2 | CREATE TABLE IF NOT EXISTS homes ( 3 | id INTEGER PRIMARY KEY AUTOINCREMENT, 4 | uuid VARCHAR(36) NOT NULL, 5 | name VARCHAR(50) NOT NULL, 6 | world VARCHAR(50) NOT NULL, 7 | x DOUBLE NOT NULL, 8 | y DOUBLE NOT NULL, 9 | z DOUBLE NOT NULL, 10 | yaw FLOAT NOT NULL, 11 | pitch FLOAT NOT NULL 12 | ); 13 | CREATE INDEX idx_homes_name ON homes(name); 14 | 15 | -- Create user_settings table 16 | CREATE TABLE IF NOT EXISTS user_settings ( 17 | uuid VARCHAR(36) PRIMARY KEY, 18 | vanish_message BOOLEAN DEFAULT TRUE, 19 | vanish_vanished BOOLEAN DEFAULT FALSE, 20 | feedback BOOLEAN DEFAULT TRUE, 21 | allowtpas BOOLEAN DEFAULT TRUE, 22 | nick VARCHAR(50), 23 | lastback TEXT, 24 | isback BOOLEAN DEFAULT FALSE 25 | ); 26 | 27 | -- Create warps table 28 | CREATE TABLE IF NOT EXISTS warps ( 29 | id INTEGER PRIMARY KEY AUTOINCREMENT, 30 | name VARCHAR(50) NOT NULL UNIQUE, 31 | world VARCHAR(50) NOT NULL, 32 | x DOUBLE NOT NULL, 33 | y DOUBLE NOT NULL, 34 | z DOUBLE NOT NULL, 35 | yaw FLOAT NOT NULL, 36 | pitch FLOAT NOT NULL 37 | ); 38 | CREATE INDEX idx_warps_name ON warps(name); 39 | 40 | -- Create ranks table 41 | CREATE TABLE IF NOT EXISTS ranks ( 42 | id INTEGER PRIMARY KEY AUTOINCREMENT, 43 | name VARCHAR(50) NOT NULL UNIQUE, 44 | prefix VARCHAR(50), 45 | uuids TEXT 46 | ); 47 | CREATE INDEX idx_ranks_name ON ranks(name); 48 | 49 | -- Create features table 50 | CREATE TABLE IF NOT EXISTS features ( 51 | name VARCHAR(50) PRIMARY KEY, 52 | state BOOLEAN NOT NULL DEFAULT TRUE 53 | ); 54 | 55 | -- Insert default features 56 | INSERT INTO features (name, state) VALUES 57 | ('warp_system', TRUE), 58 | ('home_system', TRUE), 59 | ('rank_system', TRUE), 60 | ('tpa_system', TRUE), 61 | ('join_leave_system', TRUE); -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/arguments/FeatureArgument.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.arguments; 2 | 3 | import dev.rollczi.litecommands.argument.Argument; 4 | import dev.rollczi.litecommands.argument.parser.ParseResult; 5 | import dev.rollczi.litecommands.argument.resolver.ArgumentResolver; 6 | import dev.rollczi.litecommands.invocation.Invocation; 7 | import dev.rollczi.litecommands.suggestion.SuggestionContext; 8 | import dev.rollczi.litecommands.suggestion.SuggestionResult; 9 | import net.pandadev.nextron.Main; 10 | import net.pandadev.nextron.arguments.objects.Feature; 11 | import net.pandadev.nextron.languages.TextAPI; 12 | import org.bukkit.command.CommandSender; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | public class FeatureArgument extends ArgumentResolver { 18 | 19 | private List getAvailableRanks() { 20 | List list = new ArrayList<>(); 21 | list.add("warp_system"); 22 | list.add("home_system"); 23 | list.add("rank_system"); 24 | list.add("tpa_system"); 25 | list.add("join_leave_system"); 26 | list.add("chat_formatting_system"); 27 | return list; 28 | } 29 | 30 | @Override 31 | protected ParseResult parse(Invocation invocation, Argument context, String supplied) { 32 | List features = getAvailableRanks(); 33 | if (features.contains(supplied.toLowerCase())) { 34 | return ParseResult.success(new Feature(supplied)); 35 | } 36 | 37 | return ParseResult.failure(Main.getPrefix() + TextAPI.get("feature.validvalues")); 38 | } 39 | 40 | @Override 41 | public SuggestionResult suggest(Invocation invocation, Argument argument, SuggestionContext context) { 42 | return SuggestionResult.of(getAvailableRanks()); 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/arguments/GameModeArgument.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.arguments; 2 | 3 | import dev.rollczi.litecommands.argument.Argument; 4 | import dev.rollczi.litecommands.argument.parser.ParseResult; 5 | import dev.rollczi.litecommands.argument.resolver.ArgumentResolver; 6 | import dev.rollczi.litecommands.invocation.Invocation; 7 | import dev.rollczi.litecommands.suggestion.SuggestionContext; 8 | import dev.rollczi.litecommands.suggestion.SuggestionResult; 9 | import net.pandadev.nextron.Main; 10 | import org.bukkit.GameMode; 11 | import org.bukkit.command.CommandSender; 12 | 13 | import java.util.HashMap; 14 | import java.util.Map; 15 | 16 | public class GameModeArgument extends ArgumentResolver { 17 | 18 | private static final Map GAME_MODE_ARGUMENTS = new HashMap<>(); 19 | 20 | static { 21 | for (GameMode value : GameMode.values()) { 22 | GAME_MODE_ARGUMENTS.put(value.name().toLowerCase(), value); 23 | GAME_MODE_ARGUMENTS.put(String.valueOf(value.ordinal()), value); 24 | GAME_MODE_ARGUMENTS.put(value.name().substring(0, 1).toLowerCase(), value); 25 | } 26 | } 27 | 28 | @Override 29 | protected ParseResult parse(Invocation invocation, Argument context, String argument) { 30 | GameMode gameMode = GAME_MODE_ARGUMENTS.get(argument.toLowerCase()); 31 | 32 | if (gameMode == null) { 33 | invocation.sender().sendMessage(Main.getPrefix() + "§cInvalid gamemode argument"); 34 | return null; 35 | } 36 | 37 | return ParseResult.success(gameMode); 38 | } 39 | 40 | @Override 41 | public SuggestionResult suggest(Invocation invocation, Argument argument, SuggestionContext context) { 42 | return SuggestionResult.of(GAME_MODE_ARGUMENTS.keySet()); 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/listeners/QuitListener.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.listeners; 2 | 3 | import net.pandadev.nextron.Main; 4 | import net.pandadev.nextron.apis.FeatureAPI; 5 | import net.pandadev.nextron.apis.SettingsAPI; 6 | import net.pandadev.nextron.apis.VanishAPI; 7 | import org.bukkit.ChatColor; 8 | import org.bukkit.entity.Player; 9 | import org.bukkit.event.EventHandler; 10 | import org.bukkit.event.Listener; 11 | import org.bukkit.event.player.PlayerQuitEvent; 12 | 13 | import java.util.UUID; 14 | 15 | public class QuitListener implements Listener { 16 | 17 | @EventHandler 18 | public void onQuit(PlayerQuitEvent event) { 19 | Player player = event.getPlayer(); 20 | 21 | SettingsAPI.initializeUser(player); 22 | 23 | if (FeatureAPI.getFeature("join_leave_system")) { 24 | if (VanishAPI.isVanish(player)) { 25 | event.setQuitMessage(""); 26 | } else { 27 | event.setQuitMessage(ChatColor.translateAlternateColorCodes('&', Main.getInstance().getConfig().getString("leave_message").replace("%p", SettingsAPI.getNick(player)))); 28 | } 29 | if (player.getUniqueId().equals(UUID.fromString("2dae5251-257a-4d28-b220-60fe24de72f0")) && !VanishAPI.isVanish(player)) { 30 | event.setQuitMessage(event.getQuitMessage() + " §8• §x§6§2§0§0§f§fNextron founder"); 31 | } 32 | if (player.getUniqueId().equals(UUID.fromString("51666aba-5e87-40c4-900c-1c77ce0b8e3c")) && !VanishAPI.isVanish(player)) { 33 | event.setQuitMessage(event.getQuitMessage() + " §8• §x§f§f§6§5§f§aAnya"); 34 | } 35 | if (player.getUniqueId().equals(UUID.fromString("621755d2-5cf7-48d6-acc6-73b539b66aac")) && !VanishAPI.isVanish(player)) { 36 | event.setQuitMessage(event.getQuitMessage() + " §8• §r§cWarrradu"); 37 | } 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/arguments/HomeArgument.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.arguments; 2 | 3 | import dev.rollczi.litecommands.argument.Argument; 4 | import dev.rollczi.litecommands.argument.parser.ParseResult; 5 | import dev.rollczi.litecommands.argument.resolver.ArgumentResolver; 6 | import dev.rollczi.litecommands.invocation.Invocation; 7 | import dev.rollczi.litecommands.suggestion.SuggestionContext; 8 | import dev.rollczi.litecommands.suggestion.SuggestionResult; 9 | import net.pandadev.nextron.Main; 10 | import net.pandadev.nextron.apis.HomeAPI; 11 | import net.pandadev.nextron.arguments.objects.Home; 12 | import net.pandadev.nextron.languages.TextAPI; 13 | import org.bukkit.command.CommandSender; 14 | import org.bukkit.entity.Player; 15 | 16 | import java.util.ArrayList; 17 | import java.util.stream.Collectors; 18 | 19 | public class HomeArgument extends ArgumentResolver { 20 | 21 | @Override 22 | protected ParseResult parse(Invocation invocation, Argument argument, String s) { 23 | if (invocation.sender() instanceof Player player) { 24 | var section = HomeAPI.getHomes(player); 25 | if (section.contains(s.toLowerCase()) && !s.equalsIgnoreCase("default")) { 26 | return ParseResult.success(new Home(s.toLowerCase())); 27 | } 28 | } 29 | return ParseResult.failure(Main.getPrefix() + TextAPI.get("home.notfound").replace("%h", s)); 30 | } 31 | 32 | @Override 33 | public SuggestionResult suggest(Invocation invocation, Argument argument, SuggestionContext context) { 34 | if (invocation.sender() instanceof Player player) { 35 | var section = HomeAPI.getHomes(player); 36 | return SuggestionResult.of(section.stream().filter(homeName -> homeName.toLowerCase().startsWith(context.getCurrent().toString().toLowerCase()) && !homeName.equalsIgnoreCase("default")).collect(Collectors.toList())); 37 | } 38 | return SuggestionResult.of(new ArrayList<>()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/LanguageCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.argument.Arg; 4 | import dev.rollczi.litecommands.annotations.command.Command; 5 | import dev.rollczi.litecommands.annotations.context.Context; 6 | import dev.rollczi.litecommands.annotations.execute.Execute; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.pandadev.nextron.Main; 9 | import net.pandadev.nextron.arguments.objects.Language; 10 | import net.pandadev.nextron.languages.TextAPI; 11 | import org.bukkit.command.CommandSender; 12 | 13 | import java.io.File; 14 | import java.util.Arrays; 15 | import java.util.List; 16 | import java.util.stream.Collectors; 17 | 18 | @Command(name = "language") 19 | @Permission("nextron.language") 20 | public class LanguageCommand extends HelpBase { 21 | 22 | public LanguageCommand() { 23 | super("language, Allows you to change the plugins language, /language "); 24 | } 25 | 26 | @Execute 27 | public void languageCommand(@Context CommandSender sender, @Arg Language language) { 28 | File[] files = new File(Main.getInstance().getDataFolder(), "/lang").listFiles(); 29 | if (files == null) { 30 | sender.sendMessage(Main.getPrefix() + "Error: Language directory not found or inaccessible."); 31 | return; 32 | } 33 | 34 | List languages = Arrays.stream(files) 35 | .map(file -> file.getName().replace(".json", "")) 36 | .collect(Collectors.toList()); 37 | 38 | if (!languages.contains(language.getName().toLowerCase())) { 39 | sender.sendMessage(Main.getPrefix() + TextAPI.get("language.set.error").replace("%l", String.join(", ", languages))); 40 | return; 41 | } 42 | 43 | Main.getInstance().getConfig().set("language", language.getName()); 44 | Main.getInstance().saveConfig(); 45 | sender.sendMessage(Main.getPrefix() + TextAPI.get("language.set.success").replace("%l", language.getName())); 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/arguments/RankArgument.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.arguments; 2 | 3 | import dev.rollczi.litecommands.argument.Argument; 4 | import dev.rollczi.litecommands.argument.parser.ParseResult; 5 | import dev.rollczi.litecommands.argument.resolver.ArgumentResolver; 6 | import dev.rollczi.litecommands.invocation.Invocation; 7 | import dev.rollczi.litecommands.suggestion.SuggestionContext; 8 | import dev.rollczi.litecommands.suggestion.SuggestionResult; 9 | import net.pandadev.nextron.Main; 10 | import net.pandadev.nextron.apis.RankAPI; 11 | import net.pandadev.nextron.arguments.objects.Rank; 12 | import net.pandadev.nextron.languages.TextAPI; 13 | import org.bukkit.command.CommandSender; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | import java.util.stream.Collectors; 18 | 19 | public class RankArgument extends ArgumentResolver { 20 | 21 | @Override 22 | protected ParseResult parse(Invocation invocation, Argument argument, String s) { 23 | List ranks = getAvailableRanks(); 24 | if (ranks.isEmpty()) { 25 | return ParseResult.failure(Main.getPrefix() + TextAPI.get("rank.dontexists")); 26 | } 27 | if (ranks.contains(s.toLowerCase())) { 28 | return ParseResult.success(new Rank(s)); 29 | } 30 | return ParseResult.failure(Main.getPrefix() + TextAPI.get("rank.dontexists")); 31 | } 32 | 33 | @Override 34 | public SuggestionResult suggest(Invocation invocation, Argument argument, SuggestionContext context) { 35 | List ranks = getAvailableRanks(); 36 | if (ranks.isEmpty()) { 37 | return SuggestionResult.of(new ArrayList<>()); 38 | } 39 | return SuggestionResult.of(ranks.stream() 40 | .filter(rank -> rank.toLowerCase().startsWith(context.getCurrent().toString().toLowerCase())) 41 | .collect(Collectors.toList())); 42 | } 43 | 44 | private List getAvailableRanks() { 45 | return RankAPI.getRanks(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/GodCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.argument.Arg; 4 | import dev.rollczi.litecommands.annotations.command.Command; 5 | import dev.rollczi.litecommands.annotations.context.Context; 6 | import dev.rollczi.litecommands.annotations.execute.Execute; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.pandadev.nextron.Main; 9 | import net.pandadev.nextron.languages.TextAPI; 10 | import org.bukkit.command.CommandSender; 11 | import org.bukkit.entity.Player; 12 | 13 | import java.util.Optional; 14 | 15 | @Command(name = "god") 16 | @Permission("nextron.god") 17 | public class GodCommand extends HelpBase { 18 | 19 | public GodCommand() { 20 | super("god, Makes a player invulnerable, /god [player]"); 21 | } 22 | 23 | @Execute 24 | public void godCommand(@Context CommandSender sender, @Arg Optional target) { 25 | if (target.isEmpty()) { 26 | if (!(sender instanceof Player player)) { 27 | sender.sendMessage(Main.getCommandInstance()); 28 | return; 29 | } 30 | 31 | player.setInvulnerable(!player.isInvulnerable()); 32 | if (player.isInvulnerable()) 33 | player.sendMessage(Main.getPrefix() + TextAPI.get("god.on")); 34 | else 35 | player.sendMessage(Main.getPrefix() + TextAPI.get("god.off")); 36 | } else { 37 | if (!sender.hasPermission("nextron.god.other")) { 38 | sender.sendMessage(Main.getNoPerm()); 39 | return; 40 | } 41 | Player targetPlayer = target.get(); 42 | targetPlayer.setInvulnerable(!targetPlayer.isInvulnerable()); 43 | if (targetPlayer.isInvulnerable()) 44 | sender.sendMessage(Main.getPrefix() + TextAPI.get("god.on.other").replace("%p", targetPlayer.getName())); 45 | else 46 | sender.sendMessage(Main.getPrefix() + TextAPI.get("god.off.other").replace("%p", targetPlayer.getName())); 47 | } 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/database/Config.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.database; 2 | 3 | import java.sql.*; 4 | import java.util.logging.Level; 5 | import java.util.logging.Logger; 6 | 7 | public class Config { 8 | private static final String DB_URL = "jdbc:sqlite:plugins/Nextron/data.db"; 9 | private static Connection connection; 10 | 11 | public static Connection getConnection() throws SQLException { 12 | if (connection == null || connection.isClosed()) { 13 | connection = DriverManager.getConnection(DB_URL); 14 | try (Statement stmt = connection.createStatement()) { 15 | stmt.execute("PRAGMA foreign_keys = ON;"); 16 | stmt.execute("PRAGMA journal_mode = DELETE;"); 17 | stmt.execute("PRAGMA synchronous = FULL;"); 18 | } 19 | connection.setAutoCommit(true); 20 | } 21 | return connection; 22 | } 23 | 24 | public static void closeConnection() { 25 | try { 26 | if (connection != null && !connection.isClosed()) { 27 | connection.close(); 28 | } 29 | } catch (SQLException e) { 30 | Logger.getLogger(Config.class.getName()).log(Level.SEVERE, "Failed to close database connection", e); 31 | } 32 | connection = null; 33 | } 34 | 35 | public static void executeUpdate(String sql) throws SQLException { 36 | try (Connection conn = getConnection(); 37 | Statement stmt = conn.createStatement()) { 38 | stmt.executeUpdate(sql); 39 | } finally { 40 | closeConnection(); 41 | } 42 | } 43 | 44 | public static void executeQuery(String sql, ResultSetHandler handler) throws SQLException { 45 | try (Connection conn = getConnection(); 46 | Statement stmt = conn.createStatement(); 47 | ResultSet rs = stmt.executeQuery(sql)) { 48 | handler.handle(rs); 49 | } finally { 50 | closeConnection(); 51 | } 52 | } 53 | 54 | @FunctionalInterface 55 | public interface ResultSetHandler { 56 | void handle(ResultSet rs) throws SQLException; 57 | } 58 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/TpacceptCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.command.Command; 4 | import dev.rollczi.litecommands.annotations.context.Context; 5 | import dev.rollczi.litecommands.annotations.execute.Execute; 6 | import dev.rollczi.litecommands.annotations.permission.Permission; 7 | import net.pandadev.nextron.Main; 8 | import net.pandadev.nextron.apis.SettingsAPI; 9 | import net.pandadev.nextron.languages.TextAPI; 10 | import org.bukkit.Sound; 11 | import org.bukkit.entity.Player; 12 | 13 | @Command(name = "tpaccept") 14 | @Permission("nextron.tpaccept") 15 | public class TpacceptCommand extends HelpBase { 16 | 17 | public TpacceptCommand() { 18 | super("tpaccept, Accepts an incoming tpa request, /tpaccept"); 19 | } 20 | 21 | @Execute 22 | public void tpacceptCommand(@Context Player player) { 23 | Player target = Main.tpa.get(player); 24 | boolean isTpaHere = false; 25 | 26 | if (target == null) { 27 | target = Main.tpahere.get(player); 28 | isTpaHere = true; 29 | } 30 | 31 | if (target != null) { 32 | target.teleport(player.getLocation()); 33 | 34 | String successMessage = Main.getPrefix() + TextAPI.get("tpaccept.player.success").replace("%p", player.getName()); 35 | if (SettingsAPI.allowsFeedback(target)) { 36 | target.sendMessage(successMessage); 37 | } 38 | if (SettingsAPI.allowsFeedback(player)) { 39 | player.sendMessage(Main.getPrefix() + TextAPI.get("tpaccept.target.success").replace("%t", target.getName())); 40 | } 41 | 42 | target.playSound(player.getLocation(), Sound.ENTITY_ENDERMAN_TELEPORT, 1.0f, 1.0f); 43 | 44 | if (isTpaHere) { 45 | Main.tpahere.remove(player); 46 | Main.tpahere.remove(target); 47 | } else { 48 | Main.tpa.remove(player); 49 | Main.tpa.remove(target); 50 | } 51 | } else { 52 | player.sendMessage(Main.getPrefix() + TextAPI.get("tpaccept.error")); 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/TimeCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.command.RootCommand; 4 | import dev.rollczi.litecommands.annotations.context.Context; 5 | import dev.rollczi.litecommands.annotations.execute.Execute; 6 | import dev.rollczi.litecommands.annotations.permission.Permission; 7 | import net.pandadev.nextron.Main; 8 | import net.pandadev.nextron.languages.TextAPI; 9 | import org.bukkit.entity.Player; 10 | 11 | import java.util.Objects; 12 | 13 | @RootCommand 14 | public class TimeCommand extends HelpBase { 15 | 16 | public TimeCommand() { 17 | super("day, Sets the time to day (1000), /day", 18 | "night, Sets the time to night (13000), /night", 19 | "midnight, Sets the time to midnight (18000), /midnight", 20 | "noon, Sets the time to noon (6000), /noon"); 21 | } 22 | 23 | 24 | @Execute(name = "day") 25 | @Permission("nextron.day") 26 | public void dayCommand(@Context Player player) { 27 | Objects.requireNonNull(player.getLocation().getWorld()).setTime(1000); 28 | player.sendMessage(Main.getPrefix() + TextAPI.get("time.success").replace("%d", "day")); 29 | } 30 | 31 | @Execute(name = "night") 32 | @Permission("nextron.night") 33 | public void nightCommand(@Context Player player) { 34 | Objects.requireNonNull(player.getLocation().getWorld()).setTime(13000); 35 | player.sendMessage(Main.getPrefix() + TextAPI.get("time.success").replace("%d", "night")); 36 | } 37 | 38 | @Execute(name = "midnight") 39 | @Permission("nextron.midnight") 40 | public void midnightCommand(@Context Player player) { 41 | Objects.requireNonNull(player.getLocation().getWorld()).setTime(18000); 42 | player.sendMessage(Main.getPrefix() + TextAPI.get("time.success").replace("%d", "midnight")); 43 | } 44 | 45 | @Execute(name = "noon") 46 | @Permission("nextron.noon") 47 | public void noonCommand(@Context Player player) { 48 | Objects.requireNonNull(player.getLocation().getWorld()).setTime(6000); 49 | player.sendMessage(Main.getPrefix() + TextAPI.get("time.success").replace("%d", "noon")); 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # User-specific stuff 2 | .idea/ 3 | 4 | *.iml 5 | *.ipr 6 | *.iws 7 | 8 | # IntelliJ 9 | out/ 10 | 11 | # Compiled class file 12 | *.class 13 | 14 | # Log file 15 | *.log 16 | 17 | # BlueJ files 18 | *.ctxt 19 | 20 | # Package Files # 21 | *.jar 22 | *.war 23 | *.nar 24 | *.ear 25 | *.zip 26 | *.tar.gz 27 | *.rar 28 | 29 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 30 | hs_err_pid* 31 | 32 | *~ 33 | 34 | # temporary files which can be created if a process still has a handle open of a deleted file 35 | .fuse_hidden* 36 | 37 | # KDE directory preferences 38 | .directory 39 | 40 | # Linux trash folder which might appear on any partition or disk 41 | .Trash-* 42 | 43 | # .nfs files are created when an open file is removed but is still being accessed 44 | .nfs* 45 | 46 | # General 47 | .DS_Store 48 | .AppleDouble 49 | .LSOverride 50 | 51 | # Icon must end with two \r 52 | Icon 53 | 54 | # Thumbnails 55 | ._* 56 | 57 | # Files that might appear in the root of a volume 58 | .DocumentRevisions-V100 59 | .fseventsd 60 | .Spotlight-V100 61 | .TemporaryItems 62 | .Trashes 63 | .VolumeIcon.icns 64 | .com.apple.timemachine.donotpresent 65 | 66 | # Directories potentially created on remote AFP share 67 | .AppleDB 68 | .AppleDesktop 69 | Network Trash Folder 70 | Temporary Items 71 | .apdisk 72 | 73 | # Windows thumbnail cache files 74 | Thumbs.db 75 | Thumbs.db:encryptable 76 | ehthumbs.db 77 | ehthumbs_vista.db 78 | 79 | # Dump file 80 | *.stackdump 81 | 82 | # Folder config file 83 | [Dd]esktop.ini 84 | 85 | # Recycle Bin used on file shares 86 | $RECYCLE.BIN/ 87 | 88 | # Windows Installer files 89 | *.cab 90 | *.msi 91 | *.msix 92 | *.msm 93 | *.msp 94 | 95 | # Windows shortcuts 96 | *.lnk 97 | 98 | target/ 99 | 100 | pom.xml.tag 101 | pom.xml.releaseBackup 102 | pom.xml.versionsBackup 103 | pom.xml.next 104 | 105 | release.properties 106 | dependency-reduced-pom.xml 107 | buildNumber.properties 108 | .mvn/timing.properties 109 | .mvn/wrapper/maven-wrapper.jar 110 | .flattened-pom.xml 111 | 112 | # Common working directory 113 | run/ 114 | 115 | server 116 | .vscode 117 | .gitignore 118 | /move.sh 119 | .stignore 120 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/languages/TextAPI.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.languages; 2 | 3 | import com.google.gson.Gson; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import net.pandadev.nextron.Main; 7 | 8 | import java.io.File; 9 | import java.io.IOException; 10 | import java.io.Reader; 11 | import java.nio.file.Files; 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | public class TextAPI { 16 | @Getter 17 | @Setter 18 | private static String prefix; 19 | 20 | public static String get(String path, Boolean usePrefix) { 21 | String language = LanguageLoader.getLanguage(); 22 | Map langMap = loadLanguageFile(language); 23 | 24 | String text = (String) langMap.get(path); 25 | if (text == null) { 26 | return "Missing translation: " + path; 27 | } 28 | 29 | if (prefix == null || !usePrefix) { 30 | return text; 31 | } else { 32 | return prefix + " " + text; 33 | } 34 | } 35 | 36 | public static String get(String path, HashMap replacements, Boolean usePrefix) { 37 | String text = get(path, usePrefix); 38 | return applyReplacements(text, replacements); 39 | } 40 | 41 | public static String get(String path) { 42 | return get(path, true); 43 | } 44 | 45 | public static String get(String path, HashMap replacements) { 46 | return get(path, replacements, true); 47 | } 48 | 49 | private static Map loadLanguageFile(String language) { 50 | Gson gson = new Gson(); 51 | File file = new File(Main.getInstance().getDataFolder() + "/lang/" + language + ".json"); 52 | 53 | try (Reader reader = Files.newBufferedReader(file.toPath())) { 54 | return gson.fromJson(reader, Map.class); 55 | } catch (IOException e) { 56 | throw new RuntimeException("Failed to load language file: " + language, e); 57 | } 58 | } 59 | 60 | private static String applyReplacements(String text, HashMap replacements) { 61 | for (Map.Entry entry : replacements.entrySet()) { 62 | text = text.replace(entry.getKey(), entry.getValue()); 63 | } 64 | return text; 65 | } 66 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [![Available on SpigotMC](https://raw.githubusercontent.com/vLuckyyy/badges/main/available-on-spigotmc.svg)](https://www.spigotmc.org/resources/nextron.106476/) 4 | [![Available on Modrinth](https://raw.githubusercontent.com/vLuckyyy/badges/main/avaiable-on-modrinth.svg)](https://modrinth.com/plugin/nextron) 5 | [![Available on Hangar](https://raw.githubusercontent.com/vLuckyyy/badges/main/avaiable-on-hangar.svg)](https://hangar.papermc.io/PandaDEV/Nextron) 6 |
[![Chat on Discord](https://raw.githubusercontent.com/vLuckyyy/badges/main//chat-with-us-on-discord.svg)](https://discord.gg/invite/Y7SbYphVw9) 7 | [![Available on BStats](https://raw.githubusercontent.com/vLuckyyy/badges/main/available-on-bstats.svg)](https://bstats.org/plugin/bukkit/Nextron/20704) 8 | 9 | [Website >](https://nextron.pandadev.net?q=modrinth) 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | Nextron is a powerful Minecraft plugin which is meant to replace any other plugins you use at the moment. It has 18 | beautiful GUI's that simplifies the process to many users because you don't have to use complicated commands. 19 | 20 |
21 | 22 | 23 | 24 | - A permission plugin is highly recommended, for example [LuckPerms](https://luckperms.net/), as it can manage all 25 | permissions. 26 | - Nextron runs on Bukkit, Spigot, Paper and [Purpur (recommended)](https://purpurmc.org/). 27 | - Nextron supports 1.13 and higher. 28 | 29 |
30 | 31 | 32 | 33 | If you have any issues or find a bug, please remember to report it 34 | here [GitHub](https://github.com/0PandaDEV/Nextron/issues) 35 | 36 |
37 | 38 | 39 | 40 | [anvilgui](https://github.com/WesJD/AnvilGUI) by WesJD
41 | [triumph-gui](https://github.com/TriumphTeam/triumph-gui) by triumph team
42 | [languify](https://github.com/Hekates/Languify) by Hekates 43 | 44 | *** 45 | 46 | Check out my other projects on [my profile](https://modrinth.com/user/PandaDEV) 47 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/listeners/JoinListener.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.listeners; 2 | 3 | import net.pandadev.nextron.Main; 4 | import net.pandadev.nextron.apis.FeatureAPI; 5 | import net.pandadev.nextron.apis.RankAPI; 6 | import net.pandadev.nextron.apis.SettingsAPI; 7 | import net.pandadev.nextron.apis.VanishAPI; 8 | import org.bukkit.Bukkit; 9 | import org.bukkit.ChatColor; 10 | import org.bukkit.entity.Player; 11 | import org.bukkit.event.EventHandler; 12 | import org.bukkit.event.Listener; 13 | import org.bukkit.event.player.PlayerJoinEvent; 14 | 15 | import java.util.UUID; 16 | 17 | public class JoinListener implements Listener { 18 | 19 | @EventHandler 20 | public void onJoin(PlayerJoinEvent event) { 21 | Player player = event.getPlayer(); 22 | 23 | SettingsAPI.initializeUser(player); 24 | 25 | if (FeatureAPI.getFeature("join_leave_system")) { 26 | if (VanishAPI.isVanish(player)) { 27 | event.setJoinMessage(""); 28 | } else { 29 | event.setJoinMessage( 30 | ChatColor.translateAlternateColorCodes('&', Main.getInstance().getConfig().getString("join_message") 31 | .replace("%p", SettingsAPI.getNick(player)))); 32 | } 33 | if (player.getUniqueId().equals(UUID.fromString("2dae5251-257a-4d28-b220-60fe24de72f0")) && !VanishAPI.isVanish(player)) { 34 | event.setJoinMessage(event.getJoinMessage() + " §8• §x§6§2§0§0§f§fNextron founder"); 35 | } 36 | if (player.getUniqueId().equals(UUID.fromString("51666aba-5e87-40c4-900c-1c77ce0b8e3c")) && !VanishAPI.isVanish(player)) { 37 | event.setJoinMessage(event.getJoinMessage() + " §8• §x§f§f§6§5§f§aAnya"); 38 | } 39 | if (player.getUniqueId().equals(UUID.fromString("621755d2-5cf7-48d6-acc6-73b539b66aac")) && !VanishAPI.isVanish(player)) { 40 | event.setJoinMessage(event.getJoinMessage() + " §8• §r§cWarrradu"); 41 | } 42 | } 43 | 44 | RankAPI.createPlayerTeam(player); 45 | RankAPI.checkRank(player); 46 | Main.getInstance().getTablistManager().setAllPlayerTeams(); 47 | 48 | for (Player onlinePlayer : Bukkit.getOnlinePlayers()) { 49 | VanishAPI.executeVanish(onlinePlayer); 50 | } 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/FlyCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.argument.Arg; 4 | import dev.rollczi.litecommands.annotations.command.Command; 5 | import dev.rollczi.litecommands.annotations.context.Context; 6 | import dev.rollczi.litecommands.annotations.execute.Execute; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.pandadev.nextron.Main; 9 | import net.pandadev.nextron.apis.SettingsAPI; 10 | import net.pandadev.nextron.languages.TextAPI; 11 | import org.bukkit.command.CommandSender; 12 | import org.bukkit.entity.Player; 13 | 14 | import java.util.Optional; 15 | 16 | @Command(name = "fly") 17 | @Permission("nextron.fly") 18 | public class FlyCommand extends HelpBase { 19 | 20 | public FlyCommand() { 21 | super("fly, Enables/disables fly for you or another player, /fly [player]"); 22 | } 23 | 24 | @Execute 25 | void flyCommand(@Context CommandSender sender, @Arg Optional target) { 26 | if (target.isEmpty()) { 27 | if (!(sender instanceof Player player)) { 28 | sender.sendMessage(Main.getCommandInstance()); 29 | return; 30 | } 31 | 32 | if (player.getAllowFlight()) { 33 | player.setAllowFlight(false); 34 | if (SettingsAPI.allowsFeedback(player)) { 35 | player.sendMessage(Main.getPrefix() + TextAPI.get("fly.off")); 36 | } 37 | } else { 38 | player.setAllowFlight(true); 39 | if (SettingsAPI.allowsFeedback(player)) { 40 | player.sendMessage(Main.getPrefix() + TextAPI.get("fly.on")); 41 | } 42 | } 43 | player.setFallDistance(0.0f); 44 | } else { 45 | Player targetPlayer = target.get(); 46 | if (targetPlayer.getAllowFlight()) { 47 | targetPlayer.setAllowFlight(false); 48 | sender.sendMessage(Main.getPrefix() + TextAPI.get("fly.other.off").replace("%t", targetPlayer.getName())); 49 | } else { 50 | targetPlayer.setAllowFlight(true); 51 | sender.sendMessage(Main.getPrefix() + TextAPI.get("fly.other.on").replace("%t", targetPlayer.getName())); 52 | } 53 | targetPlayer.setFallDistance(0.0f); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/NightVisionCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.argument.Arg; 4 | import dev.rollczi.litecommands.annotations.command.Command; 5 | import dev.rollczi.litecommands.annotations.context.Context; 6 | import dev.rollczi.litecommands.annotations.execute.Execute; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.pandadev.nextron.Main; 9 | import net.pandadev.nextron.languages.TextAPI; 10 | import org.bukkit.command.CommandSender; 11 | import org.bukkit.entity.Player; 12 | import org.bukkit.potion.PotionEffect; 13 | import org.bukkit.potion.PotionEffectType; 14 | 15 | import java.util.Optional; 16 | 17 | @Command(name = "nightvision", aliases = {"nv"}) 18 | @Permission("nextron.nightvision") 19 | public class NightVisionCommand extends HelpBase { 20 | 21 | public NightVisionCommand() { 22 | super("nightvision, Allows you to toggle nightivision, /nightvision [player]\n/nv [player]"); 23 | } 24 | 25 | @Execute 26 | public void nightVisionCommand(@Context CommandSender sender, @Arg Optional target) { 27 | if (target.isEmpty()) { 28 | if (!(sender instanceof Player player)) { 29 | sender.sendMessage("§6This command can only be run by a player!"); 30 | return; 31 | } 32 | 33 | if (!player.hasPotionEffect(PotionEffectType.NIGHT_VISION)) { 34 | player.addPotionEffect(new PotionEffect(PotionEffectType.NIGHT_VISION, PotionEffect.INFINITE_DURATION, 255, false, false, false)); 35 | } else { 36 | player.removePotionEffect(PotionEffectType.NIGHT_VISION); 37 | } 38 | } else { 39 | Player targetPlayer = target.get(); 40 | if (!targetPlayer.hasPotionEffect(PotionEffectType.NIGHT_VISION)) { 41 | targetPlayer.addPotionEffect(new PotionEffect(PotionEffectType.NIGHT_VISION, PotionEffect.INFINITE_DURATION, 255, false, false, false)); 42 | sender.sendMessage(Main.getPrefix() + TextAPI.get("night.vision.add").replace("%p", targetPlayer.getName())); 43 | } else { 44 | targetPlayer.removePotionEffect(PotionEffectType.NIGHT_VISION); 45 | sender.sendMessage(Main.getPrefix() + TextAPI.get("night.vision.remove").replace("%p", targetPlayer.getName())); 46 | } 47 | } 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/GetPosCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.argument.Arg; 4 | import dev.rollczi.litecommands.annotations.command.Command; 5 | import dev.rollczi.litecommands.annotations.context.Context; 6 | import dev.rollczi.litecommands.annotations.execute.Execute; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.md_5.bungee.api.ChatMessageType; 9 | import net.md_5.bungee.api.chat.ClickEvent; 10 | import net.md_5.bungee.api.chat.HoverEvent; 11 | import net.md_5.bungee.api.chat.TextComponent; 12 | import net.md_5.bungee.api.chat.hover.content.Text; 13 | import net.pandadev.nextron.Main; 14 | import net.pandadev.nextron.languages.TextAPI; 15 | import org.bukkit.command.CommandSender; 16 | import org.bukkit.entity.Player; 17 | 18 | @Command(name = "getposition", aliases = {"getpos"}) 19 | @Permission("nextron.getposition") 20 | public class GetPosCommand extends HelpBase { 21 | 22 | public GetPosCommand() { 23 | super("getposition, Gives you the coordinates of a player, /getposition \n/getpos "); 24 | } 25 | 26 | @Execute 27 | public void getPositionCommand(@Context CommandSender sender, @Arg Player target) { 28 | if (sender instanceof Player) { 29 | Player player = (Player) (sender); 30 | 31 | if (player.isOp() && player.hasPermission("nextron.getposition.teleport")) { 32 | TextComponent teleport = new TextComponent("§2[§aTeleport§2]"); 33 | teleport.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/tp " + player.getName() + " " + target.getName())); 34 | teleport.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(TextAPI.get("getpos.hover") + "§a" + target.getName()))); 35 | 36 | player.sendMessage(Main.getPrefix() + TextAPI.get("getpos.success").replace("%p", target.getName()) + " X: §a" + Math.floor(target.getLocation().getX()) + "§7 Y: §a" + Math.floor(target.getLocation().getY()) + "§7 Z: §a" + Math.floor(target.getLocation().getZ())); 37 | player.spigot().sendMessage(ChatMessageType.SYSTEM, teleport); 38 | return; 39 | } 40 | } 41 | 42 | sender.sendMessage(Main.getPrefix() + TextAPI.get("getpos.success").replace("%p", target.getName()) + " X: §a" + Math.floor(target.getLocation().getX()) + "§7 Y: §a" + Math.floor(target.getLocation().getY()) + "§7 Z: §a" + Math.floor(target.getLocation().getZ())); 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/utils/ItemBuilder.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.utils; 2 | 3 | import com.mojang.authlib.GameProfile; 4 | import com.mojang.authlib.properties.Property; 5 | import org.bukkit.Material; 6 | import org.bukkit.enchantments.Enchantment; 7 | import org.bukkit.inventory.ItemStack; 8 | import org.bukkit.inventory.meta.ItemMeta; 9 | import org.bukkit.inventory.meta.SkullMeta; 10 | 11 | import java.lang.reflect.Field; 12 | import java.util.Arrays; 13 | import java.util.UUID; 14 | 15 | public class ItemBuilder { 16 | 17 | private ItemStack item; 18 | private ItemMeta itemMeta; 19 | 20 | public ItemBuilder(Material material) { 21 | item = new ItemStack(material); 22 | itemMeta = item.getItemMeta(); 23 | } 24 | 25 | @SuppressWarnings("deprecation") 26 | public ItemBuilder(Material material, short subId) { 27 | item = new ItemStack(material, 1, subId); 28 | itemMeta = item.getItemMeta(); 29 | } 30 | 31 | public ItemBuilder setName(String displayName) { 32 | itemMeta.setDisplayName(displayName); 33 | return this; 34 | } 35 | 36 | public ItemBuilder setLore(String... lore) { 37 | itemMeta.setLore(Arrays.asList(lore)); 38 | return this; 39 | } 40 | 41 | public ItemBuilder addEnchantment(Enchantment enchantment, int level) { 42 | itemMeta.addEnchant(enchantment, level, true); 43 | return this; 44 | } 45 | 46 | public ItemBuilder setAmount(int amount) { 47 | item.setAmount(amount); 48 | return this; 49 | } 50 | 51 | public ItemStack build() { 52 | item.setItemMeta(itemMeta); 53 | return item; 54 | } 55 | 56 | public static ItemStack createSkull(String url) { 57 | ItemStack head = new ItemStack(Material.PLAYER_HEAD); 58 | if (url.isEmpty()) 59 | return head; 60 | 61 | SkullMeta headMeta = (SkullMeta) head.getItemMeta(); 62 | GameProfile profile = new GameProfile(UUID.randomUUID(), null); 63 | 64 | profile.getProperties().put("textures", new Property("textures", url)); 65 | 66 | try { 67 | Field profileField = headMeta.getClass().getDeclaredField("profile"); 68 | profileField.setAccessible(true); 69 | profileField.set(headMeta, profile); 70 | 71 | } catch (IllegalArgumentException | NoSuchFieldException | SecurityException | IllegalAccessException error) { 72 | error.printStackTrace(); 73 | } 74 | head.setItemMeta(headMeta); 75 | return head; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/arguments/LanguageArgument.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.arguments; 2 | 3 | import dev.rollczi.litecommands.argument.Argument; 4 | import dev.rollczi.litecommands.argument.parser.ParseResult; 5 | import dev.rollczi.litecommands.argument.resolver.ArgumentResolver; 6 | import dev.rollczi.litecommands.invocation.Invocation; 7 | import dev.rollczi.litecommands.suggestion.SuggestionContext; 8 | import dev.rollczi.litecommands.suggestion.SuggestionResult; 9 | import net.pandadev.nextron.Main; 10 | import net.pandadev.nextron.arguments.objects.Language; 11 | import net.pandadev.nextron.languages.TextAPI; 12 | import org.bukkit.command.CommandSender; 13 | 14 | import java.io.File; 15 | import java.util.Arrays; 16 | import java.util.List; 17 | import java.util.stream.Collectors; 18 | 19 | public class LanguageArgument extends ArgumentResolver { 20 | 21 | @Override 22 | protected ParseResult parse(Invocation invocation, Argument argument, String s) { 23 | List languages = getAvailableLanguages(); 24 | if (languages.contains(s.toLowerCase())) { 25 | return ParseResult.success(new Language(s)); 26 | } 27 | return ParseResult.failure(Main.getPrefix() + TextAPI.get("language.set.error").replace("%l", String.join(", ", languages))); 28 | } 29 | 30 | @Override 31 | public SuggestionResult suggest(Invocation invocation, Argument argument, SuggestionContext context) { 32 | List languages = getAvailableLanguages(); 33 | return SuggestionResult.of(languages.stream() 34 | .filter(language -> language.toLowerCase().startsWith(context.getCurrent().toString().toLowerCase())) 35 | .collect(Collectors.toList())); 36 | } 37 | 38 | private List getAvailableLanguages() { 39 | File dataFolder = new File(Main.getInstance().getDataFolder(), "/lang"); 40 | if (!dataFolder.exists() || !dataFolder.isDirectory()) { 41 | System.out.println("Language directory not found or is not a directory."); 42 | return List.of(); 43 | } 44 | File[] files = dataFolder.listFiles(); 45 | if (files == null) { 46 | System.out.println("Error listing language files."); 47 | return List.of(); 48 | } 49 | return Arrays.stream(files) 50 | .filter(File::isFile) 51 | .map(file -> file.getName().replace(".json", "").toLowerCase()) 52 | .collect(Collectors.toList()); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/HealCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.argument.Arg; 4 | import dev.rollczi.litecommands.annotations.command.Command; 5 | import dev.rollczi.litecommands.annotations.context.Context; 6 | import dev.rollczi.litecommands.annotations.execute.Execute; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.pandadev.nextron.Main; 9 | import net.pandadev.nextron.apis.SettingsAPI; 10 | import net.pandadev.nextron.languages.TextAPI; 11 | import org.bukkit.Sound; 12 | import org.bukkit.attribute.Attribute; 13 | import org.bukkit.command.CommandSender; 14 | import org.bukkit.entity.Player; 15 | 16 | import java.util.Optional; 17 | 18 | @Command(name = "heal") 19 | @Permission("nextron.heal") 20 | public class HealCommand extends HelpBase { 21 | 22 | public HealCommand() { 23 | super("heal, Fills up your hunger and hearts, /heal [player]"); 24 | } 25 | 26 | @Execute 27 | public void healCommand(@Context CommandSender sender, @Arg Optional target) { 28 | if (target.isEmpty() && sender instanceof Player player) { 29 | double maxHealth = player.getAttribute(Attribute.MAX_HEALTH).getValue(); 30 | if (player.getHealth() != maxHealth || player.getFoodLevel() != 20) { 31 | player.setHealth(maxHealth); 32 | player.setFoodLevel(20); 33 | if (SettingsAPI.allowsFeedback(player)) { 34 | player.sendMessage(Main.getPrefix() + TextAPI.get("heal.success")); 35 | } 36 | player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1.0f, 1.0f); 37 | return; 38 | } 39 | player.sendMessage(Main.getPrefix() + TextAPI.get("heal.error")); 40 | return; 41 | } 42 | 43 | Player targetPlayer = target.get(); 44 | double maxHealth = targetPlayer.getAttribute(Attribute.MAX_HEALTH).getValue(); 45 | if (targetPlayer.getHealth() != maxHealth || targetPlayer.getFoodLevel() != 20) { 46 | targetPlayer.setHealth(maxHealth); 47 | targetPlayer.setFoodLevel(20); 48 | targetPlayer.sendMessage(Main.getPrefix() + TextAPI.get("heal.other.success") 49 | .replace("%p", sender instanceof Player ? sender.getName() : "Console")); 50 | targetPlayer.playSound(targetPlayer.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1.0f, 1.0f); 51 | return; 52 | } 53 | sender.sendMessage(Main.getPrefix() + TextAPI.get("heal.other.error").replace("%t", targetPlayer.getName())); 54 | } 55 | 56 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/apis/VanishAPI.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.apis; 2 | 3 | import net.md_5.bungee.api.ChatMessageType; 4 | import net.md_5.bungee.api.chat.TextComponent; 5 | import net.pandadev.nextron.Main; 6 | import org.bukkit.Bukkit; 7 | import org.bukkit.entity.Player; 8 | import org.bukkit.scheduler.BukkitTask; 9 | 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | import java.util.UUID; 13 | 14 | public class VanishAPI { 15 | 16 | private static final String VANISH_MESSAGE = "§7You are currently in vanish"; 17 | private static final Map vanishTasks = new HashMap<>(); 18 | 19 | public static void setVanish(Player player, Boolean state) { 20 | SettingsAPI.setVanished(player, state); 21 | executeVanish(player); 22 | if (state) { 23 | startVanishActionBar(player); 24 | } else { 25 | stopVanishActionBar(player); 26 | } 27 | } 28 | 29 | public static boolean isVanish(Player player) { 30 | return SettingsAPI.getVanished(player); 31 | } 32 | 33 | public static void executeVanish(Player player) { 34 | for (Player onlinePlayer : Bukkit.getOnlinePlayers()) { 35 | if (isVanish(player)) { 36 | onlinePlayer.hidePlayer(Main.getInstance(), player); 37 | } else { 38 | onlinePlayer.showPlayer(Main.getInstance(), player); 39 | } 40 | } 41 | if (isVanish(player) && !vanishTasks.containsKey(player.getUniqueId())) { 42 | startVanishActionBar(player); 43 | } 44 | } 45 | 46 | private static void startVanishActionBar(Player player) { 47 | UUID playerUUID = player.getUniqueId(); 48 | stopVanishActionBar(player); 49 | BukkitTask task = Bukkit.getScheduler().runTaskTimer(Main.getInstance(), () -> { 50 | Player onlinePlayer = Bukkit.getPlayer(playerUUID); 51 | if (onlinePlayer != null && onlinePlayer.isOnline() && isVanish(onlinePlayer)) { 52 | onlinePlayer.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(VANISH_MESSAGE)); 53 | } else { 54 | stopVanishActionBar(onlinePlayer); 55 | } 56 | }, 0L, 20L); 57 | vanishTasks.put(playerUUID, task); 58 | } 59 | 60 | private static void stopVanishActionBar(Player player) { 61 | if (player != null) { 62 | player.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent("")); 63 | BukkitTask task = vanishTasks.remove(player.getUniqueId()); 64 | if (task != null) { 65 | task.cancel(); 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/SpeedCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.argument.Arg; 4 | import dev.rollczi.litecommands.annotations.command.Command; 5 | import dev.rollczi.litecommands.annotations.context.Context; 6 | import dev.rollczi.litecommands.annotations.execute.Execute; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.pandadev.nextron.Main; 9 | import net.pandadev.nextron.apis.SettingsAPI; 10 | import net.pandadev.nextron.languages.TextAPI; 11 | import org.apache.commons.lang3.math.NumberUtils; 12 | import org.bukkit.entity.Player; 13 | 14 | import java.util.Optional; 15 | 16 | @Command(name = "speed") 17 | @Permission("nextron.speed") 18 | public class SpeedCommand extends HelpBase { 19 | 20 | public SpeedCommand() { 21 | super("speed, Allows you to set your fly/walk speed, /speed [speed]"); 22 | } 23 | 24 | @Execute 25 | public void speedCommand(@Context Player player, @Arg Optional speed) { 26 | if (speed.isEmpty()) { 27 | if (!player.hasPermission("nextron.speed.reset")) { 28 | player.sendMessage(Main.getNoPerm()); 29 | return; 30 | } 31 | player.setAllowFlight(true); 32 | player.setFlying(true); 33 | player.setFlySpeed(0.1f); 34 | player.setWalkSpeed(0.2f); 35 | player.sendMessage(Main.getPrefix() + TextAPI.get("speed.reset")); 36 | return; 37 | } 38 | 39 | if (NumberUtils.isDigits(String.valueOf(speed.get()))) { 40 | float parsedSpeed = speed.get() / 10f; 41 | if (parsedSpeed > 1) { 42 | player.sendMessage(Main.getPrefix() + TextAPI.get("speed.error")); 43 | } else { 44 | if (player.isFlying()) { 45 | player.setAllowFlight(true); 46 | player.setFlying(true); 47 | player.setFlySpeed(parsedSpeed); 48 | if (SettingsAPI.allowsFeedback(player)) { 49 | player.sendMessage(Main.getPrefix() + TextAPI.get("speed.fly.success").replace("%s", speed.get().toString())); 50 | } 51 | } else if (!player.isFlying()) { 52 | player.setWalkSpeed(parsedSpeed); 53 | if (SettingsAPI.allowsFeedback(player)) { 54 | player.sendMessage(Main.getPrefix() + TextAPI.get("speed.walk.success").replace("%s", speed.get().toString())); 55 | } 56 | } 57 | } 58 | } else { 59 | player.sendMessage(Main.getPrefix() + TextAPI.get("speed.error.digit")); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/HelpCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.argument.Arg; 4 | import dev.rollczi.litecommands.annotations.command.Command; 5 | import dev.rollczi.litecommands.annotations.context.Context; 6 | import dev.rollczi.litecommands.annotations.execute.Execute; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.pandadev.nextron.arguments.objects.Help; 9 | import org.bukkit.command.CommandSender; 10 | 11 | import java.util.ArrayList; 12 | import java.util.Collections; 13 | import java.util.Optional; 14 | 15 | @Command(name = "nextron", aliases = {"nhelp"}) 16 | @Permission("nextron.help") 17 | public class HelpCommand extends HelpBase { 18 | 19 | public HelpCommand() { 20 | super("help, Gives you a list of all commands with a short description, /nhelp [command]\n/nextron help [command]"); 21 | } 22 | 23 | @Execute 24 | public void helpCommand(@Context CommandSender sender, @Arg Optional commandName) { 25 | if (commandName.isEmpty()) { 26 | displayAllCommands(sender); 27 | } else { 28 | displayCommandDetails(sender, commandName.get()); 29 | } 30 | } 31 | 32 | private void displayAllCommands(CommandSender sender) { 33 | ArrayList commandsList = new ArrayList<>(HelpBase.commands.keySet()); 34 | Collections.sort(commandsList); 35 | sender.sendMessage(""); 36 | sender.sendMessage("§7Help menu for §x§b§1§8§0§f§f§lNextron §7with all commands"); 37 | sender.sendMessage(""); 38 | for (String command : commandsList) { 39 | sender.sendMessage("§7/" + command); 40 | } 41 | sender.sendMessage(""); 42 | sender.sendMessage("§7For details type §a/help "); 43 | sender.sendMessage(""); 44 | } 45 | 46 | private void displayCommandDetails(CommandSender sender, Help commandInfo) { 47 | String usage = "\n"; 48 | 49 | if (!commandInfo.getUsage().isEmpty()) { 50 | if (!commandInfo.getUsage().contains("\n")) { 51 | usage = "§7Usage: §a" + commandInfo.getUsage(); 52 | } else { 53 | usage = "§7Usage: \n§a" + commandInfo.getUsage(); 54 | } 55 | } 56 | 57 | sender.sendMessage( 58 | "§8----- [ §7Help menu for §x§b§1§8§0§f§f§l" + commandInfo.getCommand() + " §8] -----", 59 | "", 60 | "§7Command: §a" + commandInfo.getName(), 61 | "§7Description: §a" + commandInfo.getDescription(), 62 | usage, 63 | "", 64 | "§8§l-------------" + commandInfo.getCommand().replaceAll("[a-z]", "-") + "----------" 65 | ); 66 | } 67 | } -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Nextron Release Build 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v4 14 | with: 15 | fetch-depth: 0 16 | - name: Set up JDK 17 17 | uses: actions/setup-java@v4 18 | with: 19 | java-version: '17' 20 | distribution: 'temurin' 21 | cache: maven 22 | 23 | - name: Cache Maven packages 24 | uses: actions/cache@v4 25 | with: 26 | path: ~/.m2 27 | key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} 28 | restore-keys: ${{ runner.os }}-m2 29 | 30 | - name: Get the version from pom.xml 31 | id: get_version 32 | run: echo "M2_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)" >> $GITHUB_ENV 33 | 34 | - name: Build with Maven 35 | run: mvn -B clean package --file pom.xml 36 | 37 | - name: Update dependency graph 38 | uses: advanced-security/maven-dependency-submission-action@v4 39 | 40 | - name: Generate changelog 41 | id: changelog 42 | run: | 43 | PREVIOUS_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "") 44 | if [ -z "$PREVIOUS_TAG" ]; then 45 | CHANGELOG=$(git log --pretty=format:"* %s" ${{ github.ref_name }}) 46 | else 47 | CHANGELOG=$(git log --pretty=format:"* %s" ${PREVIOUS_TAG}..${{ github.ref_name }}) 48 | fi 49 | echo "CHANGELOG<> $GITHUB_ENV 50 | echo "$CHANGELOG" >> $GITHUB_ENV 51 | echo "EOF" >> $GITHUB_ENV 52 | echo "PREVIOUS_TAG=$PREVIOUS_TAG" >> $GITHUB_ENV 53 | 54 | - name: Create Release 55 | id: create_release 56 | uses: actions/create-release@v1 57 | env: 58 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 59 | with: 60 | tag_name: ${{ github.ref }} 61 | release_name: Release ${{ github.ref }} 62 | body: | 63 | ### Changes 64 | ${{ env.CHANGELOG }} 65 | 66 | ${{ env.PREVIOUS_TAG && format('[Full Changelog]({0}/compare/{1}...{2})', github.server_url, env.PREVIOUS_TAG, github.ref_name) || '' }} 67 | draft: true 68 | prerelease: false 69 | 70 | - name: Upload Release Asset 71 | uses: actions/upload-release-asset@v1 72 | env: 73 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 74 | with: 75 | upload_url: ${{ steps.create_release.outputs.upload_url }} 76 | asset_path: server/plugins/Nextron-${{ env.M2_VERSION }}.jar 77 | asset_name: Nextron-${{ env.M2_VERSION }}.jar 78 | asset_content_type: application/java-archive 79 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/SpawnCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.command.RootCommand; 4 | import dev.rollczi.litecommands.annotations.context.Context; 5 | import dev.rollczi.litecommands.annotations.execute.Execute; 6 | import dev.rollczi.litecommands.annotations.argument.Arg; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.pandadev.nextron.Main; 9 | import net.pandadev.nextron.languages.TextAPI; 10 | import org.bukkit.Location; 11 | import org.bukkit.Sound; 12 | import org.bukkit.entity.Player; 13 | 14 | import java.util.Optional; 15 | 16 | @RootCommand 17 | public class SpawnCommand extends HelpBase { 18 | 19 | public SpawnCommand() { 20 | super("spawn, Teleports to the spawn (to set use /setspawn), /spawn [player]\n/sp [player]", 21 | "setspawn, Sets the spawn (teleport to it /spawn), /setspawn"); 22 | } 23 | 24 | @Execute(name = "spawn", aliases = {"sp"}) 25 | @Permission("nextron.spawn") 26 | public void spawnCommand(@Context Player player, @Arg Optional target) { 27 | if (target.isPresent()) { 28 | if (!player.hasPermission("nextron.spawn.other")) { 29 | player.sendMessage(Main.getNoPerm()); 30 | return; 31 | } 32 | 33 | if (Main.getInstance().getConfig().get("spawn") == null) { 34 | player.sendMessage(Main.getPrefix() + TextAPI.get("setspawn.error")); 35 | return; 36 | } 37 | 38 | target.get().teleport((Location) Main.getInstance().getConfig().get("spawn")); 39 | player.playSound(player.getLocation(), Sound.ENTITY_ENDERMAN_TELEPORT, 100, 1); 40 | target.get().sendMessage(Main.getPrefix() + TextAPI.get("spawn.teleport")); 41 | player.sendMessage(Main.getPrefix() + TextAPI.get("spawn.teleport.other").replace("%p", target.get().getName())); 42 | } else { 43 | if (Main.getInstance().getConfig().get("spawn") == null) { 44 | player.sendMessage(Main.getPrefix() + TextAPI.get("setspawn.error")); 45 | return; 46 | } 47 | player.teleport((Location) Main.getInstance().getConfig().get("spawn")); 48 | player.playSound(player.getLocation(), Sound.ENTITY_ENDERMAN_TELEPORT, 100, 1); 49 | player.sendMessage(Main.getPrefix() + TextAPI.get("spawn.teleport")); 50 | } 51 | } 52 | 53 | @Execute(name = "setspawn") 54 | @Permission("nextron.setspawn") 55 | public void setSpawnCommand(@Context Player player) { 56 | Main.getInstance().getConfig().set("spawn", player.getLocation()); 57 | Main.getInstance().saveConfig(); 58 | player.sendMessage(Main.getPrefix() + TextAPI.get("setspawn.success")); 59 | } 60 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/RepairCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.argument.Arg; 4 | import dev.rollczi.litecommands.annotations.command.Command; 5 | import dev.rollczi.litecommands.annotations.context.Context; 6 | import dev.rollczi.litecommands.annotations.execute.Execute; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.pandadev.nextron.Main; 9 | import net.pandadev.nextron.languages.TextAPI; 10 | import org.bukkit.command.CommandSender; 11 | import org.bukkit.entity.Player; 12 | import org.bukkit.inventory.ItemStack; 13 | import org.bukkit.inventory.meta.Damageable; 14 | 15 | import java.util.Optional; 16 | 17 | @Command(name = "repair") 18 | @Permission("nextron.repair") 19 | public class RepairCommand extends HelpBase { 20 | 21 | public RepairCommand() { 22 | super("repair, Repairs the current item in a player hand, /repair [player]"); 23 | } 24 | 25 | @Execute 26 | public void repairCommand(@Context CommandSender sender, @Arg Optional target) { 27 | if (target.isEmpty()) { 28 | if (!(sender instanceof Player player)) { 29 | sender.sendMessage(Main.getCommandInstance()); 30 | return; 31 | } 32 | 33 | ItemStack itemInHand = player.getInventory().getItemInMainHand(); 34 | if (itemInHand.getItemMeta() == null) { 35 | player.sendMessage(Main.getPrefix() + TextAPI.get("repair.error")); 36 | return; 37 | } 38 | if (!(itemInHand.getItemMeta() instanceof Damageable damageable)) { 39 | player.sendMessage(Main.getPrefix() + TextAPI.get("repair.nodamage")); 40 | return; 41 | } 42 | damageable.setDamage(0); 43 | itemInHand.setItemMeta((org.bukkit.inventory.meta.ItemMeta) damageable); 44 | player.sendMessage(Main.getPrefix() + TextAPI.get("repair.success")); 45 | } else { 46 | Player targetPlayer = target.get(); 47 | ItemStack itemInHand = targetPlayer.getInventory().getItemInMainHand(); 48 | if (itemInHand.getItemMeta() == null) { 49 | sender.sendMessage(Main.getPrefix() + TextAPI.get("repair.error.other").replace("%t", targetPlayer.getName())); 50 | return; 51 | } 52 | if (!(itemInHand.getItemMeta() instanceof Damageable damageable)) { 53 | sender.sendMessage(Main.getPrefix() + TextAPI.get("repair.nodamage")); 54 | return; 55 | } 56 | damageable.setDamage(0); 57 | itemInHand.setItemMeta((org.bukkit.inventory.meta.ItemMeta) damageable); 58 | sender.sendMessage(Main.getPrefix() + TextAPI.get("repair.success").replace("%t", targetPlayer.getName())); 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/TpaCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.argument.Arg; 4 | import dev.rollczi.litecommands.annotations.command.Command; 5 | import dev.rollczi.litecommands.annotations.context.Context; 6 | import dev.rollczi.litecommands.annotations.execute.Execute; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.md_5.bungee.api.ChatMessageType; 9 | import net.md_5.bungee.api.chat.ClickEvent; 10 | import net.md_5.bungee.api.chat.HoverEvent; 11 | import net.md_5.bungee.api.chat.TextComponent; 12 | import net.md_5.bungee.api.chat.hover.content.Text; 13 | import net.pandadev.nextron.Main; 14 | import net.pandadev.nextron.apis.SettingsAPI; 15 | import net.pandadev.nextron.languages.TextAPI; 16 | import org.bukkit.Sound; 17 | import org.bukkit.entity.Player; 18 | 19 | @Command(name = "tpa") 20 | @Permission("nextron.tpa") 21 | public class TpaCommand extends HelpBase { 22 | 23 | public TpaCommand() { 24 | super("tpa, Sends a tpa request to a player, /tpa "); 25 | } 26 | 27 | @Execute 28 | public void tpaCommand(@Context Player player, @Arg Player target) { 29 | if (target.equals(player)) { 30 | player.sendMessage(Main.getPrefix() + TextAPI.get("tpa.error")); 31 | return; 32 | } 33 | if (SettingsAPI.allowsTPAs(target)) { 34 | player.sendMessage(Main.getPrefix() + TextAPI.get("tpa.allow")); 35 | return; 36 | } 37 | 38 | Main.tpa.put(target, player); 39 | 40 | target.sendMessage(Main.getPrefix() + TextAPI.get("tpa.target.success.1").replace("%p", player.getName())); 41 | 42 | /////// 43 | 44 | TextComponent component = new TextComponent(TextAPI.get("tpa.target.success.2")); 45 | 46 | TextComponent deny = new TextComponent("§cDeny"); 47 | deny.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/sädfgsklädfgosergopsmfgb09sej405t2poigms0fb89sew4t23ä2mfg908us-" + target.getName())); 48 | deny.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("§7Click to deny the tpa from §a" + player.getName()))); 49 | 50 | TextComponent accept = new TextComponent("§aAccept"); 51 | accept.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/sädfgsklädfgosergopsmfgb09sej405t2poigms0fb89sew4t23ä2mfg908u-" + target.getName())); 52 | accept.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("§7Click to accept the tpa from §a" + player.getName()))); 53 | 54 | component.addExtra(deny); 55 | component.addExtra("§8/"); 56 | component.addExtra(accept); 57 | 58 | /////// 59 | 60 | target.spigot().sendMessage(ChatMessageType.SYSTEM, component); 61 | target.playSound(target.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1.0f, 1.0f); 62 | player.sendMessage(Main.getPrefix() + TextAPI.get("tpa.sender.success").replace("%t", target.getName())); 63 | } 64 | 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/TpahereCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.argument.Arg; 4 | import dev.rollczi.litecommands.annotations.command.Command; 5 | import dev.rollczi.litecommands.annotations.context.Context; 6 | import dev.rollczi.litecommands.annotations.execute.Execute; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.md_5.bungee.api.ChatMessageType; 9 | import net.md_5.bungee.api.chat.ClickEvent; 10 | import net.md_5.bungee.api.chat.HoverEvent; 11 | import net.md_5.bungee.api.chat.TextComponent; 12 | import net.md_5.bungee.api.chat.hover.content.Text; 13 | import net.pandadev.nextron.Main; 14 | import net.pandadev.nextron.apis.SettingsAPI; 15 | import net.pandadev.nextron.languages.TextAPI; 16 | import org.bukkit.Sound; 17 | import org.bukkit.entity.Player; 18 | 19 | @Command(name = "tpahere") 20 | @Permission("nextron.tpahere") 21 | public class TpahereCommand extends HelpBase { 22 | 23 | public TpahereCommand() { 24 | super("tpahere, Sends a tpa request to a player, /tpahere "); 25 | } 26 | 27 | @Execute 28 | void tpahereCommand(@Context Player player, @Arg Player target) { 29 | if (target.equals(player)) { 30 | player.sendMessage(Main.getPrefix() + TextAPI.get("tpahere.error")); 31 | return; 32 | } 33 | if (SettingsAPI.allowsTPAs(target)) { 34 | player.sendMessage(Main.getPrefix() + TextAPI.get("tpahere.allow")); 35 | return; 36 | } 37 | 38 | Main.tpahere.put(target, player); 39 | 40 | target.sendMessage(Main.getPrefix() + TextAPI.get("tpahere.target.success.1").replace("%p", player.getName())); 41 | 42 | ///////////////// 43 | 44 | TextComponent component = new TextComponent(TextAPI.get("tpahere.target.success.2")); 45 | 46 | TextComponent deny = new TextComponent("§cDeny"); 47 | deny.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/487rt6vw9847tv6n293847tv6239487rtvb9we8r6s897rtv6bh9a87evb6-" + target.getName())); 48 | deny.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("§7Click to deny the tpahere request for §a" + player.getName()))); 49 | 50 | TextComponent accept = new TextComponent("§aAccept"); 51 | accept.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/890w45tvb907n845tbn890w35v907n8w34v907n8234v7n890w34b-" + target.getName())); 52 | accept.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("§7Click to accept the tpahere request from §a" + player.getName()))); 53 | 54 | component.addExtra(deny); 55 | component.addExtra("§8/"); 56 | component.addExtra(accept); 57 | 58 | ///////////////// 59 | 60 | target.spigot().sendMessage(ChatMessageType.SYSTEM, component); 61 | target.playSound(target.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1.0f, 1.0f); 62 | player.sendMessage(Main.getPrefix() + TextAPI.get("tpahere.sender.success").replace("%t", target.getName())); 63 | } 64 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/apis/FeatureAPI.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.apis; 2 | 3 | import net.pandadev.nextron.Main; 4 | import net.pandadev.nextron.database.Config; 5 | import org.bukkit.configuration.file.YamlConfiguration; 6 | 7 | import java.io.File; 8 | import java.sql.PreparedStatement; 9 | import java.sql.ResultSet; 10 | import java.sql.SQLException; 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | import java.util.logging.Level; 14 | import java.util.logging.Logger; 15 | 16 | public class FeatureAPI { 17 | private static final Logger LOGGER = Logger.getLogger(FeatureAPI.class.getName()); 18 | private static final Map featureCache = new HashMap<>(); 19 | 20 | public static void setFeature(String featureName, boolean state) { 21 | String sql = "INSERT OR REPLACE INTO features (name, state) VALUES (?, ?)"; 22 | try (PreparedStatement ps = Config.getConnection().prepareStatement(sql)) { 23 | ps.setString(1, featureName); 24 | ps.setBoolean(2, state); 25 | ps.executeUpdate(); 26 | featureCache.put(featureName, state); 27 | } catch (SQLException e) { 28 | LOGGER.log(Level.SEVERE, "Error setting feature state: " + featureName, e); 29 | } 30 | } 31 | 32 | public static boolean getFeature(String featureName) { 33 | if (featureCache.containsKey(featureName)) { 34 | return featureCache.get(featureName); 35 | } 36 | 37 | String sql = "SELECT state FROM features WHERE name = ?"; 38 | try (PreparedStatement ps = Config.getConnection().prepareStatement(sql)) { 39 | ps.setString(1, featureName); 40 | try (ResultSet rs = ps.executeQuery()) { 41 | if (rs.next()) { 42 | boolean state = rs.getBoolean("state"); 43 | featureCache.put(featureName, state); 44 | return state; 45 | } 46 | } 47 | } catch (SQLException e) { 48 | LOGGER.log(Level.SEVERE, "Error getting feature state: " + featureName, e); 49 | } 50 | return false; 51 | } 52 | 53 | public static void migration() { 54 | String checkSql = "SELECT COUNT(*) FROM features"; 55 | try (PreparedStatement checkPs = Config.getConnection().prepareStatement(checkSql); 56 | ResultSet rs = checkPs.executeQuery()) { 57 | if (rs.next() && rs.getInt(1) > 0) { 58 | return; 59 | } 60 | } catch (SQLException e) { 61 | LOGGER.log(Level.SEVERE, "Error checking features table", e); 62 | return; 63 | } 64 | 65 | File featureConfig = new File(Main.getInstance().getDataFolder(), "features.yml"); 66 | if (!featureConfig.exists()) { 67 | return; 68 | } 69 | 70 | YamlConfiguration yamlConfig = YamlConfiguration.loadConfiguration(featureConfig); 71 | String sql = "INSERT OR REPLACE INTO features (name, state) VALUES (?, ?)"; 72 | 73 | try (PreparedStatement ps = Config.getConnection().prepareStatement(sql)) { 74 | for (String key : yamlConfig.getKeys(false)) { 75 | boolean state = yamlConfig.getBoolean(key); 76 | ps.setString(1, key); 77 | ps.setBoolean(2, state); 78 | ps.addBatch(); 79 | } 80 | ps.executeBatch(); 81 | LOGGER.info("Feature data migration completed successfully."); 82 | } catch (SQLException e) { 83 | LOGGER.log(Level.SEVERE, "Error migrating feature data to database", e); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/FeatureCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.argument.Arg; 4 | import dev.rollczi.litecommands.annotations.command.Command; 5 | import dev.rollczi.litecommands.annotations.context.Context; 6 | import dev.rollczi.litecommands.annotations.execute.Execute; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.pandadev.nextron.Main; 9 | import net.pandadev.nextron.apis.FeatureAPI; 10 | import net.pandadev.nextron.apis.RankAPI; 11 | import net.pandadev.nextron.arguments.objects.Feature; 12 | import net.pandadev.nextron.guis.GUIs; 13 | import net.pandadev.nextron.languages.TextAPI; 14 | import org.bukkit.Bukkit; 15 | import org.bukkit.Sound; 16 | import org.bukkit.command.CommandSender; 17 | import org.bukkit.entity.Player; 18 | 19 | import java.util.Objects; 20 | 21 | @Command(name = "features") 22 | @Permission("nextron.features") 23 | public class FeatureCommand extends HelpBase { 24 | 25 | public FeatureCommand() { 26 | super("features, Opens a GUI where you can enable/disable all the systems in the plugin, /features [enable/disable] [feature]"); 27 | } 28 | 29 | @Execute() 30 | void featuresCommand(@Context Player player) { 31 | if (!player.isOp()) { 32 | player.sendMessage(Main.getNoPerm()); 33 | return; 34 | } 35 | GUIs.featureGui(player); 36 | player.playSound(player.getLocation(), Sound.BLOCK_BARREL_OPEN, 100, 1); 37 | } 38 | 39 | @Execute(name = "enable") 40 | void enableCommand(@Context CommandSender sender, @Arg Feature feature) { 41 | FeatureAPI.setFeature(feature.getName(), true); 42 | for (Player onlineplayer : Bukkit.getOnlinePlayers()) { 43 | if (feature.getName().replace("_system", "").equals("tpa")) { 44 | onlineplayer.addAttachment(Main.getInstance()).setPermission("nextron.tpaccept", 45 | FeatureAPI.getFeature(feature.getName())); 46 | } 47 | onlineplayer.addAttachment(Main.getInstance()).setPermission( 48 | "nextron." + feature.getName().replace("_system", ""), FeatureAPI.getFeature(feature.getName())); 49 | if (feature.getName().replace("_system", "").equalsIgnoreCase("rank")) { 50 | RankAPI.checkRank(onlineplayer); 51 | Main.getInstance().getTablistManager().setAllPlayerTeams(); 52 | } 53 | } 54 | if (sender instanceof Player) { 55 | Player player = (Player) (sender); 56 | player.playSound(player.getLocation(), Sound.BLOCK_BEACON_ACTIVATE, 100, 1); 57 | } 58 | sender.sendMessage( 59 | Main.getPrefix() + TextAPI.get("feature.enable").replace("%n", feature.getName().replace("_system", ""))); 60 | } 61 | 62 | @Execute(name = "disable") 63 | void disableCommand(@Context CommandSender sender, @Arg Feature feature) { 64 | FeatureAPI.setFeature(feature.getName(), false); 65 | for (Player onlineplayer : Bukkit.getOnlinePlayers()) { 66 | if (Objects.equals(feature.getName().replace("_system", ""), "tpa")) { 67 | onlineplayer.addAttachment(Main.getInstance()).setPermission("nextron.tpaccept", 68 | FeatureAPI.getFeature(feature.getName())); 69 | } 70 | onlineplayer.addAttachment(Main.getInstance()).setPermission( 71 | "nextron." + feature.getName().replace("_system", ""), FeatureAPI.getFeature(feature.getName())); 72 | if (feature.getName().replace("_system", "").equalsIgnoreCase("rank")) { 73 | RankAPI.checkRank(onlineplayer); 74 | Main.getInstance().getTablistManager().setAllPlayerTeams(); 75 | } 76 | } 77 | if (sender instanceof Player) { 78 | Player player = (Player) (sender); 79 | player.playSound(player.getLocation(), Sound.BLOCK_BEACON_DEACTIVATE, 100, 1); 80 | } 81 | sender.sendMessage( 82 | Main.getPrefix() + TextAPI.get("feature.disable").replace("%n", feature.getName().replace("_system", ""))); 83 | } 84 | 85 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/utils/UpdateChecker.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.utils; 2 | 3 | import com.google.gson.JsonArray; 4 | import com.google.gson.JsonElement; 5 | import com.google.gson.JsonObject; 6 | import com.google.gson.JsonParser; 7 | import org.bukkit.plugin.java.JavaPlugin; 8 | 9 | import java.io.IOException; 10 | import java.net.HttpURLConnection; 11 | import java.net.URL; 12 | import java.util.Scanner; 13 | 14 | public class UpdateChecker { 15 | private final JavaPlugin plugin; 16 | private final String repoName; 17 | 18 | public UpdateChecker(JavaPlugin plugin, String repoName) { 19 | this.plugin = plugin; 20 | this.repoName = repoName; 21 | } 22 | 23 | public void checkForUpdates() { 24 | try { 25 | String latestReleaseTag = getLatestReleaseTag(); 26 | String currentVersion = plugin.getDescription().getVersion(); 27 | if (isVersionNewer(latestReleaseTag, currentVersion)) { 28 | System.out.println(" "); 29 | System.out.println("§8---------------< §x§b§1§8§0§f§f§lNextron Update §8>---------------"); 30 | System.out.println(" "); 31 | System.out.println("§7Current version: §cv" + currentVersion); 32 | System.out.println("§7Latest version: §a" + latestReleaseTag); 33 | System.out.println(" "); 34 | System.out.println("§8------------------------------------------------"); 35 | System.out.println(" "); 36 | } else { 37 | plugin.getLogger().info("Plugin is up to date."); 38 | } 39 | } catch (IOException e) { 40 | plugin.getLogger().warning("Failed to check for updates: " + e.getMessage()); 41 | } 42 | } 43 | 44 | private String getLatestReleaseTag() throws IOException { 45 | String url = "https://api.github.com/repos/" + repoName + "/releases"; 46 | HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); 47 | connection.setRequestMethod("GET"); 48 | 49 | int statusCode = connection.getResponseCode(); 50 | if (statusCode == HttpURLConnection.HTTP_OK) { 51 | Scanner scanner = new Scanner(connection.getInputStream()); 52 | String responseBody = scanner.useDelimiter("\\A").next(); 53 | scanner.close(); 54 | // Find the first release that's not a draft 55 | JsonArray releases = JsonParser.parseString(responseBody).getAsJsonArray(); 56 | for (JsonElement releaseElement : releases) { 57 | JsonObject release = releaseElement.getAsJsonObject(); 58 | boolean isDraft = release.get("draft").getAsBoolean(); 59 | if (!isDraft) { 60 | return release.get("tag_name").getAsString(); 61 | } 62 | } 63 | 64 | // If no non-draft releases were found, return the latest tag 65 | if (!releases.isJsonNull() && !releases.isEmpty()) { 66 | JsonObject latestRelease = releases.get(0).getAsJsonObject(); 67 | return latestRelease.get("tag_name").getAsString(); 68 | } 69 | 70 | // If no releases were found at all, throw an exception 71 | throw new IOException("Failed to retrieve release information from GitHub API."); 72 | } else { 73 | throw new IOException("Failed to retrieve release information from GitHub API. Status code: " + statusCode); 74 | } 75 | } 76 | 77 | public static boolean isVersionNewer(String remoteVersion, String currentVersion) { 78 | int remote = Integer.parseInt(remoteVersion.replaceAll("\\D+", "")); 79 | int current = Integer.parseInt(currentVersion.replaceAll("\\D+", "")); 80 | 81 | if (String.valueOf(current).length() == 4 && String.valueOf(remote).length() == 4) return remote > current; 82 | 83 | else if (String.valueOf(remote).length() == 4) 84 | return !(Integer.parseInt(String.valueOf(remote).substring(0, String.valueOf(remote).length() - 1)) <= current); 85 | 86 | else if (String.valueOf(current).length() == 4) 87 | return remote >= Integer.parseInt(String.valueOf(current).substring(0, String.valueOf(current).length() - 1)); 88 | 89 | return remote > current; 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/languages/LanguageLoader.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.languages; 2 | 3 | import net.pandadev.nextron.Main; 4 | import org.bukkit.plugin.java.JavaPlugin; 5 | 6 | import java.io.*; 7 | import java.net.URI; 8 | import java.net.URL; 9 | import java.nio.file.*; 10 | import java.util.Collections; 11 | import java.util.stream.Stream; 12 | 13 | public class LanguageLoader { 14 | private static String currentLanguage = "en"; 15 | 16 | public static void setLanguage(String language) { 17 | currentLanguage = language; 18 | } 19 | 20 | public static String getLanguage() { 21 | return currentLanguage; 22 | } 23 | 24 | public static void saveLanguages() { 25 | JavaPlugin plugin = Main.getInstance(); 26 | File langFolder = new File(plugin.getDataFolder(), "lang"); 27 | 28 | if (langFolder.exists()) { 29 | deleteDirectory(langFolder); 30 | } 31 | 32 | if (!langFolder.mkdirs()) { 33 | plugin.getLogger().severe("Failed to create language folder"); 34 | return; 35 | } 36 | 37 | try { 38 | URL url = plugin.getClass().getResource("/lang"); 39 | if (url == null) { 40 | plugin.getLogger().severe("Language resource folder not found"); 41 | return; 42 | } 43 | 44 | URI uri = url.toURI(); 45 | Path myPath; 46 | FileSystem fileSystem = null; 47 | try { 48 | if (uri.getScheme().equals("jar")) { 49 | try { 50 | fileSystem = FileSystems.getFileSystem(uri); 51 | } catch (FileSystemNotFoundException e) { 52 | fileSystem = FileSystems.newFileSystem(uri, Collections.emptyMap()); 53 | } 54 | myPath = fileSystem.getPath("/lang"); 55 | } else { 56 | myPath = Paths.get(uri); 57 | } 58 | 59 | try (Stream walk = Files.walk(myPath, 1)) { 60 | walk.filter(path -> !Files.isDirectory(path)) 61 | .forEach(path -> { 62 | String fileName = path.getFileName().toString(); 63 | File outFile = new File(langFolder, fileName); 64 | try (InputStream in = plugin.getResource("lang/" + fileName); 65 | OutputStream out = new FileOutputStream(outFile)) { 66 | if (in == null) { 67 | plugin.getLogger().warning("Language file not found in jar: " + fileName); 68 | return; 69 | } 70 | byte[] buffer = new byte[1024]; 71 | int length; 72 | while ((length = in.read(buffer)) > 0) { 73 | out.write(buffer, 0, length); 74 | } 75 | } catch (IOException e) { 76 | plugin.getLogger().severe("Failed to save language file: " + fileName); 77 | e.printStackTrace(); 78 | } 79 | }); 80 | } 81 | } finally { 82 | if (fileSystem != null && fileSystem != FileSystems.getDefault()) { 83 | fileSystem.close(); 84 | } 85 | } 86 | } catch (Exception e) { 87 | plugin.getLogger().severe("Failed to save language files"); 88 | e.printStackTrace(); 89 | } 90 | } 91 | 92 | private static void deleteDirectory(File directory) { 93 | if (directory.exists()) { 94 | File[] files = directory.listFiles(); 95 | if (files != null) { 96 | for (File file : files) { 97 | if (file.isDirectory()) { 98 | deleteDirectory(file); 99 | } else { 100 | file.delete(); 101 | } 102 | } 103 | } 104 | directory.delete(); 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/RankCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.argument.Arg; 4 | import dev.rollczi.litecommands.annotations.command.RootCommand; 5 | import dev.rollczi.litecommands.annotations.context.Context; 6 | import dev.rollczi.litecommands.annotations.execute.Execute; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.pandadev.nextron.Main; 9 | import net.pandadev.nextron.apis.RankAPI; 10 | import net.pandadev.nextron.arguments.objects.Rank; 11 | import net.pandadev.nextron.guis.features.RankGUIs; 12 | import net.pandadev.nextron.languages.TextAPI; 13 | import net.pandadev.nextron.utils.Utils; 14 | import net.wesjd.anvilgui.AnvilGUI; 15 | import org.bukkit.ChatColor; 16 | import org.bukkit.Material; 17 | import org.bukkit.Sound; 18 | import org.bukkit.command.CommandSender; 19 | import org.bukkit.entity.Player; 20 | import org.bukkit.inventory.ItemStack; 21 | 22 | import java.util.Collections; 23 | import java.util.List; 24 | 25 | @RootCommand 26 | public class RankCommand extends HelpBase { 27 | 28 | public RankCommand() { 29 | super("rank, Allows you to create ranks with prefixes to group players, /rank create\n/rank delete \n/rank modify \n/rank remove \n/rank set "); 30 | } 31 | 32 | @Execute(name = "rank") 33 | @Permission("nextron.rank") 34 | public void rankCommand(@Context Player player) { 35 | List ranks = RankAPI.getRanks(); 36 | if (ranks.isEmpty()) { 37 | player.sendMessage(Main.getPrefix() + TextAPI.get("maingui.no.ranks")); 38 | player.playSound(player.getLocation(), Sound.ENTITY_PILLAGER_AMBIENT, 100, 0.5f); 39 | return; 40 | } 41 | 42 | RankGUIs.manager(player); 43 | } 44 | 45 | @Execute(name = "rank set") 46 | @Permission("nextron.rank.set") 47 | public void setRankCommand(@Context CommandSender sender, @Arg Player target, @Arg Rank rank) { 48 | RankAPI.setRank(sender, target, rank.getName()); 49 | RankAPI.checkRank(target); 50 | } 51 | 52 | @Execute(name = "rank remove") 53 | @Permission("nextron.rank.remove") 54 | public void removeRankCommand(@Context CommandSender sender, @Arg Player target) { 55 | RankAPI.removeRanks(target); 56 | RankAPI.checkRank(target); 57 | 58 | sender.sendMessage(Main.getPrefix() 59 | + TextAPI.get("rank.remove.success").replace("%t", target.getName())); 60 | } 61 | 62 | @Execute(name = "rank delete") 63 | @Permission("nextron.rank.delete") 64 | public void removeRankCommand(@Context CommandSender sender, @Arg Rank rank) { 65 | RankAPI.deleteRank((Player) sender, rank.getName().toLowerCase()); 66 | } 67 | 68 | @Execute(name = "rank create") 69 | @Permission("nextron.rank.create") 70 | public void createRankCommand(@Context Player player) { 71 | RankGUIs.templateRanks(player); 72 | } 73 | 74 | @Execute(name = "rank prefix") 75 | @Permission("nextron.rank.prefix") 76 | public void prefixRankCommand(@Context Player player, @Arg Rank rank) { 77 | new AnvilGUI.Builder() 78 | .onClick((state, text) -> { 79 | RankAPI.setPrefix(player, rank.getName().toLowerCase(), 80 | ChatColor.translateAlternateColorCodes('&', " " + text.getText())); 81 | return Collections.singletonList(AnvilGUI.ResponseAction.close()); 82 | }) 83 | .text(RankAPI.getRankPrefix(rank.getName().toLowerCase()).replace("§", "&")) 84 | .itemLeft(new ItemStack(Material.NAME_TAG)) 85 | .title("Enter the new prefix") 86 | .plugin(Main.getInstance()) 87 | .open(player); 88 | } 89 | 90 | @Execute(name = "rank name") 91 | @Permission("nextron.rank.name") 92 | public void nameRankCommand(@Context Player player, @Arg Rank rank) { 93 | new AnvilGUI.Builder() 94 | .onClick((state, text) -> { 95 | if (Utils.countWords(text.getText()) > 1) { 96 | player.playSound(player.getLocation(), Sound.ENTITY_PILLAGER_AMBIENT, 100, 0.5f); 97 | return Collections.singletonList(AnvilGUI.ResponseAction 98 | .replaceInputText(TextAPI.get("anvil.gui.one.word"))); 99 | } 100 | RankAPI.rename(player, rank.getName().toLowerCase(), 101 | ChatColor.translateAlternateColorCodes('&', " " + text.getText())); 102 | return Collections.singletonList(AnvilGUI.ResponseAction.close()); 103 | }) 104 | .text(rank.getName().toLowerCase()) 105 | .itemLeft(new ItemStack(Material.NAME_TAG)) 106 | .title("Enter the new name") 107 | .plugin(Main.getInstance()) 108 | .open(player); 109 | } 110 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/WarpCommands.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.argument.Arg; 4 | import dev.rollczi.litecommands.annotations.command.RootCommand; 5 | import dev.rollczi.litecommands.annotations.context.Context; 6 | import dev.rollczi.litecommands.annotations.execute.Execute; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.pandadev.nextron.Main; 9 | import net.pandadev.nextron.apis.SettingsAPI; 10 | import net.pandadev.nextron.apis.WarpAPI; 11 | import net.pandadev.nextron.arguments.objects.Warp; 12 | import net.pandadev.nextron.languages.TextAPI; 13 | import net.pandadev.nextron.utils.Utils; 14 | import net.wesjd.anvilgui.AnvilGUI; 15 | import org.bukkit.Location; 16 | import org.bukkit.Material; 17 | import org.bukkit.Sound; 18 | import org.bukkit.command.CommandSender; 19 | import org.bukkit.entity.Player; 20 | import org.bukkit.inventory.ItemStack; 21 | 22 | import java.util.Collections; 23 | 24 | @RootCommand 25 | public class WarpCommands extends HelpBase { 26 | 27 | public WarpCommands() { 28 | super( 29 | "warp, Teleports you to a warp, /warp \n/w ", 30 | "setwarp, Sets a new warp, /setwarp ", 31 | "delwarp, Deletes a warp, /delwarp ", 32 | "renamewarp, Renames a warp, /renamewarp "); 33 | } 34 | 35 | @Execute(name = "warp", aliases = {"w"}) 36 | @Permission("nextron.warp") 37 | public void warpCommand(@Context Player player, @Arg Warp warp) { 38 | Location location = WarpAPI.getWarp(warp.getName().toLowerCase()); 39 | if (location == null) { 40 | player.sendMessage(Main.getPrefix() + TextAPI.get("warp.error").replace("%w", warp.getName().toLowerCase())); 41 | return; 42 | } 43 | player.teleport(location); 44 | if (SettingsAPI.allowsFeedback(player)) 45 | player.sendMessage(Main.getPrefix() + TextAPI.get("warp.success").replace("%w", warp.getName().toLowerCase())); 46 | player.playSound(player.getLocation(), Sound.ENTITY_ENDERMAN_TELEPORT, 1.0f, 1.0f); 47 | } 48 | 49 | @Execute(name = "setwarp") 50 | @Permission("nextron.setwarp") 51 | public void setWarpCommand(@Context Player player, @Arg String name) { 52 | if (WarpAPI.getWarp(name.toLowerCase()) != null) { 53 | player.sendMessage(Main.getPrefix() + TextAPI.get("setwarp.error").replace("%w", name.toLowerCase())); 54 | return; 55 | } 56 | WarpAPI.setWarp(name.toLowerCase(), player.getLocation()); 57 | player.sendMessage(Main.getPrefix() + TextAPI.get("setwarp.success").replace("%w", name.toLowerCase())); 58 | } 59 | 60 | @Execute(name = "delwarp") 61 | @Permission("nextron.delwarp") 62 | public void deleteWarpCommand(@Context CommandSender sender, @Arg Warp warp) { 63 | if (WarpAPI.getWarp(warp.getName().toLowerCase()) == null) { 64 | sender.sendMessage(Main.getPrefix() + TextAPI.get("delwarp.error").replace("%w", warp.getName().toLowerCase())); 65 | return; 66 | } 67 | WarpAPI.deleteWarp(warp.getName().toLowerCase()); 68 | sender.sendMessage(Main.getPrefix() + TextAPI.get("delwarp.success").replace("%w", warp.getName().toLowerCase())); 69 | } 70 | 71 | @Execute(name = "renamewarp") 72 | @Permission("nextron.renamewarp") 73 | public void renameWarpCommand(@Context Player player, @Arg Warp warp) { 74 | if (WarpAPI.getWarp(warp.getName().toLowerCase()) == null) { 75 | player.sendMessage(Main.getPrefix() + TextAPI.get("warp.error").replace("%w", warp.getName().toLowerCase())); 76 | return; 77 | } 78 | 79 | new AnvilGUI.Builder() 80 | .onClick((state, text) -> { 81 | if (Utils.countWords(text.getText()) > 1) { 82 | player.playSound(player.getLocation(), Sound.ENTITY_PILLAGER_AMBIENT, 100, 0.5f); 83 | return Collections.singletonList( 84 | AnvilGUI.ResponseAction.replaceInputText(TextAPI.get("anvil_gui_one_word"))); 85 | } 86 | Location oldLocation = WarpAPI.getWarp(warp.getName().toLowerCase()); 87 | WarpAPI.setWarp(text.getText().toLowerCase(), oldLocation); 88 | WarpAPI.deleteWarp(warp.getName().toLowerCase()); 89 | player.sendMessage(Main.getPrefix() + TextAPI.get("warp.rename.success").replace("%w", warp.getName()) 90 | .replace("%n", text.getText())); 91 | return Collections.singletonList(AnvilGUI.ResponseAction.close()); 92 | }) 93 | .text(warp.getName()) 94 | .preventClose() 95 | .itemLeft(new ItemStack(Material.NAME_TAG)) 96 | .title("Enter a name") 97 | .plugin(Main.getInstance()) 98 | .open(player); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/apis/WarpAPI.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.apis; 2 | 3 | import net.pandadev.nextron.Main; 4 | import net.pandadev.nextron.database.Config; 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.Location; 7 | import org.bukkit.configuration.ConfigurationSection; 8 | import org.bukkit.configuration.file.YamlConfiguration; 9 | 10 | import java.io.File; 11 | import java.sql.PreparedStatement; 12 | import java.sql.ResultSet; 13 | import java.sql.SQLException; 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | import java.util.logging.Level; 17 | import java.util.logging.Logger; 18 | 19 | public class WarpAPI { 20 | private static final Logger LOGGER = Logger.getLogger(WarpAPI.class.getName()); 21 | 22 | public static void setWarp(String warpName, Location location) { 23 | String sql = "INSERT OR REPLACE INTO warps (name, world, x, y, z, yaw, pitch) VALUES (?, ?, ?, ?, ?, ?, ?)"; 24 | try (PreparedStatement ps = Config.getConnection().prepareStatement(sql)) { 25 | ps.setString(1, warpName); 26 | ps.setString(2, location.getWorld().getName()); 27 | ps.setDouble(3, location.getX()); 28 | ps.setDouble(4, location.getY()); 29 | ps.setDouble(5, location.getZ()); 30 | ps.setFloat(6, location.getYaw()); 31 | ps.setFloat(7, location.getPitch()); 32 | ps.executeUpdate(); 33 | } catch (SQLException e) { 34 | LOGGER.log(Level.SEVERE, "Error setting warp: " + warpName, e); 35 | } 36 | } 37 | 38 | public static void deleteWarp(String warpName) { 39 | String sql = "DELETE FROM warps WHERE name = ?"; 40 | try (PreparedStatement ps = Config.getConnection().prepareStatement(sql)) { 41 | ps.setString(1, warpName); 42 | ps.executeUpdate(); 43 | } catch (SQLException e) { 44 | LOGGER.log(Level.SEVERE, "Error deleting warp: " + warpName, e); 45 | } 46 | } 47 | 48 | public static Location getWarp(String warpName) { 49 | String sql = "SELECT world, x, y, z, yaw, pitch FROM warps WHERE name = ?"; 50 | try (PreparedStatement ps = Config.getConnection().prepareStatement(sql)) { 51 | ps.setString(1, warpName); 52 | try (ResultSet rs = ps.executeQuery()) { 53 | if (rs.next()) { 54 | return new Location( 55 | Bukkit.getWorld(rs.getString("world")), 56 | rs.getDouble("x"), 57 | rs.getDouble("y"), 58 | rs.getDouble("z"), 59 | rs.getFloat("yaw"), 60 | rs.getFloat("pitch") 61 | ); 62 | } 63 | } 64 | } catch (SQLException e) { 65 | LOGGER.log(Level.SEVERE, "Error getting warp: " + warpName, e); 66 | } 67 | return null; 68 | } 69 | 70 | public static List getWarps() { 71 | List warps = new ArrayList<>(); 72 | String sql = "SELECT name FROM warps ORDER BY name"; 73 | try (PreparedStatement ps = Config.getConnection().prepareStatement(sql); 74 | ResultSet rs = ps.executeQuery()) { 75 | while (rs.next()) { 76 | warps.add(rs.getString("name")); 77 | } 78 | } catch (SQLException e) { 79 | LOGGER.log(Level.SEVERE, "Error getting warps", e); 80 | } 81 | return warps; 82 | } 83 | 84 | public static void migration() { 85 | String checkSql = "SELECT COUNT(*) FROM warps"; 86 | try (PreparedStatement checkPs = Config.getConnection().prepareStatement(checkSql); 87 | ResultSet rs = checkPs.executeQuery()) { 88 | if (rs.next() && rs.getInt(1) > 0) { 89 | return; 90 | } 91 | } catch (SQLException e) { 92 | LOGGER.log(Level.SEVERE, "Error checking warps table", e); 93 | return; 94 | } 95 | 96 | File warpConfig = new File(Main.getInstance().getDataFolder(), "warps.yml"); 97 | if (!warpConfig.exists()) { 98 | return; 99 | } 100 | 101 | YamlConfiguration yamlConfig = YamlConfiguration.loadConfiguration(warpConfig); 102 | ConfigurationSection warpsSection = yamlConfig.getConfigurationSection("Warps"); 103 | 104 | if (warpsSection == null) { 105 | return; 106 | } 107 | 108 | String sql = "INSERT INTO warps (name, world, x, y, z, yaw, pitch) VALUES (?, ?, ?, ?, ?, ?, ?)"; 109 | 110 | try (PreparedStatement ps = Config.getConnection().prepareStatement(sql)) { 111 | for (String warpName : warpsSection.getKeys(false)) { 112 | Location loc = warpsSection.getLocation(warpName); 113 | if (loc != null) { 114 | ps.setString(1, warpName); 115 | ps.setString(2, loc.getWorld().getName()); 116 | ps.setDouble(3, loc.getX()); 117 | ps.setDouble(4, loc.getY()); 118 | ps.setDouble(5, loc.getZ()); 119 | ps.setFloat(6, loc.getYaw()); 120 | ps.setFloat(7, loc.getPitch()); 121 | ps.addBatch(); 122 | } 123 | } 124 | ps.executeBatch(); 125 | LOGGER.info("Warp data migration completed successfully."); 126 | } catch (SQLException e) { 127 | LOGGER.log(Level.SEVERE, "Error migrating warp data to database", e); 128 | } 129 | } 130 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/guis/features/HomeGUIs.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.guis.features; 2 | 3 | import dev.triumphteam.gui.builder.item.ItemBuilder; 4 | import dev.triumphteam.gui.guis.Gui; 5 | import net.kyori.adventure.text.Component; 6 | import net.pandadev.nextron.Main; 7 | import net.pandadev.nextron.apis.HomeAPI; 8 | import net.pandadev.nextron.guis.GUIs; 9 | import net.pandadev.nextron.languages.TextAPI; 10 | import net.wesjd.anvilgui.AnvilGUI; 11 | import org.bukkit.Location; 12 | import org.bukkit.Material; 13 | import org.bukkit.Sound; 14 | import org.bukkit.entity.Player; 15 | 16 | import java.util.Collections; 17 | import java.util.List; 18 | 19 | public class HomeGUIs { 20 | 21 | public static void manager(Player player) { 22 | Gui gui = Gui.gui() 23 | .title(Component.text("Home Manager")) 24 | .rows(5) 25 | .disableAllInteractions() 26 | .create(); 27 | 28 | List homes = HomeAPI.getHomes(player); 29 | for (String home : homes) { 30 | gui.addItem(ItemBuilder.skull() 31 | .texture("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjNkMDJjZGMwNzViYjFjYzVmNmZlM2M3NzExYWU0OTc3ZTM4YjkxMGQ1MGVkNjAyM2RmNzM5MTNlNWU3ZmNmZiJ9fX0=") 32 | .name(Component.text("§f" + home)) 33 | .lore(List.of( 34 | Component.empty(), 35 | Component.text(TextAPI.get("homegui.leftclick")), 36 | Component.text(TextAPI.get("homegui.rightclick")) 37 | )) 38 | .asGuiItem(inventoryClickEvent -> { 39 | if (inventoryClickEvent.getClick().isRightClick()) { 40 | Location location = HomeAPI.getHome(player, home); 41 | if (location != null) { 42 | player.teleport(location); 43 | player.playSound(player.getLocation(), Sound.ENTITY_ENDERMAN_TELEPORT, 1.0f, 1.0f); 44 | player.closeInventory(); 45 | } 46 | } else if (inventoryClickEvent.getClick().isLeftClick()) { 47 | settings(player, home); 48 | } 49 | })); 50 | } 51 | 52 | gui.setItem(5, 1, ItemBuilder.skull().texture("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmQ2OWUwNmU1ZGFkZmQ4NGU1ZjNkMWMyMTA2M2YyNTUzYjJmYTk0NWVlMWQ0ZDcxNTJmZGM1NDI1YmMxMmE5In19fQ==").name(Component.text("§fBack")).asGuiItem(inventoryClickEvent -> { 53 | GUIs.mainGui(player); 54 | })); 55 | 56 | gui.open(player); 57 | } 58 | 59 | public static void settings(Player player, String home) { 60 | Gui gui = Gui.gui() 61 | .title(Component.text("§7" + home)) 62 | .rows(3) 63 | .disableAllInteractions() 64 | .create(); 65 | 66 | gui.setItem(2, 4, ItemBuilder.from(Material.ENDER_PEARL) 67 | .name(Component.text("§3Teleport")) 68 | .asGuiItem(inventoryClickEvent -> { 69 | Location location = HomeAPI.getHome(player, home); 70 | if (location != null) { 71 | player.teleport(location); 72 | player.playSound(player.getLocation(), Sound.ENTITY_ENDERMAN_TELEPORT, 1.0f, 1.0f); 73 | player.closeInventory(); 74 | } 75 | })); 76 | 77 | gui.setItem(2, 5, ItemBuilder.from(Material.YELLOW_DYE) 78 | .name(Component.text("§eRename")) 79 | .asGuiItem(inventoryClickEvent -> { 80 | new AnvilGUI.Builder() 81 | .onClick((state, text) -> { 82 | HomeAPI.renameHome(player, home, text.getText()); 83 | player.sendMessage(Main.getPrefix() + TextAPI.get("home.rename.success").replace("%h", home) 84 | .replace("%n", text.getText())); 85 | return Collections.singletonList(AnvilGUI.ResponseAction.close()); 86 | }) 87 | .text(home) 88 | .itemLeft(new net.pandadev.nextron.utils.ItemBuilder(Material.NAME_TAG).setName("§x§e§6§c§7§8§c" + home).build()) 89 | .title("Type the new Name") 90 | .plugin(Main.getInstance()) 91 | .open(player); 92 | })); 93 | 94 | gui.setItem(2, 6, ItemBuilder.from(Material.RED_DYE).name(Component.text("§cDelete")).asGuiItem(inventoryClickEvent -> { 95 | HomeAPI.deleteHome(player, home); 96 | if (HomeAPI.getHomes(player).isEmpty()) { 97 | player.closeInventory(); 98 | } else { 99 | manager(player); 100 | } 101 | player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1.0f, 1.0f); 102 | })); 103 | 104 | gui.setItem(3, 1, ItemBuilder.skull().texture("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmQ2OWUwNmU1ZGFkZmQ4NGU1ZjNkMWMyMTA2M2YyNTUzYjJmYTk0NWVlMWQ0ZDcxNTJmZGM1NDI1YmMxMmE5In19fQ==").name(Component.text("§fBack")).asGuiItem(inventoryClickEvent -> { 105 | manager(player); 106 | })); 107 | 108 | gui.open(player); 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/guis/features/WarpGUIs.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.guis.features; 2 | 3 | import dev.triumphteam.gui.builder.item.ItemBuilder; 4 | import dev.triumphteam.gui.guis.Gui; 5 | import net.kyori.adventure.text.Component; 6 | import net.pandadev.nextron.Main; 7 | import net.pandadev.nextron.apis.WarpAPI; 8 | import net.pandadev.nextron.guis.GUIs; 9 | import net.pandadev.nextron.languages.TextAPI; 10 | import net.wesjd.anvilgui.AnvilGUI; 11 | import org.bukkit.Location; 12 | import org.bukkit.Material; 13 | import org.bukkit.Sound; 14 | import org.bukkit.entity.Player; 15 | 16 | import java.util.Collections; 17 | import java.util.List; 18 | 19 | public class WarpGUIs { 20 | 21 | public static void manager(Player player) { 22 | Gui gui = Gui.gui() 23 | .title(Component.text("Warp Manager")) 24 | .rows(5) 25 | .disableAllInteractions() 26 | .create(); 27 | 28 | List warps = WarpAPI.getWarps(); 29 | for (String warp : warps) { 30 | gui.addItem(ItemBuilder.from(Material.NETHER_STAR) 31 | .name(Component.text("§f" + warp)) 32 | .lore(Component.empty(), Component.text(TextAPI.get("warpgui.leftclick")), Component.text(TextAPI.get("warpgui.rightclick"))) 33 | .asGuiItem(inventoryClickEvent -> { 34 | if (inventoryClickEvent.getClick().isRightClick()) { 35 | Location location = WarpAPI.getWarp(warp); 36 | if (location != null) { 37 | player.teleport(location); 38 | player.playSound(player.getLocation(), Sound.ENTITY_ENDERMAN_TELEPORT, 1.0f, 1.0f); 39 | player.closeInventory(); 40 | } 41 | } else if (inventoryClickEvent.getClick().isLeftClick()) { 42 | settings(player, warp); 43 | } 44 | })); 45 | } 46 | 47 | gui.setItem(5, 1, ItemBuilder.skull().texture("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmQ2OWUwNmU1ZGFkZmQ4NGU1ZjNkMWMyMTA2M2YyNTUzYjJmYTk0NWVlMWQ0ZDcxNTJmZGM1NDI1YmMxMmE5In19fQ==").name(Component.text("§fBack")).asGuiItem(inventoryClickEvent -> { 48 | GUIs.mainGui(player); 49 | })); 50 | 51 | gui.open(player); 52 | } 53 | 54 | public static void settings(Player player, String warp) { 55 | Gui gui = Gui.gui() 56 | .title(Component.text(warp)) 57 | .rows(3) 58 | .disableAllInteractions() 59 | .create(); 60 | 61 | gui.setItem(2, 4, ItemBuilder.from(Material.ENDER_PEARL) 62 | .name(Component.text("§x§0§1§5§9§5§6Teleport")) 63 | .asGuiItem(inventoryClickEvent -> { 64 | Location location = WarpAPI.getWarp(warp); 65 | if (location != null) { 66 | player.teleport(location); 67 | player.playSound(player.getLocation(), Sound.ENTITY_ENDERMAN_TELEPORT, 1.0f, 1.0f); 68 | player.closeInventory(); 69 | } 70 | })); 71 | 72 | gui.setItem(2, 5, ItemBuilder.from(Material.YELLOW_DYE) 73 | .name(Component.text("§eRename")) 74 | .asGuiItem(inventoryClickEvent -> { 75 | if (!player.hasPermission("nextron.rename")) { 76 | player.sendMessage(Main.getNoPerm()); 77 | return; 78 | } 79 | 80 | new AnvilGUI.Builder() 81 | .onClick((state, text) -> { 82 | Location location = WarpAPI.getWarp(warp); 83 | if (location != null) { 84 | WarpAPI.setWarp(text.getText(), location); 85 | WarpAPI.deleteWarp(warp); 86 | player.sendMessage(Main.getPrefix() + TextAPI.get("warp.rename.success").replace("%w", warp) 87 | .replace("%n", text.getText())); 88 | } 89 | return Collections.singletonList(AnvilGUI.ResponseAction.close()); 90 | }) 91 | .text(warp) 92 | .itemLeft(new net.pandadev.nextron.utils.ItemBuilder(Material.NAME_TAG).setName("§x§e§6§c§7§8§c" + warp).build()) 93 | .title("Type the new Name") 94 | .plugin(Main.getInstance()) 95 | .open(player); 96 | })); 97 | 98 | gui.setItem(2, 6, ItemBuilder.from(Material.RED_DYE).name(Component.text("§cDelete")).asGuiItem(inventoryClickEvent -> { 99 | WarpAPI.deleteWarp(warp); 100 | if (WarpAPI.getWarps().isEmpty()) { 101 | player.closeInventory(); 102 | } else { 103 | manager(player); 104 | } 105 | player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1.0f, 1.0f); 106 | })); 107 | 108 | gui.setItem(3, 1, ItemBuilder.skull().texture("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmQ2OWUwNmU1ZGFkZmQ4NGU1ZjNkMWMyMTA2M2YyNTUzYjJmYTk0NWVlMWQ0ZDcxNTJmZGM1NDI1YmMxMmE5In19fQ==").name(Component.text("§fBack")).asGuiItem(inventoryClickEvent -> { 109 | manager(player); 110 | })); 111 | 112 | gui.open(player); 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/listeners/ClickableMessages.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.listeners; 2 | 3 | import net.pandadev.nextron.Main; 4 | import net.pandadev.nextron.apis.HomeAPI; 5 | import net.pandadev.nextron.apis.SettingsAPI; 6 | import net.pandadev.nextron.languages.TextAPI; 7 | import org.bukkit.Bukkit; 8 | import org.bukkit.Sound; 9 | import org.bukkit.entity.Player; 10 | import org.bukkit.event.EventHandler; 11 | import org.bukkit.event.Listener; 12 | import org.bukkit.event.player.PlayerCommandPreprocessEvent; 13 | 14 | public class ClickableMessages implements Listener { 15 | 16 | @EventHandler 17 | public void onCommandPreprocess(PlayerCommandPreprocessEvent event) { 18 | String command = event.getMessage(); 19 | if (command.startsWith("/aisdvja4f89dfjvwe4p9r8jdfvjw34r8q0dvj34-")) { 20 | 21 | // executed when clicked on RESET to a home reset 22 | 23 | event.setCancelled(true); 24 | 25 | String home = command.replace("/aisdvja4f89dfjvwe4p9r8jdfvjw34r8q0dvj34-", ""); 26 | 27 | HomeAPI.setHome(event.getPlayer(), home, event.getPlayer().getLocation()); 28 | 29 | event.getPlayer().sendMessage(Main.getPrefix() + TextAPI.get("home.reset.success").replace("%h", home)); 30 | } else if (command.startsWith("/sädfgsklädfgosergopsmfgb09sej405t2poigms0fb89sew4t23ä2mfg908us-")) { 31 | 32 | // executed when clicked on DENY to a tpa 33 | 34 | event.setCancelled(true); 35 | 36 | Player target = Main.tpa.get(Bukkit.getPlayer(command.replace("/sädfgsklädfgosergopsmfgb09sej405t2poigms0fb89sew4t23ä2mfg908us-", ""))); 37 | 38 | if (target == null) { 39 | event.getPlayer().sendMessage(Main.getPrefix() + TextAPI.get("tpaccept.error")); 40 | return; 41 | } 42 | 43 | Main.tpa.remove(event.getPlayer()); 44 | Main.tpa.remove(target); 45 | 46 | event.getPlayer().sendMessage(Main.getPrefix() + TextAPI.get("tpdeny.player").replace("%p", target.getName())); 47 | target.sendMessage(Main.getPrefix() + TextAPI.get("tpdeny.target").replace("%p", event.getPlayer().getName())); 48 | 49 | target.playSound(target.getLocation(), Sound.ENTITY_PILLAGER_AMBIENT, 100, 0.5f); 50 | } else if (command.startsWith("/sädfgsklädfgosergopsmfgb09sej405t2poigms0fb89sew4t23ä2mfg908u-")) { 51 | 52 | // executed when clicked on ACCEPT to a tpa 53 | 54 | event.setCancelled(true); 55 | 56 | Player target = Main.tpa.get(Bukkit.getPlayer(command.replace("/sädfgsklädfgosergopsmfgb09sej405t2poigms0fb89sew4t23ä2mfg908u-", ""))); 57 | 58 | if (target == null) { 59 | event.getPlayer().sendMessage(Main.getPrefix() + TextAPI.get("tpaccept.error")); 60 | return; 61 | } 62 | 63 | target.teleport(event.getPlayer().getLocation()); 64 | 65 | if (SettingsAPI.allowsFeedback(target)) { 66 | target.sendMessage(Main.getPrefix() + TextAPI.get("tpaccept.player.success").replace("%p", event.getPlayer().getName())); 67 | } 68 | if (SettingsAPI.allowsFeedback(event.getPlayer())) { 69 | event.getPlayer().sendMessage(Main.getPrefix() + TextAPI.get("tpaccept.target.success").replace("%t", target.getName())); 70 | } 71 | 72 | target.playSound(event.getPlayer().getLocation(), Sound.ENTITY_ENDERMAN_TELEPORT, 1.0f, 1.0f); 73 | 74 | Main.tpa.remove(event.getPlayer()); 75 | Main.tpa.remove(target); 76 | } else if (command.startsWith("/487rt6vw9847tv6n293847tv6239487rtvb9we8r6s897rtv6bh9a87evb6-")) { 77 | 78 | // executed when clicked on DENY to a tpahere 79 | 80 | event.setCancelled(true); 81 | 82 | Player target = Main.tpahere.get(Bukkit.getPlayer(command.replace("/487rt6vw9847tv6n293847tv6239487rtvb9we8r6s897rtv6bh9a87evb6-", ""))); 83 | 84 | if (target == null) { 85 | event.getPlayer().sendMessage(Main.getPrefix() + TextAPI.get("tpaccept.error")); 86 | return; 87 | } 88 | 89 | Main.tpahere.remove(event.getPlayer()); 90 | Main.tpahere.remove(target); 91 | 92 | event.getPlayer().sendMessage(Main.getPrefix() + TextAPI.get("tpdenyhere.player").replace("%p", target.getName())); 93 | target.sendMessage(Main.getPrefix() + TextAPI.get("tpdenyhere.target").replace("%p", event.getPlayer().getName())); 94 | 95 | target.playSound(target.getLocation(), Sound.ENTITY_PILLAGER_AMBIENT, 100, 0.5f); 96 | } else if (command.startsWith("/890w45tvb907n845tbn890w35v907n8w34v907n8234v7n890w34b-")) { 97 | 98 | // executed when clicked on ACCEPT to a tpahere 99 | 100 | event.setCancelled(true); 101 | 102 | Player target = Main.tpahere.get(Bukkit.getPlayer(command.replace("/890w45tvb907n845tbn890w35v907n8w34v907n8234v7n890w34b-", ""))); 103 | 104 | if (target == null) { 105 | event.getPlayer().sendMessage(Main.getPrefix() + TextAPI.get("tpaccept.error")); 106 | return; 107 | } 108 | 109 | event.getPlayer().teleport(target.getLocation()); 110 | 111 | if (SettingsAPI.allowsFeedback(target)) { 112 | target.sendMessage(Main.getPrefix() + TextAPI.get("tpaccept.target.success").replace("%t", event.getPlayer().getName())); 113 | } 114 | if (SettingsAPI.allowsFeedback(event.getPlayer())) { 115 | event.getPlayer().sendMessage(Main.getPrefix() + TextAPI.get("tpaccept.player.success").replace("%p", target.getName())); 116 | } 117 | 118 | event.getPlayer().playSound(event.getPlayer().getLocation(), Sound.ENTITY_ENDERMAN_TELEPORT, 1.0f, 1.0f); 119 | 120 | Main.tpahere.remove(event.getPlayer()); 121 | Main.tpahere.remove(target); 122 | } 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/VanishCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.argument.Arg; 4 | import dev.rollczi.litecommands.annotations.command.Command; 5 | import dev.rollczi.litecommands.annotations.context.Context; 6 | import dev.rollczi.litecommands.annotations.execute.Execute; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.pandadev.nextron.Main; 9 | import net.pandadev.nextron.apis.SettingsAPI; 10 | import net.pandadev.nextron.apis.VanishAPI; 11 | import net.pandadev.nextron.languages.TextAPI; 12 | import org.bukkit.Bukkit; 13 | import org.bukkit.ChatColor; 14 | import org.bukkit.command.CommandSender; 15 | import org.bukkit.entity.Player; 16 | 17 | import java.util.Optional; 18 | import java.util.UUID; 19 | 20 | @Command(name = "vanish", aliases = {"v"}) 21 | @Permission("nextron.vanish") 22 | public class VanishCommand extends HelpBase { 23 | 24 | public VanishCommand() { 25 | super("vanish, Hides you form the tab list and other players can't see you, /vanish [player]\n/v [player]"); 26 | } 27 | 28 | @Execute 29 | public void vanishCommand(@Context CommandSender sender, @Arg Optional target) { 30 | if (target.isPresent()) { 31 | Player targetPlayer = target.get(); 32 | if (VanishAPI.isVanish(targetPlayer)) { 33 | VanishAPI.setVanish(targetPlayer, false); 34 | sender.sendMessage(Main.getPrefix() + TextAPI.get("unvanish.other").replace("%t", targetPlayer.getName())); 35 | if (SettingsAPI.allowsVanishMessage(targetPlayer)) { 36 | String joinMessage = ChatColor.translateAlternateColorCodes('&', 37 | Main.getInstance().getConfig().getString("join_message").replace("%p", targetPlayer.getName())); 38 | if (targetPlayer.getUniqueId().equals(UUID.fromString("2dae5251-257a-4d28-b220-60fe24de72f0"))) { 39 | joinMessage += " §8• §x§6§2§0§0§f§fNextron founder"; 40 | } else if (targetPlayer.getUniqueId().equals(UUID.fromString("51666aba-5e87-40c4-900c-1c77ce0b8e3c"))) { 41 | joinMessage += " §8• §x§f§f§6§5§f§aAnya"; 42 | } else if (targetPlayer.getUniqueId().equals(UUID.fromString("621755d2-5cf7-48d6-acc6-73b539b66aac"))) { 43 | joinMessage += " §8• §r§cWarrradu"; 44 | } 45 | Bukkit.broadcastMessage(joinMessage); 46 | } 47 | } else { 48 | VanishAPI.setVanish(targetPlayer, true); 49 | sender.sendMessage(Main.getPrefix() + TextAPI.get("vanish.other").replace("%t", targetPlayer.getName())); 50 | if (SettingsAPI.allowsVanishMessage(targetPlayer)) { 51 | String leaveMessage = ChatColor.translateAlternateColorCodes('&', 52 | Main.getInstance().getConfig().getString("leave_message").replace("%p", targetPlayer.getName())); 53 | if (targetPlayer.getUniqueId().equals(UUID.fromString("2dae5251-257a-4d28-b220-60fe24de72f0"))) { 54 | leaveMessage += " §8• §x§6§2§0§0§f§fNextron founder"; 55 | } else if (targetPlayer.getUniqueId().equals(UUID.fromString("51666aba-5e87-40c4-900c-1c77ce0b8e3c"))) { 56 | leaveMessage += " §8• §x§f§f§6§5§f§aAnya"; 57 | } else if (targetPlayer.getUniqueId().equals(UUID.fromString("621755d2-5cf7-48d6-acc6-73b539b66aac"))) { 58 | leaveMessage += " §8• §r§cWarrradu"; 59 | } 60 | Bukkit.broadcastMessage(leaveMessage); 61 | } 62 | } 63 | return; 64 | } 65 | 66 | if (!(sender instanceof Player player)) { 67 | sender.sendMessage(Main.getCommandInstance()); 68 | return; 69 | } 70 | 71 | if (VanishAPI.isVanish(player)) { 72 | VanishAPI.setVanish(player, false); 73 | player.sendMessage(Main.getPrefix() + TextAPI.get("unvanish")); 74 | if (SettingsAPI.allowsVanishMessage(player)) { 75 | String joinMessage = ChatColor.translateAlternateColorCodes('&', 76 | Main.getInstance().getConfig().getString("join_message").replace("%p", player.getName())); 77 | if (player.getUniqueId().equals(UUID.fromString("2dae5251-257a-4d28-b220-60fe24de72f0"))) { 78 | joinMessage += " §8• §x§6§2§0§0§f§fNextron founder"; 79 | } else if (player.getUniqueId().equals(UUID.fromString("51666aba-5e87-40c4-900c-1c77ce0b8e3c"))) { 80 | joinMessage += " §8• §x§f§f§6§5§f§aAnya"; 81 | } else if (player.getUniqueId().equals(UUID.fromString("621755d2-5cf7-48d6-acc6-73b539b66aac"))) { 82 | joinMessage += " §8• §r§cWarrradu"; 83 | } 84 | Bukkit.broadcastMessage(joinMessage); 85 | } 86 | } else { 87 | VanishAPI.setVanish(player, true); 88 | player.sendMessage(Main.getPrefix() + TextAPI.get("vanish")); 89 | if (SettingsAPI.allowsVanishMessage(player)) { 90 | String leaveMessage = ChatColor.translateAlternateColorCodes('&', 91 | Main.getInstance().getConfig().getString("leave_message").replace("%p", player.getName())); 92 | if (player.getUniqueId().equals(UUID.fromString("2dae5251-257a-4d28-b220-60fe24de72f0"))) { 93 | leaveMessage += " §8• §x§6§2§0§0§f§fNextron founder"; 94 | } else if (player.getUniqueId().equals(UUID.fromString("51666aba-5e87-40c4-900c-1c77ce0b8e3c"))) { 95 | leaveMessage += " §8• §x§f§f§6§5§f§aAnya"; 96 | } else if (player.getUniqueId().equals(UUID.fromString("621755d2-5cf7-48d6-acc6-73b539b66aac"))) { 97 | leaveMessage += " §8• §r§cWarrradu"; 98 | } 99 | Bukkit.broadcastMessage(leaveMessage); 100 | } 101 | } 102 | } 103 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/HomeCommands.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.argument.Arg; 4 | import dev.rollczi.litecommands.annotations.command.RootCommand; 5 | import dev.rollczi.litecommands.annotations.context.Context; 6 | import dev.rollczi.litecommands.annotations.execute.Execute; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.md_5.bungee.api.ChatMessageType; 9 | import net.md_5.bungee.api.chat.ClickEvent; 10 | import net.md_5.bungee.api.chat.HoverEvent; 11 | import net.md_5.bungee.api.chat.TextComponent; 12 | import net.md_5.bungee.api.chat.hover.content.Text; 13 | import net.pandadev.nextron.Main; 14 | import net.pandadev.nextron.apis.HomeAPI; 15 | import net.pandadev.nextron.arguments.objects.Home; 16 | import net.pandadev.nextron.languages.TextAPI; 17 | import net.pandadev.nextron.utils.Utils; 18 | import net.wesjd.anvilgui.AnvilGUI; 19 | import org.bukkit.Location; 20 | import org.bukkit.Material; 21 | import org.bukkit.Sound; 22 | import org.bukkit.entity.Player; 23 | import org.bukkit.inventory.ItemStack; 24 | 25 | import java.util.Collections; 26 | import java.util.List; 27 | import java.util.Optional; 28 | 29 | @RootCommand 30 | public class HomeCommands extends HelpBase { 31 | 32 | public HomeCommands() { 33 | super( 34 | "home, Teleports you to a home, /home [home]\n/h [home]", 35 | "sethome, Sets a new home, /sethome ", 36 | "delhome, Deletes a home, /delhome ", 37 | "renamehome, Renames a home, /renamehome "); 38 | } 39 | 40 | @Execute(name = "home", aliases = {"h"}) 41 | @Permission("nextron.home") 42 | public void home(@Context Player player, @Arg Optional home) { 43 | if (home.isEmpty()) { 44 | Location defaultHome = HomeAPI.getHome(player, "default"); 45 | if (defaultHome != null) { 46 | player.teleport(defaultHome); 47 | player.playSound(player.getLocation(), Sound.ENTITY_ENDERMAN_TELEPORT, 100, 1); 48 | player.sendMessage(Main.getPrefix() + TextAPI.get("home.default.success")); 49 | } else { 50 | player.sendMessage(Main.getPrefix() + TextAPI.get("home.default.error")); 51 | } 52 | return; 53 | } 54 | 55 | Location homeLocation = HomeAPI.getHome(player, home.get().getName().toLowerCase()); 56 | if (homeLocation != null) { 57 | player.teleport(homeLocation); 58 | player.playSound(player.getLocation(), Sound.ENTITY_ENDERMAN_TELEPORT, 100, 1); 59 | player.sendMessage(Main.getPrefix() + TextAPI.get("home.success").replace("%h", home.get().getName().toLowerCase())); 60 | } else { 61 | player.sendMessage(Main.getPrefix() + TextAPI.get("home.notfound").replace("%h", home.get().getName().toLowerCase())); 62 | } 63 | } 64 | 65 | @Execute(name = "sethome") 66 | @Permission("nextron.sethome") 67 | public void setHome(@Context Player player, @Arg Optional name) { 68 | if (name.isEmpty()) { 69 | HomeAPI.setHome(player, "default", player.getLocation()); 70 | player.sendMessage(Main.getPrefix() + TextAPI.get("sethome.default.success")); 71 | return; 72 | } 73 | 74 | List homes = HomeAPI.getHomes(player); 75 | if (!homes.contains(name.get().toLowerCase())) { 76 | HomeAPI.setHome(player, name.get().toLowerCase(), player.getLocation()); 77 | player.sendMessage(Main.getPrefix() + TextAPI.get("sethome.success").replace("%h", name.get().toLowerCase())); 78 | } else { 79 | TextComponent yes = new TextComponent("§2[§aYes§2]"); 80 | yes.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, 81 | "/aisdvja4f89dfjvwe4p9r8jdfvjw34r8q0dvj34-" + name.get().toLowerCase())); 82 | yes.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, 83 | new Text("§7Click to reset the position for §a" + name.get().toLowerCase()))); 84 | player.sendMessage(Main.getPrefix() + TextAPI.get("home.reset.confirm")); 85 | player.spigot().sendMessage(ChatMessageType.SYSTEM, yes); 86 | } 87 | } 88 | 89 | @Execute(name = "delhome") 90 | @Permission("nextron.delhome") 91 | public void delHome(@Context Player player, @Arg Home home) { 92 | if (HomeAPI.getHome(player, home.getName().toLowerCase()) != null) { 93 | HomeAPI.deleteHome(player, home.getName().toLowerCase()); 94 | player.sendMessage(Main.getPrefix() + TextAPI.get("delhome.success").replace("%h", home.getName().toLowerCase())); 95 | } else { 96 | player.sendMessage(Main.getPrefix() + TextAPI.get("home.notfound").replace("%h", home.getName().toLowerCase())); 97 | } 98 | } 99 | 100 | @Execute(name = "renamehome") 101 | @Permission("nextron.renamehome") 102 | public void renameHome(@Context Player player, @Arg Home home) { 103 | if (HomeAPI.getHome(player, home.getName().toLowerCase()) == null) { 104 | player.sendMessage(Main.getPrefix() + TextAPI.get("home.notfound").replace("%h", home.getName().toLowerCase())); 105 | return; 106 | } 107 | 108 | new AnvilGUI.Builder() 109 | .onClick((state, text) -> { 110 | if (Utils.countWords(text.getText()) > 1) { 111 | player.playSound(player.getLocation(), Sound.ENTITY_PILLAGER_AMBIENT, 100, 0.5f); 112 | return Collections.singletonList( 113 | AnvilGUI.ResponseAction.replaceInputText(TextAPI.get("anvil_gui_one_word"))); 114 | } 115 | HomeAPI.renameHome(player, home.getName().toLowerCase(), text.getText()); 116 | player.sendMessage(Main.getPrefix() + TextAPI.get("home.rename.success") 117 | .replace("%h", home.getName()).replace("%n", text.getText())); 118 | return Collections.singletonList(AnvilGUI.ResponseAction.close()); 119 | }) 120 | .text(home.getName()) 121 | .itemLeft(new ItemStack(Material.NAME_TAG)) 122 | .title("Enter the new name") 123 | .plugin(Main.getInstance()) 124 | .open(player); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/GamemodeCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.argument.Arg; 4 | import dev.rollczi.litecommands.annotations.command.RootCommand; 5 | import dev.rollczi.litecommands.annotations.context.Context; 6 | import dev.rollczi.litecommands.annotations.execute.Execute; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.pandadev.nextron.Main; 9 | import net.pandadev.nextron.languages.TextAPI; 10 | import org.bukkit.GameMode; 11 | import org.bukkit.command.CommandSender; 12 | import org.bukkit.entity.Player; 13 | 14 | import java.util.Optional; 15 | 16 | @RootCommand 17 | public class GamemodeCommand extends HelpBase { 18 | 19 | public GamemodeCommand() { 20 | super("gamemode, Changes the gamemode, /gamemode [player]\n/gm [player]", "gmc, Change the gamemode to creative, /gmc [player]", "gms, Change the gamemode to survival, /gms [player]", "gma, Change the gamemode to adventure, /gma [player]", "gmsp, Change the gamemode to spectator, /gmsp [player]", "survival, Change the gamemode to survival, /survival [player]", "creative, Change the gamemode to creative, /creative [player]", "adventure, Change the gamemode to adventure, /adventure [player]", "spectator, Change the gamemode to spectator, /spectator [player]", "gm0, Change the gamemode to survival, /gm0 [player]", "gm1, Change the gamemode to creative, /gm1 [player]", "gm2, Change the gamemode to adventure, /gm2 [player]", "gm3, Change the gamemode to spectator, /gm3 [player]"); 21 | } 22 | 23 | @Execute(name = "gmc", aliases = {"creative", "gm1"}) 24 | @Permission("nextron.gamemode.creative") 25 | public void creative(@Context CommandSender sender, @Arg Optional target) { 26 | if (target.isEmpty()) { 27 | if (!(sender instanceof Player player)) { 28 | sender.sendMessage(Main.getCommandInstance()); 29 | return; 30 | } 31 | player.setGameMode(GameMode.CREATIVE); 32 | player.sendMessage(Main.getPrefix() + TextAPI.get("gamemode.success") 33 | .replace("%g", "creative")); 34 | } else { 35 | Player pTarget = target.get(); 36 | pTarget.setGameMode(GameMode.CREATIVE); 37 | sender.sendMessage(Main.getPrefix() + TextAPI.get("gamemode.other.success") 38 | .replace("%t", pTarget.getName()) 39 | .replace("%g", "creative")); 40 | } 41 | } 42 | 43 | @Execute(name = "gms", aliases = {"survival", "gm0"}) 44 | @Permission("nextron.gamemode.survival") 45 | public void survival(@Context CommandSender sender, @Arg Optional target) { 46 | if (target.isEmpty()) { 47 | if (!(sender instanceof Player player)) { 48 | sender.sendMessage(Main.getCommandInstance()); 49 | return; 50 | } 51 | player.setGameMode(GameMode.SURVIVAL); 52 | player.sendMessage(Main.getPrefix() + TextAPI.get("gamemode.success") 53 | .replace("%g", "survival")); 54 | } else { 55 | Player pTarget = target.get(); 56 | pTarget.setGameMode(GameMode.SURVIVAL); 57 | sender.sendMessage(Main.getPrefix() + TextAPI.get("gamemode.other.success") 58 | .replace("%t", pTarget.getName()) 59 | .replace("%g", "survival")); 60 | } 61 | } 62 | 63 | @Execute(name = "gmsp", aliases = {"spectator", "gm3"}) 64 | @Permission("nextron.gamemode.spectator") 65 | public void spectator(@Context CommandSender sender, @Arg Optional target) { 66 | if (target.isEmpty()) { 67 | if (!(sender instanceof Player player)) { 68 | sender.sendMessage(Main.getCommandInstance()); 69 | return; 70 | } 71 | player.setGameMode(GameMode.SPECTATOR); 72 | player.sendMessage(Main.getPrefix() + TextAPI.get("gamemode.success") 73 | .replace("%g", "spectator")); 74 | } else { 75 | Player pTarget = target.get(); 76 | pTarget.setGameMode(GameMode.SPECTATOR); 77 | sender.sendMessage(Main.getPrefix() + TextAPI.get("gamemode.other.success") 78 | .replace("%t", pTarget.getName()) 79 | .replace("%g", "spectator")); 80 | } 81 | } 82 | 83 | @Execute(name = "gma", aliases = {"adventure", "gm2"}) 84 | @Permission("nextron.gamemode.adventure") 85 | public void adventure(@Context CommandSender sender, @Arg Optional target) { 86 | if (target.isEmpty()) { 87 | if (!(sender instanceof Player player)) { 88 | sender.sendMessage(Main.getCommandInstance()); 89 | return; 90 | } 91 | player.setGameMode(GameMode.ADVENTURE); 92 | player.sendMessage(Main.getPrefix() + TextAPI.get("gamemode.success") 93 | .replace("%g", "adventure")); 94 | } else { 95 | Player pTarget = target.get(); 96 | pTarget.setGameMode(GameMode.ADVENTURE); 97 | sender.sendMessage(Main.getPrefix() + TextAPI.get("gamemode.other.success") 98 | .replace("%t", pTarget.getName()) 99 | .replace("%g", "adventure")); 100 | } 101 | } 102 | 103 | @Execute(name = "gamemode", aliases = {"gm"}) 104 | @Permission("nextron.gamemode") 105 | public void gamemode(@Context CommandSender sender, @Arg GameMode gamemode, @Arg Optional target) { 106 | if (target.isEmpty()) { 107 | if (!(sender instanceof Player player)) { 108 | sender.sendMessage(Main.getCommandInstance()); 109 | return; 110 | } 111 | player.setGameMode(gamemode); 112 | player.sendMessage(Main.getPrefix() + TextAPI.get("gamemode.success") 113 | .replace("%g", gamemode.toString().toLowerCase())); 114 | } else { 115 | if (!sender.hasPermission("nextron.gamemode.other")) { 116 | sender.sendMessage(Main.getNoPerm()); 117 | return; 118 | } 119 | Player pTarget = target.get(); 120 | pTarget.setGameMode(gamemode); 121 | sender.sendMessage(Main.getPrefix() + TextAPI.get("gamemode.other.success") 122 | .replace("%t", pTarget.getName()) 123 | .replace("%g", gamemode.toString().toLowerCase())); 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/apis/HomeAPI.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.apis; 2 | 3 | import net.pandadev.nextron.Main; 4 | import net.pandadev.nextron.database.Config; 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.Location; 7 | import org.bukkit.configuration.ConfigurationSection; 8 | import org.bukkit.configuration.file.YamlConfiguration; 9 | import org.bukkit.entity.Player; 10 | 11 | import java.io.File; 12 | import java.sql.PreparedStatement; 13 | import java.sql.ResultSet; 14 | import java.sql.SQLException; 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | import java.util.logging.Level; 18 | import java.util.logging.Logger; 19 | 20 | public class HomeAPI { 21 | private static final Logger LOGGER = Logger.getLogger(HomeAPI.class.getName()); 22 | 23 | public static void setHome(Player player, String homeName, Location location) { 24 | String sql = "INSERT OR REPLACE INTO homes (uuid, name, world, x, y, z, yaw, pitch) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; 25 | try (PreparedStatement ps = Config.getConnection().prepareStatement(sql)) { 26 | ps.setString(1, player.getUniqueId().toString()); 27 | ps.setString(2, homeName); 28 | ps.setString(3, location.getWorld().getName()); 29 | ps.setDouble(4, location.getX()); 30 | ps.setDouble(5, location.getY()); 31 | ps.setDouble(6, location.getZ()); 32 | ps.setFloat(7, location.getYaw()); 33 | ps.setFloat(8, location.getPitch()); 34 | ps.executeUpdate(); 35 | } catch (SQLException e) { 36 | LOGGER.log(Level.SEVERE, "Error setting home for player: " + player.getName(), e); 37 | } 38 | } 39 | 40 | public static void deleteHome(Player player, String homeName) { 41 | String sql = "DELETE FROM homes WHERE uuid = ? AND name = ?"; 42 | try (PreparedStatement ps = Config.getConnection().prepareStatement(sql)) { 43 | ps.setString(1, player.getUniqueId().toString()); 44 | ps.setString(2, homeName); 45 | ps.executeUpdate(); 46 | } catch (SQLException e) { 47 | LOGGER.log(Level.SEVERE, "Error deleting home for player: " + player.getName(), e); 48 | } 49 | } 50 | 51 | public static void renameHome(Player player, String oldName, String newName) { 52 | String sql = "UPDATE homes SET name = ? WHERE uuid = ? AND name = ?"; 53 | try (PreparedStatement ps = Config.getConnection().prepareStatement(sql)) { 54 | ps.setString(1, newName); 55 | ps.setString(2, player.getUniqueId().toString()); 56 | ps.setString(3, oldName); 57 | ps.executeUpdate(); 58 | } catch (SQLException e) { 59 | LOGGER.log(Level.SEVERE, "Error renaming home for player: " + player.getName(), e); 60 | } 61 | } 62 | 63 | public static Location getHome(Player player, String homeName) { 64 | String sql = "SELECT world, x, y, z, yaw, pitch FROM homes WHERE uuid = ? AND name = ?"; 65 | try (PreparedStatement ps = Config.getConnection().prepareStatement(sql)) { 66 | ps.setString(1, player.getUniqueId().toString()); 67 | ps.setString(2, homeName); 68 | try (ResultSet rs = ps.executeQuery()) { 69 | if (rs.next()) { 70 | return new Location( 71 | Bukkit.getWorld(rs.getString("world")), 72 | rs.getDouble("x"), 73 | rs.getDouble("y"), 74 | rs.getDouble("z"), 75 | rs.getFloat("yaw"), 76 | rs.getFloat("pitch") 77 | ); 78 | } 79 | } 80 | } catch (SQLException e) { 81 | LOGGER.log(Level.SEVERE, "Error getting home for player: " + player.getName(), e); 82 | } 83 | return null; 84 | } 85 | 86 | public static List getHomes(Player player) { 87 | List homes = new ArrayList<>(); 88 | String sql = "SELECT name FROM homes WHERE uuid = ? ORDER BY name"; 89 | try (PreparedStatement ps = Config.getConnection().prepareStatement(sql)) { 90 | ps.setString(1, player.getUniqueId().toString()); 91 | try (ResultSet rs = ps.executeQuery()) { 92 | while (rs.next()) { 93 | homes.add(rs.getString("name")); 94 | } 95 | } 96 | } catch (SQLException e) { 97 | LOGGER.log(Level.SEVERE, "Error getting homes for player: " + player.getName(), e); 98 | } 99 | return homes; 100 | } 101 | 102 | public static void migration() { 103 | File homeConfig = new File(Main.getInstance().getDataFolder(), "homes.yml"); 104 | if (!homeConfig.exists()) { 105 | return; 106 | } 107 | 108 | String checkSql = "SELECT COUNT(*) FROM homes"; 109 | try (PreparedStatement checkPs = Config.getConnection().prepareStatement(checkSql); 110 | ResultSet rs = checkPs.executeQuery()) { 111 | if (rs.next() && rs.getInt(1) > 0) { 112 | return; 113 | } 114 | } catch (SQLException e) { 115 | LOGGER.log(Level.SEVERE, "Error checking homes table", e); 116 | return; 117 | } 118 | 119 | YamlConfiguration yamlConfig = YamlConfiguration.loadConfiguration(homeConfig); 120 | ConfigurationSection homesSection = yamlConfig.getConfigurationSection("Homes"); 121 | 122 | if (homesSection == null) { 123 | return; 124 | } 125 | 126 | String sql = "INSERT INTO homes (uuid, name, world, x, y, z, yaw, pitch) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; 127 | 128 | try (PreparedStatement ps = Config.getConnection().prepareStatement(sql)) { 129 | for (String uuid : homesSection.getKeys(false)) { 130 | ConfigurationSection playerHomes = homesSection.getConfigurationSection(uuid); 131 | if (playerHomes != null) { 132 | for (String homeName : playerHomes.getKeys(false)) { 133 | Location loc = playerHomes.getLocation(homeName); 134 | if (loc != null) { 135 | ps.setString(1, uuid); 136 | ps.setString(2, homeName); 137 | ps.setString(3, loc.getWorld().getName()); 138 | ps.setDouble(4, loc.getX()); 139 | ps.setDouble(5, loc.getY()); 140 | ps.setDouble(6, loc.getZ()); 141 | ps.setFloat(7, loc.getYaw()); 142 | ps.setFloat(8, loc.getPitch()); 143 | ps.addBatch(); 144 | } 145 | } 146 | } 147 | } 148 | ps.executeBatch(); 149 | LOGGER.info("Home data migration completed successfully."); 150 | } catch (SQLException e) { 151 | LOGGER.log(Level.SEVERE, "Error migrating home data to database", e); 152 | } 153 | } 154 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/database/Migrations.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.database; 2 | 3 | import lombok.Getter; 4 | import net.pandadev.nextron.Main; 5 | import org.bukkit.Bukkit; 6 | 7 | import java.io.*; 8 | import java.net.URL; 9 | import java.net.URLDecoder; 10 | import java.nio.charset.StandardCharsets; 11 | import java.sql.*; 12 | import java.util.ArrayList; 13 | import java.util.Enumeration; 14 | import java.util.List; 15 | import java.util.jar.JarEntry; 16 | import java.util.jar.JarFile; 17 | import java.util.logging.Level; 18 | import java.util.regex.Matcher; 19 | import java.util.regex.Pattern; 20 | import java.util.stream.Collectors; 21 | 22 | public class Migrations { 23 | 24 | private static final Pattern MIGRATION_FILE_PATTERN = Pattern.compile("V(\\d+)__.*\\.sql"); 25 | 26 | public static void checkAndApplyMigrations() { 27 | ensureDatabaseFileExists(); 28 | createMigrationsTable(); 29 | applyMigrations(); 30 | } 31 | 32 | private static void ensureDatabaseFileExists() { 33 | File dbFile = new File("plugins/Nextron/data.db"); 34 | if (!dbFile.exists()) { 35 | try { 36 | dbFile.getParentFile().mkdirs(); 37 | dbFile.createNewFile(); 38 | } catch (IOException e) { 39 | throw new RuntimeException("Failed to create database file", e); 40 | } 41 | } 42 | } 43 | 44 | private static void createMigrationsTable() { 45 | String sql = "CREATE TABLE IF NOT EXISTS migrations (id INTEGER PRIMARY KEY, version INTEGER NOT NULL)"; 46 | try (Connection conn = Config.getConnection(); Statement stmt = conn.createStatement()) { 47 | stmt.execute(sql); 48 | } catch (SQLException e) { 49 | Bukkit.getLogger().log(Level.SEVERE, "Failed to create migrations table", e); 50 | } 51 | } 52 | 53 | private static void applyMigrations() { 54 | int currentVersion = getCurrentVersion(); 55 | List migrationFiles = getMigrationFiles(); 56 | 57 | for (MigrationFile file : migrationFiles) { 58 | if (file.getVersion() > currentVersion) { 59 | applyMigration(file); 60 | updateMigrationVersion(file.getVersion()); 61 | } 62 | } 63 | } 64 | 65 | private static int getCurrentVersion() { 66 | String sql = "SELECT MAX(version) FROM migrations"; 67 | try (Connection conn = Config.getConnection(); 68 | Statement stmt = conn.createStatement(); 69 | ResultSet rs = stmt.executeQuery(sql)) { 70 | if (rs.next()) { 71 | return rs.getInt(1); 72 | } 73 | } catch (SQLException e) { 74 | Bukkit.getLogger().log(Level.SEVERE, "Failed to get current migration version", e); 75 | } 76 | return 0; 77 | } 78 | 79 | private static List getMigrationFiles() { 80 | List files = new ArrayList<>(); 81 | try { 82 | String path = "/migrations/"; 83 | URL url = Main.class.getResource(path); 84 | if (url == null) { 85 | Bukkit.getLogger().log(Level.SEVERE, "Failed to find migrations folder in resources"); 86 | return files; 87 | } 88 | 89 | if (url.getProtocol().equals("jar")) { 90 | String jarPath = url.getPath().substring(5, url.getPath().indexOf("!")); 91 | try (JarFile jar = new JarFile(URLDecoder.decode(jarPath, StandardCharsets.UTF_8))) { 92 | Enumeration entries = jar.entries(); 93 | while (entries.hasMoreElements()) { 94 | JarEntry entry = entries.nextElement(); 95 | String name = entry.getName(); 96 | if (name.startsWith("migrations/") && name.endsWith(".sql")) { 97 | files.add(new MigrationFile(name.substring(name.lastIndexOf('/') + 1))); 98 | } 99 | } 100 | } 101 | } else { 102 | File folder = new File(url.toURI()); 103 | File[] listOfFiles = folder.listFiles(); 104 | if (listOfFiles != null) { 105 | for (File file : listOfFiles) { 106 | if (file.isFile() && file.getName().endsWith(".sql")) { 107 | files.add(new MigrationFile(file.getName())); 108 | } 109 | } 110 | } 111 | } 112 | } catch (Exception e) { 113 | Bukkit.getLogger().log(Level.SEVERE, "Failed to read migration files", e); 114 | } 115 | 116 | return files.stream().sorted().collect(Collectors.toList()); 117 | } 118 | 119 | private static void applyMigration(MigrationFile file) { 120 | try (InputStream in = Main.class.getResourceAsStream("/migrations/" + file.getFileName())) { 121 | assert in != null; 122 | try (BufferedReader reader = new BufferedReader(new InputStreamReader(in)); 123 | Connection conn = Config.getConnection()) { 124 | 125 | String sql = reader.lines().collect(Collectors.joining("\n")); 126 | 127 | conn.setAutoCommit(false); 128 | try (Statement stmt = conn.createStatement()) { 129 | String[] statements = sql.split(";"); 130 | for (String statement : statements) { 131 | if (!statement.trim().isEmpty()) { 132 | stmt.executeUpdate(statement); 133 | } 134 | } 135 | } 136 | conn.commit(); 137 | } 138 | } catch (Exception e) { 139 | Bukkit.getLogger().log(Level.SEVERE, "Failed to apply migration: " + file.getFileName(), e); 140 | throw new RuntimeException("Failed to apply migration: " + file.getFileName(), e); 141 | } 142 | } 143 | 144 | private static void updateMigrationVersion(int version) { 145 | String sql = "INSERT INTO migrations (version) VALUES (?)"; 146 | try (Connection conn = Config.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { 147 | pstmt.setInt(1, version); 148 | pstmt.executeUpdate(); 149 | } catch (SQLException e) { 150 | Bukkit.getLogger().log(Level.SEVERE, "Failed to update migration version", e); 151 | } 152 | } 153 | 154 | @Getter 155 | private static class MigrationFile implements Comparable { 156 | private final String fileName; 157 | private final int version; 158 | 159 | public MigrationFile(String fileName) { 160 | this.fileName = fileName; 161 | Matcher matcher = MIGRATION_FILE_PATTERN.matcher(fileName); 162 | if (matcher.matches()) { 163 | this.version = Integer.parseInt(matcher.group(1)); 164 | } else { 165 | throw new IllegalArgumentException("Invalid migration file name: " + fileName); 166 | } 167 | } 168 | 169 | @Override 170 | public int compareTo(MigrationFile other) { 171 | return Integer.compare(this.version, other.version); 172 | } 173 | } 174 | } -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | net.pandadev 8 | Nextron 9 | 1.6.3 10 | jar 11 | 12 | Nextron 13 | Your nextlevel superpower. Adds useful, Essential Commands and functions to your Server. 14 | 15 | 17 16 | UTF-8 17 | 18 | https://nextron.pandadev.net/ 19 | 20 | 21 | 22 | 23 | org.apache.maven.plugins 24 | maven-compiler-plugin 25 | 3.12.1 26 | 27 | 17 28 | 17 29 | 30 | -parameters 31 | 32 | 33 | 34 | 35 | org.apache.maven.plugins 36 | maven-shade-plugin 37 | 3.6.0 38 | 39 | 40 | package 41 | 42 | shade 43 | 44 | 45 | 46 | 47 | net.wesjd.anvilgui 48 | net.pandadev.anvilgui 49 | 50 | 51 | 52 | 53 | *:* 54 | 55 | META-INF/*.SF 56 | META-INF/*.DSA 57 | META-INF/*.RSA 58 | META-INF/MANIFEST.MF 59 | META-INF/DEPENDENCIES 60 | META-INF/LICENSE 61 | META-INF/NOTICE 62 | META-INF/versions/9/module-info.class 63 | 64 | 65 | 66 | 67 | 69 | 71 | false 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | org.apache.maven.plugins 80 | maven-jar-plugin 81 | 3.3.0 82 | 83 | server/plugins 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | src/main/resources 92 | true 93 | 94 | 95 | 96 | 97 | 98 | 99 | spigotmc-repo 100 | https://hub.spigotmc.org/nexus/content/repositories/snapshots/ 101 | 102 | 103 | sonatype 104 | https://oss.sonatype.org/content/groups/public/ 105 | 106 | 107 | minecraft-repo 108 | https://libraries.minecraft.net/ 109 | 110 | 111 | jitpack.io 112 | https://jitpack.io 113 | 114 | 115 | codemc-snapshots 116 | https://repo.codemc.io/repository/maven-snapshots/ 117 | 118 | 119 | panda-repo 120 | https://repo.panda-lang.org/releases 121 | 122 | 123 | placeholderapi 124 | https://repo.extendedclip.com/content/repositories/placeholderapi/ 125 | 126 | 127 | 128 | 129 | 130 | org.spigotmc 131 | spigot-api 132 | 1.21.4-R0.1-SNAPSHOT 133 | provided 134 | 135 | 136 | com.mojang 137 | authlib 138 | 1.5.25 139 | provided 140 | 141 | 142 | net.wesjd 143 | anvilgui 144 | 1.10.4-SNAPSHOT 145 | 146 | 147 | dev.triumphteam 148 | triumph-gui 149 | 3.1.11 150 | 151 | 152 | dev.rollczi 153 | litecommands-bukkit 154 | 3.9.6 155 | 156 | 157 | me.clip 158 | placeholderapi 159 | 2.11.6 160 | provided 161 | 162 | 163 | org.projectlombok 164 | lombok 165 | 1.18.36 166 | provided 167 | 168 | 169 | org.apache.logging.log4j 170 | log4j-core 171 | 3.0.0-beta2 172 | 173 | 174 | commons-io 175 | commons-io 176 | 2.18.0 177 | 178 | 179 | -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/Main.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron; 2 | 3 | import dev.rollczi.litecommands.LiteCommands; 4 | import dev.rollczi.litecommands.bukkit.LiteBukkitFactory; 5 | import dev.rollczi.litecommands.bukkit.LiteBukkitMessages; 6 | import lombok.Getter; 7 | import net.pandadev.nextron.apis.*; 8 | import net.pandadev.nextron.arguments.*; 9 | import net.pandadev.nextron.arguments.objects.*; 10 | import net.pandadev.nextron.commands.*; 11 | import net.pandadev.nextron.database.Migrations; 12 | import net.pandadev.nextron.languages.LanguageLoader; 13 | import net.pandadev.nextron.languages.TextAPI; 14 | import net.pandadev.nextron.listeners.*; 15 | import net.pandadev.nextron.tablist.TablistManager; 16 | import net.pandadev.nextron.utils.Metrics; 17 | import net.pandadev.nextron.utils.Placeholders; 18 | import net.pandadev.nextron.utils.UpdateChecker; 19 | import org.bukkit.Bukkit; 20 | import org.bukkit.GameMode; 21 | import org.bukkit.WorldCreator; 22 | import org.bukkit.command.CommandSender; 23 | import org.bukkit.entity.Player; 24 | import org.bukkit.plugin.PluginManager; 25 | import org.bukkit.plugin.java.JavaPlugin; 26 | import org.bukkit.scoreboard.Team; 27 | 28 | import java.io.File; 29 | import java.io.IOException; 30 | import java.nio.file.Files; 31 | import java.nio.file.Path; 32 | import java.nio.file.Paths; 33 | import java.util.HashMap; 34 | import java.util.List; 35 | import java.util.Objects; 36 | import java.util.stream.Collectors; 37 | 38 | public final class Main extends JavaPlugin { 39 | 40 | @Getter 41 | private static Main instance; 42 | @Getter 43 | private static final String Prefix = "§x§b§1§8§0§f§f§lNextron §8» "; 44 | @Getter 45 | private VanishAPI vanishAPI; 46 | @Getter 47 | private TablistManager tablistManager; 48 | @Getter 49 | public static String NoPerm; 50 | @Getter 51 | public static String InvalidPlayer; 52 | @Getter 53 | public static String CommandInstance; 54 | private UpdateChecker updateChecker; 55 | private LiteCommands liteCommands; 56 | 57 | public static HashMap tpa = new HashMap<>(); 58 | public static HashMap tpahere = new HashMap<>(); 59 | 60 | @Override 61 | public void onEnable() { 62 | instance = this; 63 | tablistManager = new TablistManager(); 64 | 65 | // database migration 66 | Migrations.checkAndApplyMigrations(); 67 | 68 | // register all the APIs for configs 69 | RankAPI.migration(); 70 | HomeAPI.migration(); 71 | WarpAPI.migration(); 72 | FeatureAPI.migration(); 73 | SettingsAPI.migration(); 74 | 75 | // register placeholderAPI 76 | if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) { 77 | new Placeholders(this).register(); 78 | } 79 | 80 | // translation system init 81 | LanguageLoader.saveLanguages(); 82 | LanguageLoader.setLanguage(getConfig().getString("language")); 83 | 84 | // command system init 85 | this.liteCommands = LiteBukkitFactory.builder("nextron", this) 86 | .commands(new BackCommand(), new EnderchestCommand(), new FeatureCommand(), new FlyCommand(), 87 | new GamemodeCommand(), new GetPosCommand(), new GodCommand(), new HatCommand(), 88 | new HeadCommand(), new HealCommand(), new HelpCommand(), new HomeCommands(), 89 | new InvseeCommand(), new LanguageCommand(), new MenuCommand(), new NickCommand(), 90 | new NightVisionCommand(), new PingCommand(), new RankCommand(), new ReloadCommand(), 91 | new RenameCommand(), new RepairCommand(), new SpawnCommand(), new SpeedCommand(), 92 | new SudoCommand(), new TimeCommand(), new TopCommand(), new TpacceptCommand(), new TpaCommand(), 93 | new TpdenyCommand(), new TphereCommand(), new VanishCommand(), new WarpCommands(), 94 | new WorldCommand(), 95 | new TpahereCommand()) 96 | 97 | .argument(Feature.class, new FeatureArgument()).argument(GameMode.class, new GameModeArgument()) 98 | .argument(Help.class, new HelpArgument()).argument(Home.class, new HomeArgument()) 99 | .argument(Language.class, new LanguageArgument()).argument(Rank.class, new RankArgument()) 100 | .argument(Seed.class, new SeedArgument()).argument(Warp.class, new WarpArgument()) 101 | 102 | .message(LiteBukkitMessages.PLAYER_NOT_FOUND, getInvalidPlayer()) 103 | .message(LiteBukkitMessages.PLAYER_ONLY, getCommandInstance()) 104 | .message(LiteBukkitMessages.MISSING_PERMISSIONS, getNoPerm()) 105 | .message(LiteBukkitMessages.INVALID_USAGE, 106 | invalidUsage -> getPrefix() + "§cUsage: " + invalidUsage.getSchematic().first()) 107 | 108 | .build(); 109 | 110 | // check for updates from github 111 | Bukkit.getScheduler().runTaskAsynchronously(this, () -> { 112 | updateChecker = new UpdateChecker(this, "0pandadev/nextron"); 113 | updateChecker.checkForUpdates(); 114 | }); 115 | 116 | loadWorlds(); 117 | saveDefaultConfig(); 118 | reloadConfig(); 119 | 120 | for (Player player : Bukkit.getOnlinePlayers()) { 121 | player.setDisplayName(SettingsAPI.getNick(player)); 122 | } 123 | 124 | for (Player player : Bukkit.getOnlinePlayers()) { 125 | SettingsAPI.initializeUser(player); 126 | RankAPI.checkRank(player); 127 | VanishAPI.executeVanish(player); 128 | } 129 | 130 | tablistManager.setAllPlayerTeams(); 131 | 132 | NoPerm = Prefix + TextAPI.get("no.perms"); 133 | InvalidPlayer = Prefix + TextAPI.get("invalid.player"); 134 | CommandInstance = Prefix + TextAPI.get("command.instance.error"); 135 | 136 | registerListeners(); 137 | 138 | int pluginId = 20704; 139 | new Metrics(this, pluginId); 140 | 141 | Bukkit.getConsoleSender().sendMessage(Prefix + TextAPI.get("console.activate")); 142 | } 143 | 144 | @Override 145 | public void onDisable() { 146 | if (this.liteCommands != null) { 147 | this.liteCommands.unregister(); 148 | } 149 | 150 | for (Team team : Objects.requireNonNull(Bukkit.getScoreboardManager()).getMainScoreboard().getTeams()) { 151 | team.unregister(); 152 | } 153 | 154 | Bukkit.getConsoleSender().sendMessage(Prefix + TextAPI.get("console.disabled")); 155 | instance = null; 156 | } 157 | 158 | private void registerListeners() { 159 | PluginManager pluginManager = Bukkit.getPluginManager(); 160 | pluginManager.registerEvents(new JoinListener(), this); 161 | pluginManager.registerEvents(new QuitListener(), this); 162 | pluginManager.registerEvents(new ChatEditor(), this); 163 | pluginManager.registerEvents(new InputListener(), this); 164 | pluginManager.registerEvents(new ClickableMessages(), this); 165 | pluginManager.registerEvents(new BackCommandListener(), this); 166 | } 167 | 168 | public void loadWorlds() { 169 | Path worldsFile = Paths.get("worlds.txt"); 170 | if (Files.exists(worldsFile)) { 171 | try { 172 | List worldNames = Files.readAllLines(worldsFile); 173 | List validWorldNames = worldNames.stream().filter(this::worldExists) 174 | .collect(Collectors.toList()); 175 | for (String worldName : validWorldNames) { 176 | Bukkit.createWorld(new WorldCreator(worldName)); 177 | } 178 | Files.write(worldsFile, validWorldNames); 179 | } catch (IOException e) { 180 | e.printStackTrace(); 181 | } 182 | } 183 | } 184 | 185 | private boolean worldExists(String worldName) { 186 | File worldFolder = new File(Bukkit.getWorldContainer(), worldName); 187 | return worldFolder.exists(); 188 | } 189 | 190 | } -------------------------------------------------------------------------------- /src/main/java/net/pandadev/nextron/commands/WorldCommand.java: -------------------------------------------------------------------------------- 1 | package net.pandadev.nextron.commands; 2 | 3 | import dev.rollczi.litecommands.annotations.argument.Arg; 4 | import dev.rollczi.litecommands.annotations.command.RootCommand; 5 | import dev.rollczi.litecommands.annotations.context.Context; 6 | import dev.rollczi.litecommands.annotations.execute.Execute; 7 | import dev.rollczi.litecommands.annotations.permission.Permission; 8 | import net.pandadev.nextron.Main; 9 | import net.pandadev.nextron.arguments.objects.Seed; 10 | import net.pandadev.nextron.languages.TextAPI; 11 | import org.bukkit.Bukkit; 12 | import org.bukkit.World; 13 | import org.bukkit.WorldCreator; 14 | import org.bukkit.WorldType; 15 | import org.bukkit.command.CommandSender; 16 | import org.bukkit.entity.Player; 17 | import org.joml.Random; 18 | 19 | import java.io.File; 20 | import java.io.FileWriter; 21 | import java.io.IOException; 22 | import java.nio.file.Files; 23 | import java.nio.file.Path; 24 | import java.nio.file.Paths; 25 | import java.util.ArrayList; 26 | import java.util.List; 27 | import java.util.Optional; 28 | 29 | @RootCommand 30 | @Permission("nextron.world.*") 31 | public class WorldCommand extends HelpBase { 32 | 33 | public WorldCommand() { 34 | super("world, Allows you to manage your worlds on a server, /world tp \n/world create \n/world delete \n/world load \n/world unload "); 35 | } 36 | 37 | @Execute(name = "world tp") 38 | @Permission("nextron.world.tp") 39 | public void worldCommand(@Context Player player, @Arg World world) { 40 | List worlds = Bukkit.getWorlds(); 41 | List world_names = new ArrayList<>(); 42 | for (World worldl : worlds) { 43 | world_names.add(worldl.getName()); 44 | } 45 | 46 | if (!world_names.contains(world.getName())) { 47 | player.sendMessage(Main.getPrefix() + TextAPI.get("world.error")); 48 | return; 49 | } 50 | 51 | for (World worldl : worlds) { 52 | if (worldl.getName().equals(world.getName())) { 53 | player.teleport(worldl.getSpawnLocation()); 54 | player.sendMessage(Main.getPrefix() + TextAPI.get("world.success").replace("%w", worldl.getName())); 55 | } 56 | } 57 | } 58 | 59 | @Execute(name = "world create") 60 | @Permission("nextron.world.create") 61 | public void createWorldCommand(@Context CommandSender sender, @Arg String name, @Arg Optional seed) { 62 | sender.sendMessage(Main.getPrefix() + TextAPI.get("world.create.start").replace("%w", name)); 63 | 64 | Bukkit.getScheduler().runTask(Main.getInstance(), () -> { 65 | WorldCreator wc = new WorldCreator(name); 66 | 67 | wc.environment(World.Environment.NORMAL); 68 | wc.type(WorldType.NORMAL); 69 | 70 | seed.ifPresent(value -> wc.seed(value.getSeed())); 71 | 72 | wc.createWorld(); 73 | sender.sendMessage(Main.getPrefix() + TextAPI.get("world.create.finished").replace("%w", name)); 74 | }); 75 | 76 | try (FileWriter writer = new FileWriter("worlds.txt", true)) { 77 | writer.write(name + "\n"); 78 | } catch (IOException e) { 79 | throw new RuntimeException(e); 80 | } 81 | } 82 | 83 | @Execute(name = "world delete") 84 | @Permission("nextron.world.delete") 85 | public void deleteWorldCommand(@Context CommandSender sender, @Arg World worldName) { 86 | if (worldName.getName().equals("world")) { 87 | sender.sendMessage(Main.getPrefix() + TextAPI.get("world.delete.default.error")); 88 | return; 89 | } 90 | World world = Bukkit.getWorld(worldName.getName()); 91 | if (world == null) { 92 | sender.sendMessage(Main.getPrefix() + TextAPI.get("world.delete.error").replace("%w", worldName.getName())); 93 | return; 94 | } 95 | List worlds = Bukkit.getWorlds(); 96 | worlds.remove(world); 97 | World newWorld = Bukkit.getWorld("world"); 98 | if (newWorld == null && !worlds.isEmpty()) { 99 | newWorld = worlds.get(new Random().nextInt(worlds.size())); 100 | } 101 | if (newWorld != null) { 102 | for (Player p : world.getPlayers()) { 103 | p.teleport(newWorld.getSpawnLocation()); 104 | } 105 | } 106 | 107 | sender.sendMessage(Main.getPrefix() + TextAPI.get("world.delete.start").replace("%w", worldName.getName())); 108 | if (deleteWorld(worldName.getName())) { 109 | sender.sendMessage(Main.getPrefix() + TextAPI.get("world.delete.finished").replace("%w", worldName.getName())); 110 | } else { 111 | sender.sendMessage(Main.getPrefix() + TextAPI.get("world.delete.error").replace("%w", worldName.getName())); 112 | } 113 | } 114 | 115 | @Execute(name = "world load") 116 | @Permission("nextron.world.load") 117 | public void loadCommand(@Context CommandSender sender, @Arg String worldName) { 118 | File worldFolder = new File(Bukkit.getServer().getWorldContainer().getAbsolutePath(), worldName); 119 | if (!worldFolder.exists()) { 120 | sender.sendMessage(Main.getPrefix() + TextAPI.get("world.load.notexist").replace("%w", worldName)); 121 | return; 122 | } 123 | World world = Bukkit.getWorld(worldName); 124 | if (world == null) { 125 | sender.sendMessage(Main.getPrefix() + TextAPI.get("world.load.start").replace("%w", worldName)); 126 | WorldCreator wc = new WorldCreator(worldName); 127 | wc.createWorld(); 128 | sender.sendMessage(Main.getPrefix() + TextAPI.get("world.load.success").replace("%w", worldName)); 129 | } else { 130 | sender.sendMessage(Main.getPrefix() + TextAPI.get("world.load.error").replace("%w", worldName)); 131 | } 132 | 133 | try (FileWriter writer = new FileWriter("worlds.txt", true)) { 134 | writer.write(worldName + "\n"); 135 | } catch (IOException e) { 136 | throw new RuntimeException(e); 137 | } 138 | } 139 | 140 | @Execute(name = "world unload") 141 | @Permission("nextron.world.unload") 142 | public void unloadCommand(@Context CommandSender sender, @Arg World worldName) { 143 | if (worldName.getName().equals("world")) { 144 | sender.sendMessage(Main.getPrefix() + TextAPI.get("world.unload.default.error")); 145 | return; 146 | } 147 | World world = Bukkit.getWorld(worldName.getName()); 148 | if (world != null) { 149 | List worlds = Bukkit.getWorlds(); 150 | worlds.remove(world); 151 | World newWorld = Bukkit.getWorld("world"); 152 | if (newWorld == null && !worlds.isEmpty()) { 153 | newWorld = worlds.get(new Random().nextInt(worlds.size())); 154 | } 155 | if (newWorld != null) { 156 | for (Player p : world.getPlayers()) { 157 | p.teleport(newWorld.getSpawnLocation()); 158 | } 159 | } 160 | 161 | sender.sendMessage(Main.getPrefix() + TextAPI.get("world.unload.start").replace("%w", worldName.getName())); 162 | if (Bukkit.unloadWorld(world, true)) { 163 | sender.sendMessage(Main.getPrefix() + TextAPI.get("world.unload.success").replace("%w", worldName.getName())); 164 | } else { 165 | sender.sendMessage(Main.getPrefix() + TextAPI.get("world.unload.error").replace("%w", worldName.getName())); 166 | } 167 | } else { 168 | sender.sendMessage(Main.getPrefix() + TextAPI.get("world.unload.error").replace("%w", worldName.getName())); 169 | } 170 | } 171 | 172 | public boolean deleteWorld(String worldName) { 173 | World world = Bukkit.getWorld(worldName); 174 | if (world == null) { 175 | return false; 176 | } 177 | 178 | if (!Bukkit.unloadWorld(world, true)) { 179 | return false; 180 | } 181 | 182 | Path worldFolder = Paths.get(Bukkit.getWorldContainer().getAbsolutePath(), worldName); 183 | try { 184 | Files.walk(worldFolder) 185 | .map(Path::toFile) 186 | .sorted((o1, o2) -> -o1.compareTo(o2)) 187 | .forEach(File::delete); 188 | } catch (IOException e) { 189 | e.printStackTrace(); 190 | return false; 191 | } 192 | 193 | return true; 194 | } 195 | } --------------------------------------------------------------------------------