diff --git a/.github/workflows/Validate-Build.yml b/.github/workflows/Validate-Build.yml new file mode 100644 index 0000000..1ad6f66 --- /dev/null +++ b/.github/workflows/Validate-Build.yml @@ -0,0 +1,32 @@ +name: Validate Build + +on: + # Trigger when a pull request is opened or reopened + pull_request: + types: + - opened + - reopened + # Trigger when a code review is submitted + pull_request_review: + types: + - submitted + # Allow manual runs + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - uses: actions/checkout@v3 + + - name: Set up JDK 21 + uses: actions/setup-java@v3 + with: + java-version: '21' + distribution: 'temurin' + + - name: Build with Gradle + run: gradle build diff --git a/build.gradle b/build.gradle index 26cbb75..d8ed326 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ plugins { id 'java' - // Apply the plugin + id 'com.github.johnrengelman.shadow' version '7.1.2' id("xyz.jpenilla.run-paper") version "2.3.1" } @@ -17,10 +17,19 @@ repositories { name = "sonatype" url = "https://oss.sonatype.org/content/groups/public/" } + maven{ + url = "https://repo.aikar.co/content/groups/aikar/" + } + + maven { + url = 'https://repo.extendedclip.com/content/repositories/placeholderapi/' + } } dependencies { compileOnly("io.papermc.paper:paper-api:1.21.4-R0.1-SNAPSHOT") + + implementation("co.aikar:acf-paper:0.5.1-SNAPSHOT") } def targetJavaVersion = 21 diff --git a/gradle.properties b/gradle.properties index 40a9427..854a88c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -mod_version=0.2.1 \ No newline at end of file +mod_version=0.2.2 \ No newline at end of file diff --git a/src/main/java/moe/sebiann/system/Classes/Home.java b/src/main/java/moe/sebiann/system/Classes/Home.java new file mode 100644 index 0000000..e5cd711 --- /dev/null +++ b/src/main/java/moe/sebiann/system/Classes/Home.java @@ -0,0 +1,325 @@ +package moe.sebiann.system.Classes; + +import moe.sebiann.system.SystemHomes; +import org.bukkit.OfflinePlayer; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +public class Home extends Location implements Serializable { + + String name; + UUID owningPlayer; + boolean isPublic = false; + + // + /** + * Creates a home Object + * @param name The name of the home + * @param owningPlayer The UUID of the player who owns the home + * @param location The location where the home is + */ + public Home(String name, UUID owningPlayer, Location location) { + super(location); + this.name = name; + this.owningPlayer = owningPlayer; + } + + /** + * Creates a home Object + * @param name The name of the home + * @param owningPlayer The player who owns the home + * @param location The location where the home is + */ + public Home(String name, OfflinePlayer owningPlayer, Location location) { + super(location); + this.name = name; + this.owningPlayer = owningPlayer.getUniqueId(); + } + + /** + * Creates a home Object + * @param name The name of the home + * @param owningPlayer The player who owns the home + * @param worldName The name of the world + * @param x The X-Coordinate + * @param y The Y-Coordinate + * @param z The Z-Coordinate + */ + public Home(String name, OfflinePlayer owningPlayer, String worldName, float x, float y, float z) { + super(worldName, x,y,z); + this.name = name; + this.owningPlayer = owningPlayer.getUniqueId(); + } + + /** + * Creates a home Object + * @param name The name of the home + * @param owningPlayer The player UUID who owns the home + * @param worldName The name of the world + * @param x The X-Coordinate + * @param y The Y-Coordinate + * @param z The Z-Coordinate + */ + public Home(String name, UUID owningPlayer, String worldName, float x, float y, float z) { + super(worldName, x,y,z); + this.name = name; + this.owningPlayer = owningPlayer; + } + + /** + * Creates a home Object + * @param name The name of the home + * @param owningPlayer The player who owns the home + * @param worldName The name of the world + * @param x The X-Coordinate + * @param y The Y-Coordinate + * @param z The Z-Coordinate + * @param yaw The yaw + * @param pitch The pitch + */ + public Home(String name, OfflinePlayer owningPlayer, String worldName, float x, float y, float z, float yaw, float pitch) { + super(worldName, x,y,z, yaw, pitch); + this.name = name; + this.owningPlayer = owningPlayer.getUniqueId(); + } + + /** + * Creates a home Object + * @param name The name of the home + * @param owningPlayer The player UUID who owns the home + * @param worldName The name of the world + * @param x The X-Coordinate + * @param y The Y-Coordinate + * @param z The Z-Coordinate + * @param yaw The yaw + * @param pitch The pitch + */ + public Home(String name, UUID owningPlayer, String worldName, float x, float y, float z, float yaw, float pitch) { + super(worldName, x,y,z, yaw, pitch); + this.name = name; + this.owningPlayer = owningPlayer; + } + // + + // + /** + * Gets the current home name + * @return The name of the home + */ + public String getHomeName() { + return name; + } + + /** + * Sets the name of the home + * @param name New name of the home + */ + public void setHomeName(String name) { + this.name = name; + } + + /** + * Gets who owns the home + * @return UUID of the player + */ + public UUID getOwner() { + return owningPlayer; + } + + /** + * Gets if the home is public + * @return publicity of the home + */ + public boolean isPublic() { + return isPublic; + } + + /** + * Sets the new publicity of this home + * @param isPublic whether the home is public or not + */ + public void setPublic(boolean isPublic) { + this.isPublic = isPublic; + } + // + + @Override + public String toString(){ + return name; + } + + /** + * Creates the YAML FileConfig of this class + * @return FileConfiguration of the YAML + */ + private FileConfiguration toYamlConfiguration(){ + File homesFile = new File(SystemHomes.plugin.getDataFolder(), "homes.yml"); + + if (!homesFile.exists()) { + try { + if (homesFile.getParentFile().mkdirs()) { + SystemHomes.plugin.getLogger().info("Created plugin data directory."); + } + if (homesFile.createNewFile()) { + SystemHomes.plugin.getLogger().info("Created homes.yml file."); + } + } catch (IOException e) { + SystemHomes.plugin.getLogger().severe("Could not create homes.yml file!"); + e.printStackTrace(); + } + } + + FileConfiguration config = YamlConfiguration.loadConfiguration(homesFile); + String path = "homes." + owningPlayer + "." + name; + + config.set(path + ".world", world); + config.set(path + ".public", isPublic); + config.set(path + ".x", x); + config.set(path + ".y", y); + config.set(path + ".z", z); + config.set(path + ".yaw", yaw); + config.set(path + ".pitch", pitch); + return config; + } + + /** + * @return the YAML string from this class + */ + public String toYamlString(){ + return toYamlConfiguration().toString(); + } + + /** + * Adds the home to the homes.yml file + * @throws RuntimeException May throw a runtime exception if it can not write the file + */ + public void uploadHome(){ + File homesFile = new File(SystemHomes.plugin.getDataFolder(), "homes.yml"); + try { + toYamlConfiguration().save(homesFile); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * Deletes a home from the homes.yml file + * @throws RuntimeException May throw a runtime exception if it can not write the file + */ + public void deleteHome() { + File homesFile = new File(SystemHomes.plugin.getDataFolder(), "homes.yml"); + YamlConfiguration config = YamlConfiguration.loadConfiguration(homesFile); + String path = "homes." + owningPlayer + "." + name; + + if (config.contains(path)) { + config.set(path, null); + + try { + config.save(homesFile); + } catch (IOException e) { + throw new RuntimeException("Could not save updated homes.yml file", e); + } + } + } + + /** + * Gets the home object from a YAML config file + * @param config The YAML FileConfiguration + * @param pathPrefix the prefix of what to search + * @return Home object + */ + private static Home getHomeFromConfig(FileConfiguration config, String pathPrefix){ + String[] pathSegments = pathPrefix.split("\\."); + String owningPlayer = pathSegments[pathSegments.length - 2]; + String name = pathSegments[pathSegments.length - 1]; + + Home home = new Home( + name, + UUID.fromString(owningPlayer), + config.getString(pathPrefix + ".world"), + Float.parseFloat(config.getString(pathPrefix + ".x")), + Float.parseFloat(config.getString(pathPrefix + ".y")), + Float.parseFloat(config.getString(pathPrefix + ".z")), + Float.parseFloat(config.getString(pathPrefix + ".yaw")), + Float.parseFloat(config.getString(pathPrefix + ".pitch")) + ); + + home.setPublic(config.getBoolean(pathPrefix + ".public", false)); + return home; + } + + /** + * Gets the home object from a YAML string + * @param yamlString the YAML string of the object + * @return Home object + */ + public static Home fromYamlString(String yamlString) { + FileConfiguration config = YamlConfiguration.loadConfiguration(new StringReader(yamlString)); + String pathPrefix = "homes."; + return getHomeFromConfig(config, pathPrefix); + } + + /** + * Gets the default home of the player + * @param owningPlayer The player whose home you want to get + * @return The home object + */ + public static Home getHome(UUID owningPlayer) { + return getHome(owningPlayer, "home"); + } + + /** + * Gets the specified home of the player + * @param owningPlayer The player whose home you want to get + * @param name The home name + * @return The home object + */ + public static Home getHome(UUID owningPlayer, String name) { + FileConfiguration config = YamlConfiguration.loadConfiguration(new File(SystemHomes.plugin.getDataFolder(), "homes.yml")); + String pathPrefix = "homes." + owningPlayer + "." + name; + + if (!config.contains(pathPrefix)) { + throw new IllegalArgumentException("Home '" + name + "' does not exist for player '" + owningPlayer + "' in the file."); + } + + return getHomeFromConfig(config, pathPrefix); + } + + public static boolean containsHome(String homePath){ + FileConfiguration config = YamlConfiguration.loadConfiguration(new File(SystemHomes.plugin.getDataFolder(), "homes.yml")); + return config.contains(homePath); + } + + public static List getPlayerHomes(UUID owningPlayer){ + List homes = new ArrayList<>(); + File homesFile = new File(SystemHomes.plugin.getDataFolder(), "homes.yml"); + FileConfiguration config = YamlConfiguration.loadConfiguration(homesFile); + + String playerPath = "homes." + owningPlayer.toString(); + + ConfigurationSection section = config.getConfigurationSection(playerPath); + if(section == null){ + return homes; + } + + Set homeNames = section.getKeys(false); + for (String homeName : homeNames) { + String homePath = playerPath + "." + homeName; + Home home = getHomeFromConfig(config, homePath); + homes.add(home); + } + + return homes; + } + +} diff --git a/src/main/java/moe/sebiann/system/Classes/Location.java b/src/main/java/moe/sebiann/system/Classes/Location.java new file mode 100644 index 0000000..9af5e54 --- /dev/null +++ b/src/main/java/moe/sebiann/system/Classes/Location.java @@ -0,0 +1,89 @@ +package moe.sebiann.system.Classes; + +import org.bukkit.Bukkit; + +import java.io.Serializable; + +public class Location implements Serializable { + + public float x; + public float y; + public float z; + public float yaw = 0; + public float pitch = 0; + public String world; + + // + /** + * Creates a location + * @param location An already existing location + */ + public Location(Location location) { + this.world = location.world; + this.x = location.x; + this.y = location.y; + this.z = location.z; + + if(location.yaw != 0){ + this.yaw = location.yaw; + } + if(location.pitch != 0){ + this.pitch = location.pitch; + } + } + + public Location(org.bukkit.Location location) { + this.world = location.getWorld().getName(); + this.x = (float) location.getX(); + this.y = (float) location.getY(); + this.z = (float) location.getZ(); + this.yaw = location.getYaw(); + this.pitch = location.getPitch(); + } + + /** + * Creates a new location + * @param world Name of the world this location is in + * @param x X-Coordinate + * @param y Y-Coordinate + * @param z Z-Coordinate + */ + public Location(String world, float x, float y, float z) { + this.world = world; + this.x = x; + this.y = y; + this.z = z; + } + + /** + * + * Creates a new location + * @param world Name of the world this location is in + * @param x X-Coordinate + * @param y Y-Coordinate + * @param z Z-Coordinate + * @param yaw Yaw + * @param pitch Pitch + */ + public Location(String world, float x, float y, float z, float yaw, float pitch) { + this.world = world; + this.x = x; + this.y = y; + this.z = z; + this.yaw = yaw; + this.pitch = pitch; + } + // + + public Location getLocation(){ + return this; + } + + public org.bukkit.Location toBukkitLocation() { + return new org.bukkit.Location( + Bukkit.getWorld(world), + x, y, z, + pitch, yaw + ); + } +} diff --git a/src/main/java/moe/sebiann/system/Classes/PlayerWarp.java b/src/main/java/moe/sebiann/system/Classes/PlayerWarp.java new file mode 100644 index 0000000..d4e7e50 --- /dev/null +++ b/src/main/java/moe/sebiann/system/Classes/PlayerWarp.java @@ -0,0 +1,24 @@ +package moe.sebiann.system.Classes; + +import java.util.UUID; + +public class PlayerWarp extends Warp{ + + UUID owningPlayer; + + public PlayerWarp(String warpName, org.bukkit.Location location) { + super(warpName, location); + } + + public PlayerWarp(String warpName, Location location) { + super(warpName, location); + } + + public PlayerWarp(String warpName, String world, float x, float y, float z, float yaw, float pitch) { + super(warpName, world, x, y, z, yaw, pitch); + } + + public PlayerWarp(String warpName, String world, float x, float y, float z) { + super(warpName, world, x, y, z); + } +} diff --git a/src/main/java/moe/sebiann/system/Classes/TpaRequest.java b/src/main/java/moe/sebiann/system/Classes/TpaRequest.java new file mode 100644 index 0000000..9732540 --- /dev/null +++ b/src/main/java/moe/sebiann/system/Classes/TpaRequest.java @@ -0,0 +1,51 @@ +package moe.sebiann.system.Classes; + +import moe.sebiann.system.Enums.TpaType; + +import java.util.UUID; + +public class TpaRequest { + + UUID requester; + UUID target; + TpaType type; + + // + /** + * Makes a new TPA-Request (TPA, Not TPA-HERE) + * @param requester The person who will be teleported + * @param target The person who will be teleported to + */ + public TpaRequest(UUID requester, UUID target) { + this.requester = requester; + this.target = target; + this.type = TpaType.TPA_THERE; + } + + /** + * Makes a new TPA-Request + * @param requester The person who will be teleported + * @param target The person who will be teleported to + * @param type The type of request it is TPA or TPA-here + */ + public TpaRequest(UUID requester, UUID target, TpaType type) { + this.requester = requester; + this.target = target; + this.type = type; + } + // + + // + public UUID getRequester() { + return requester; + } + + public UUID getTarget() { + return target; + } + + public TpaType getType() { + return type; + } + // +} diff --git a/src/main/java/moe/sebiann/system/Classes/Warp.java b/src/main/java/moe/sebiann/system/Classes/Warp.java new file mode 100644 index 0000000..46364fc --- /dev/null +++ b/src/main/java/moe/sebiann/system/Classes/Warp.java @@ -0,0 +1,237 @@ +package moe.sebiann.system.Classes; + +import moe.sebiann.system.SystemHomes; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +public class Warp extends Location{ + + String warpName; + + // + /** + * Creates a warp object + * @param warpName The name of the warp + * @param location The location of the warp + */ + public Warp(String warpName, Location location) { + super(location); + this.warpName = warpName; + } + + /** + * Creates a warp object + * @param warpName The name of the warp + * @param location The bukkit location of the warp + */ + public Warp(String warpName, org.bukkit.Location location) { + super(location); + this.warpName = warpName; + } + + /** + * Creates a warp object + * @param warpName The name of the warp + * @param world The world of the warp + * @param x The X-Coordinate of the warp + * @param y The Y-Coordinate of the warp + * @param z The Z-Coordinate of the warp + */ + public Warp(String warpName, String world, float x, float y, float z) { + super(world, x, y, z); + this.warpName = warpName; + } + + /** + * + * Creates a warp object + * @param warpName The name of the warp + * @param world The world of the warp + * @param x The X-Coordinate of the warp + * @param y The Y-Coordinate of the warp + * @param z The Z-Coordinate of the warp + * @param yaw The yaw of the warp + * @param pitch The pitch of the warp + */ + public Warp(String warpName, String world, float x, float y, float z, float yaw, float pitch) { + super(world, x, y, z, yaw, pitch); + this.warpName = warpName; + } + // + + // + + /** + * @return Gets the warp name + */ + public String getWarpName() { + return warpName; + } + + /** + * Sets the warp name + * @param warpName New name for this warp + */ + public void setWarpName(String warpName) { + this.warpName = warpName; + } + // + + + /** + * Creates the YAML FileConfig of this class + * @return FileConfiguration of the YAML + */ + @SuppressWarnings("DuplicatedCode") + private FileConfiguration toYamlConfiguration(){ + File warpFile = new File(SystemHomes.plugin.getDataFolder(), "warps.yml"); + + if (!warpFile.exists()) { + try { + if (warpFile.getParentFile().mkdirs()) { + SystemHomes.plugin.getLogger().info("Created plugin data directory."); + } + if (warpFile.createNewFile()) { + SystemHomes.plugin.getLogger().info("Created warps.yml file."); + } + } catch (IOException e) { + SystemHomes.plugin.getLogger().severe("Could not create warps.yml file!"); + e.printStackTrace(); + } + } + + FileConfiguration config = YamlConfiguration.loadConfiguration(warpFile); + String path = "warps." + warpName; + + config.set(path + ".world", world); + config.set(path + ".x", x); + config.set(path + ".y", y); + config.set(path + ".z", z); + config.set(path + ".yaw", yaw); + config.set(path + ".pitch", pitch); + return config; + } + + /** + * @return the YAML string from this class + */ + public String toYamlString(){ + return toYamlConfiguration().toString(); + } + + /** + * Adds the warp to the warps.yml file + * @throws RuntimeException May throw a runtime exception if it can not write the file + */ + public void uploadWarp(){ + File warpsFile = new File(SystemHomes.plugin.getDataFolder(), "warps.yml"); + try { + toYamlConfiguration().save(warpsFile); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * Deletes a home from the warps.yml file + * @throws RuntimeException May throw a runtime exception if it can not write the file + */ + public void deleteWarp() { + File warpsFile = new File(SystemHomes.plugin.getDataFolder(), "warps.yml"); + YamlConfiguration config = YamlConfiguration.loadConfiguration(warpsFile); + String path = "warps." + warpName; + + if (config.contains(path)) { + config.set(path, null); + + try { + config.save(warpsFile); + } catch (IOException e) { + throw new RuntimeException("Could not save updated warps.yml file", e); + } + } + } + + /** + * Gets the home object from a YAML config file + * @param config The YAML FileConfiguration + * @param pathPrefix the prefix of what to search + * @return Home object + */ + private static Warp getWarpFromConfig(FileConfiguration config, String pathPrefix){ + String[] pathSegments = pathPrefix.split("\\."); + String name = pathSegments[pathSegments.length - 1]; + + return new Warp( + name, + config.getString(pathPrefix + ".world"), + Float.parseFloat(config.getString(pathPrefix + ".x")), + Float.parseFloat(config.getString(pathPrefix + ".y")), + Float.parseFloat(config.getString(pathPrefix + ".z")), + Float.parseFloat(config.getString(pathPrefix + ".yaw")), + Float.parseFloat(config.getString(pathPrefix + ".pitch")) + ); + } + + /** + * Gets the home object from a YAML string + * @param yamlString the YAML string of the object + * @return Home object + */ + public static Warp fromYamlString(String yamlString) { + FileConfiguration config = YamlConfiguration.loadConfiguration(new StringReader(yamlString)); + String pathPrefix = "warps."; + return getWarpFromConfig(config, pathPrefix); + } + + /** + * Gets the specified warp + * @param name The home name + * @return The home object + */ + public static Warp getWarp(String name) { + FileConfiguration config = YamlConfiguration.loadConfiguration(new File(SystemHomes.plugin.getDataFolder(), "warps.yml")); + String pathPrefix = "warps." + name; + + if (!config.contains(pathPrefix)) { + throw new IllegalArgumentException("Warp '" + name + "' does not exist in the file."); + } + + return getWarpFromConfig(config, pathPrefix); + } + + public static List getWarps(){ + List warps = new ArrayList<>(); + File warpsFile = new File(SystemHomes.plugin.getDataFolder(), "warps.yml"); + FileConfiguration config = YamlConfiguration.loadConfiguration(warpsFile); + + String path = "warps."; + + ConfigurationSection section = config.getConfigurationSection(path); + if(section == null){ + return warps; + } + + Set warpNames = section.getKeys(false); + for (String warpName : warpNames) { + String warpPath = path + warpName; + Warp warp = getWarpFromConfig(config, warpPath); + warps.add(warp); + } + + return warps; + } + + public static boolean containsWarp(String warpPath){ + FileConfiguration config = YamlConfiguration.loadConfiguration(new File(SystemHomes.plugin.getDataFolder(), "warps.yml")); + return config.contains(warpPath); + } +} diff --git a/src/main/java/moe/sebiann/system/Enums/TpaType.java b/src/main/java/moe/sebiann/system/Enums/TpaType.java new file mode 100644 index 0000000..f0ceba1 --- /dev/null +++ b/src/main/java/moe/sebiann/system/Enums/TpaType.java @@ -0,0 +1,6 @@ +package moe.sebiann.system.Enums; + +public enum TpaType { + TPA_THERE, + TPA_HERE +} diff --git a/src/main/java/moe/sebiann/system/SystemHomes.java b/src/main/java/moe/sebiann/system/SystemHomes.java index bde6310..19984cc 100644 --- a/src/main/java/moe/sebiann/system/SystemHomes.java +++ b/src/main/java/moe/sebiann/system/SystemHomes.java @@ -1,92 +1,51 @@ package moe.sebiann.system; -import moe.sebiann.system.commands.home.*; -import moe.sebiann.system.commands.warp.*; -import moe.sebiann.system.commands.tpa.*; +import co.aikar.commands.PaperCommandManager; +import com.google.common.collect.ImmutableList; import moe.sebiann.system.commands.*; import org.bukkit.plugin.java.JavaPlugin; -import java.io.File; -import java.io.IOException; +import java.util.List; public class SystemHomes extends JavaPlugin { - private File homesFile; - private File warpsFile; + public static SystemHomes plugin = null; + PaperCommandManager manager; @Override public void onEnable() { + if(plugin == null){ + plugin = this; + } // Save and load the configuration saveDefaultConfig(); - // Initialize the homes file - createHomesFile(); - createWarpsFile(); - - TpaManager tpaManager = new TpaManager(); - - getCommand("systemhomes").setExecutor(new SystemHomesCommand(this)); - - // Register home commands - getCommand("sethome").setExecutor(new SetHomeCommand(homesFile, this)); - getCommand("home").setExecutor(new HomeCommand(homesFile, this)); - getCommand("homes").setExecutor(new ListHomesCommand(homesFile)); - getCommand("delhome").setExecutor(new DelHomeCommand(homesFile)); - - // Register warp commands - getCommand("setwarp").setExecutor(new SetWarpCommand(warpsFile)); - getCommand("warp").setExecutor(new WarpCommand(warpsFile, this)); - getCommand("delwarp").setExecutor(new DelWarpCommand(warpsFile)); - getCommand("warps").setExecutor(new ListWarpsCommand(warpsFile)); - getCommand("spawn").setExecutor(new SpawnCommand(warpsFile, this)); - // Register tpa commands - getCommand("tpa").setExecutor(new TpaCommand(tpaManager)); - getCommand("tpahere").setExecutor(new TpahereCommand(tpaManager)); - getCommand("tpaccept").setExecutor(new TpAcceptCommand(tpaManager, this)); - getCommand("tpdeny").setExecutor(new TpDenyCommand(tpaManager)); - - // Register tab completions for warps and homes and reload - getCommand("warp").setTabCompleter(new WarpTabCompleter(warpsFile)); - getCommand("delwarp").setTabCompleter(new WarpTabCompleter(warpsFile)); - getCommand("home").setTabCompleter(new HomeTabCompleter(homesFile)); - getCommand("delhome").setTabCompleter(new HomeTabCompleter(homesFile)); - getCommand("systemhomes").setTabCompleter(new SystemHomesTabCompleter()); + registerCommands(); + commandCompletions(); } - private void createHomesFile() { - homesFile = new File(getDataFolder(), "homes.yml"); - if (!homesFile.exists()) { - try { - if (homesFile.getParentFile().mkdirs()) { - getLogger().info("Created plugin data directory."); - } - if (homesFile.createNewFile()) { - getLogger().info("Created homes.yml file."); - } - } catch (IOException e) { - getLogger().severe("Could not create homes.yml file!"); - e.printStackTrace(); - } - } + void registerCommands(){ + manager = new PaperCommandManager(this); + manager.registerCommand(new SystemHomesCommand()); + manager.registerCommand(new HomeCommands()); + manager.registerCommand(new WarpCommands()); + manager.registerCommand(new SpawnCommand()); + manager.registerCommand(new TpaCommands()); } - private void createWarpsFile() { - warpsFile = new File(getDataFolder(), "warps.yml"); - if (!warpsFile.exists()) { - try { - if (warpsFile.getParentFile().mkdirs()) { - getLogger().info("Created plugin data directory."); - } - if (warpsFile.createNewFile()) { - getLogger().info("Created warps.yml file."); - } - } catch (IOException e) { - getLogger().severe("Could not create warps.yml file!"); - e.printStackTrace(); - } - } + void commandCompletions(){ + manager.getCommandCompletions().registerAsyncCompletion("homeNames", c -> { + String playerName = c.getSender().getName(); + + List homeNames = HomeCommands.homeNameToString(playerName); + return ImmutableList.copyOf(homeNames); + }); + manager.getCommandCompletions().registerAsyncCompletion("warpNames", c -> { + List warpNames = WarpCommands.warpNameToString(); + return ImmutableList.copyOf(warpNames); + }); } } diff --git a/src/main/java/moe/sebiann/system/commands/HomeCommands.java b/src/main/java/moe/sebiann/system/commands/HomeCommands.java new file mode 100644 index 0000000..eb38e13 --- /dev/null +++ b/src/main/java/moe/sebiann/system/commands/HomeCommands.java @@ -0,0 +1,189 @@ +package moe.sebiann.system.commands; + +import co.aikar.commands.BaseCommand; +import co.aikar.commands.annotation.CommandAlias; +import co.aikar.commands.annotation.CommandCompletion; +import moe.sebiann.system.Classes.Home; +import moe.sebiann.system.Classes.Location; +import moe.sebiann.system.SystemHomes; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.event.HoverEvent; +import net.kyori.adventure.text.format.TextColor; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.*; + +public class HomeCommands extends BaseCommand { + + private final Map pendingConfirmations = new HashMap<>(); + + @CommandAlias("sethome") + @CommandCompletion("@nothing") + public void setHome(CommandSender sender, String[] args) { + if(!(sender instanceof Player player)) { + sender.sendMessage(Component.text("Only a player can run this command.").color(TextColor.fromHexString("#FF5555"))); + return; + } + + String homeName; + if (args.length < 1) { + homeName = "home"; + }else{ + homeName = args[0].toLowerCase(); + } + + String playerPath = "homes." + player.getUniqueId() + "." + homeName; + + Home home = new Home( + homeName, + player.getUniqueId(), + new Location(player.getLocation()) + ); + + if (Home.containsHome(playerPath)) { + if (pendingConfirmations.containsKey(player.getUniqueId()) && + pendingConfirmations.get(player.getUniqueId()).equals(homeName)) { + + pendingConfirmations.remove(player.getUniqueId()); + home.uploadHome(); + + player.sendMessage(Component.text("Home ").color(TextColor.fromHexString("#55FF55")) + .append(Component.text(homeName).color(TextColor.fromHexString("#00AA00"))) + .append(Component.text(" has been overridden!").color(TextColor.fromHexString("#55FF55")))); + return; + } + + pendingConfirmations.put(player.getUniqueId(), homeName); + player.sendMessage(Component.text("Home ").color(TextColor.fromHexString("#FF5555")) + .append(Component.text(homeName).color(TextColor.fromHexString("#AA0000"))) + .append(Component.text(" already exists! Use: ").color(TextColor.fromHexString("#FF5555"))) + .append(Component.text("/sethome " + homeName).color(TextColor.fromHexString("#AA0000")) + .hoverEvent(HoverEvent.showText(Component.text("Click this to override your home!").color(TextColor.fromHexString("#FF5555")))) + .clickEvent(ClickEvent.runCommand("/sethome " + homeName))) + .append(Component.text(" again to override it!").color(TextColor.fromHexString("#FF5555")))); + return; + } + + home.uploadHome(); + player.sendMessage(Component.text("Home ").color(TextColor.fromHexString("#55FF55")) + .append(Component.text(homeName).color(TextColor.fromHexString("#00AA00"))) + .append(Component.text(" has been set to this location!").color(TextColor.fromHexString("#55FF55")))); + } + + @CommandAlias("delhome") + @CommandCompletion("@homeNames") + public void delHome(CommandSender sender, String[] args) { + if(!(sender instanceof Player player)) { + sender.sendMessage(Component.text("Only a player can run this command.").color(TextColor.fromHexString("#FF5555"))); + return; + } + + if(args.length < 1) { + player.sendMessage(Component.text("Please put in your home which you want to delete").color(TextColor.fromHexString("#FF5555"))); + return; + } + + String homeName = args[0].toLowerCase(); + Home home; + try{ + home = Home.getHome(player.getUniqueId(), homeName); + } catch (RuntimeException e) { + player.sendMessage(Component.text("This home does not exist.").color(TextColor.fromHexString("#FF5555"))); + return; + } + + try{ + home.deleteHome(); + }catch (RuntimeException e) { + player.sendMessage(Component.text("This home could not be deleted, please try again later.").color(TextColor.fromHexString("#FF5555"))); + return; + } + + player.sendMessage(Component.text("Home ").color(TextColor.fromHexString("#FF5555")) + .append(Component.text(homeName).color(TextColor.fromHexString("#AA0000"))) + .append(Component.text(" has been deleted!").color(TextColor.fromHexString("#FF5555")))); + } + + @CommandAlias("home") + @CommandCompletion("@homeNames") + public void home(CommandSender sender, String[] args) { + if (!(sender instanceof Player player)) { + sender.sendMessage(Component.text("Only a player can run this command.").color(TextColor.fromHexString("#FF5555"))); + return; + } + + String homeName; + if (args.length < 1) { + homeName = "home"; + } else { + homeName = args[0].toLowerCase(); + } + + int delayInSeconds = SystemHomes.plugin.getConfig().getInt("home.teleport_delay", 2); + + Home home; + try{ + home = Home.getHome(player.getUniqueId(), homeName); + }catch (RuntimeException e){ + player.sendMessage(Component.text("This home does not exist.").color(TextColor.fromHexString("#FF5555"))); + return; + } + + org.bukkit.Location location = home.getLocation().toBukkitLocation(); + + player.sendMessage(Component.text("Teleporting you to home: ").color(TextColor.fromHexString("#55FF55")) + .append(Component.text(home.getHomeName()).color(TextColor.fromHexString("#00AA00"))) + .append(Component.text(" in " + delayInSeconds + " seconds.").color(TextColor.fromHexString("#55FF55")))); + + Bukkit.getScheduler().runTaskLater(SystemHomes.plugin, () -> { + player.teleport(location); + player.sendMessage(Component.text("Teleported you to your home: ").color(TextColor.fromHexString("#55FF55")) + .append(Component.text(homeName).color(TextColor.fromHexString("#00AA00")))); + }, delayInSeconds * 20L); + } + + @CommandAlias("homes") + public void homeList(CommandSender sender) { + if (!(sender instanceof Player player)) { + sender.sendMessage(Component.text("Only a player can run this command.").color(TextColor.fromHexString("#FF5555"))); + return; + } + + List homes = Home.getPlayerHomes(player.getUniqueId()); + + Component component = Component.text("Your Homes:\n").color(TextColor.fromHexString("#FFAA00")); + for (Home home : homes) { + component = component.append(Component.text(home.getHomeName()).color(TextColor.fromHexString("#FFAA00")) + .clickEvent(ClickEvent.runCommand("/home " + home.getHomeName())) + .hoverEvent(HoverEvent.showText(Component.text("Teleport to home: " + home.getHomeName()).color(TextColor.fromHexString("#FFAA00"))))); + component = component.append(Component.text(" - ").color(TextColor.fromHexString("#AAAAAA"))); + + String worldName = switch (home.world) { + case "world" -> "Overworld"; + case "world_nether" -> "Nether"; + case "world_the_end" -> "The End"; + default -> home.world; + }; + + component = component.append(Component.text("(" + worldName + "; " + (int) home.x + ", " + (int) home.y + ", " + (int) home.z + ")\n").color(TextColor.fromHexString("#55FFFF")) + .clickEvent(ClickEvent.runCommand("/home " + home.getHomeName())) + .hoverEvent(HoverEvent.showText(Component.text("Teleport to home: " + home.getHomeName()).color(TextColor.fromHexString("#FFAA00"))))); + } + + player.sendMessage(component); + } + + public static List homeNameToString(String playerName){ + List homeNameList = new ArrayList<>(); + List homes = Home.getPlayerHomes(Bukkit.getOfflinePlayer(playerName).getUniqueId()); + + for(Home h : homes){ + homeNameList.add(h.getHomeName()); + } + return homeNameList; + } + +} \ No newline at end of file diff --git a/src/main/java/moe/sebiann/system/commands/SpawnCommand.java b/src/main/java/moe/sebiann/system/commands/SpawnCommand.java index f7d9eeb..754bda9 100644 --- a/src/main/java/moe/sebiann/system/commands/SpawnCommand.java +++ b/src/main/java/moe/sebiann/system/commands/SpawnCommand.java @@ -1,66 +1,44 @@ package moe.sebiann.system.commands; +import co.aikar.commands.BaseCommand; +import co.aikar.commands.annotation.CommandAlias; +import moe.sebiann.system.Classes.Warp; +import moe.sebiann.system.SystemHomes; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.TextColor; import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; -import org.bukkit.plugin.java.JavaPlugin; -import java.io.File; +public class SpawnCommand extends BaseCommand { -public class SpawnCommand implements CommandExecutor { - - private final FileConfiguration warpsConfig; - private final JavaPlugin plugin; - - public SpawnCommand(File warpsFile, JavaPlugin plugin) { - this.warpsConfig = YamlConfiguration.loadConfiguration(warpsFile); - this.plugin = plugin; - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (sender instanceof Player player) { - String path = "warps.spawn"; - - if (!warpsConfig.contains(path)) { - player.sendMessage("§cThe spawn warp is not set!"); - return true; - } - - String worldName = warpsConfig.getString(path + ".world"); - double x = warpsConfig.getDouble(path + ".x"); - double y = warpsConfig.getDouble(path + ".y"); - double z = warpsConfig.getDouble(path + ".z"); - float yaw = (float) warpsConfig.getDouble(path + ".yaw"); - float pitch = (float) warpsConfig.getDouble(path + ".pitch"); - - if (worldName == null || Bukkit.getWorld(worldName) == null) { - player.sendMessage("§cThe world for the spawn warp does not exist!"); - return true; - } + @CommandAlias("spawn") + @SuppressWarnings("DuplicatedCode") + public void spawn(CommandSender sender) { + if(!(sender instanceof Player player)) { + sender.sendMessage(Component.text("Only a player can run this command.").color(TextColor.fromHexString("#FF5555"))); + return; + } - Location spawnLocation = new Location(Bukkit.getWorld(worldName), x, y, z, yaw, pitch); - // Configurable delay - int delayInSeconds = plugin.getConfig().getInt("warp.teleport_delay", 2); // Default 2 seconds - long delayInTicks = delayInSeconds * 20L; + Warp spawn; + try{ + spawn = Warp.getWarp("spawn"); + } catch (RuntimeException e) { + player.sendMessage(Component.text("The spawn warp is not yet set.").color(TextColor.fromHexString("#FF5555"))); + return; + } - // Inform the player about the teleport delay - player.sendMessage("§eTeleporting to spawn in " + delayInSeconds + " seconds..."); + org.bukkit.Location location = spawn.getLocation().toBukkitLocation(); + int delayInSeconds = SystemHomes.plugin.getConfig().getInt("warp.teleport_delay", 2); - // Schedule the teleport - Bukkit.getScheduler().runTaskLater(plugin, () -> { - player.teleport(spawnLocation); - player.sendMessage("§aYou have been teleported to spawn!"); - }, delayInTicks); - return true; - } + player.sendMessage(Component.text("Teleporting you to warp: ").color(TextColor.fromHexString("#55FF55")) + .append(Component.text(spawn.getWarpName()).color(TextColor.fromHexString("#00AA00"))) + .append(Component.text(" in " + delayInSeconds + " seconds.").color(TextColor.fromHexString("#55FF55")))); - sender.sendMessage("Only players can use this command!"); - return true; + Bukkit.getScheduler().runTaskLater(SystemHomes.plugin, () -> { + player.teleport(location); + player.sendMessage(Component.text("Teleported you to your warp: ").color(TextColor.fromHexString("#55FF55")) + .append(Component.text(spawn.getWarpName()).color(TextColor.fromHexString("#00AA00")))); + }, delayInSeconds * 20L); } } diff --git a/src/main/java/moe/sebiann/system/commands/SystemHomesCommand.java b/src/main/java/moe/sebiann/system/commands/SystemHomesCommand.java index 03a2041..09358d3 100644 --- a/src/main/java/moe/sebiann/system/commands/SystemHomesCommand.java +++ b/src/main/java/moe/sebiann/system/commands/SystemHomesCommand.java @@ -1,32 +1,25 @@ package moe.sebiann.system.commands; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; +import co.aikar.commands.BaseCommand; +import co.aikar.commands.annotation.CommandAlias; +import co.aikar.commands.annotation.CommandPermission; +import co.aikar.commands.annotation.Default; +import co.aikar.commands.annotation.Subcommand; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.TextColor; import org.bukkit.command.CommandSender; -import org.bukkit.plugin.java.JavaPlugin; +import moe.sebiann.system.SystemHomes; -public class SystemHomesCommand implements CommandExecutor { - private final JavaPlugin plugin; +@CommandAlias("systemhomes") +public class SystemHomesCommand extends BaseCommand { - public SystemHomesCommand(JavaPlugin plugin) { - this.plugin = plugin; - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (!sender.hasPermission("systemhomes.admin.reload")) { - sender.sendMessage("§cYou do not have permission to use this command."); - return true; - } - - if (args.length == 1 && args[0].equalsIgnoreCase("reload")) { - plugin.reloadConfig(); - sender.sendMessage("§aSystemHomes configuration reloaded successfully!"); - } else { - sender.sendMessage("§cUsage: /systemhomes reload"); - } - - return true; + @Default + @Subcommand("reload") + @CommandPermission("systemhomes.admin") + public void reload(CommandSender sender, String[] args) { + SystemHomes.plugin.reloadConfig(); + sender.sendMessage(Component.text("SystemHomes configuration reloaded successfully!") + .color(TextColor.fromHexString("#55FF55"))); } } diff --git a/src/main/java/moe/sebiann/system/commands/TpaCommands.java b/src/main/java/moe/sebiann/system/commands/TpaCommands.java new file mode 100644 index 0000000..c44c307 --- /dev/null +++ b/src/main/java/moe/sebiann/system/commands/TpaCommands.java @@ -0,0 +1,234 @@ +package moe.sebiann.system.commands; + +import co.aikar.commands.BaseCommand; +import co.aikar.commands.annotation.CommandAlias; +import co.aikar.commands.annotation.CommandCompletion; +import moe.sebiann.system.Classes.TpaRequest; +import moe.sebiann.system.Enums.TpaType; +import moe.sebiann.system.SystemHomes; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.event.HoverEvent; +import net.kyori.adventure.text.format.TextColor; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; + +public class TpaCommands extends BaseCommand { + + List tpaRequests = new ArrayList<>(); + + @CommandAlias("tpa") + @CommandCompletion("@players") + public void tpa(CommandSender sender, String[] args) { + if (!(sender instanceof Player player)) { + sender.sendMessage(Component.text("Only a player can run this command.").color(TextColor.fromHexString("#FF5555"))); + return; + } + if(args.length < 1) { + player.sendMessage(Component.text("Please mention a player you'd want to teleport to.").color(TextColor.fromHexString("#FF5555"))); + return; + } + + Player target = Bukkit.getPlayer(args[0]); + if(target == null) { + player.sendMessage(Component.text("You can not teleport to an offline player.").color(TextColor.fromHexString("#FF5555"))); + return; + } + if(target.getUniqueId().equals(player.getUniqueId())) { + player.sendMessage(Component.text("You can not teleport to yourself.").color(TextColor.fromHexString("#FF5555"))); + return; + } + + for(TpaRequest r : tpaRequests) { + if(r.getRequester().equals(player.getUniqueId())) { + player.sendMessage(Component.text("You already have an outgoing TPA request to this player").color(TextColor.fromHexString("#FF5555"))); + return; + } + } + + TpaRequest tpaRequest = new TpaRequest(player.getUniqueId(), target.getUniqueId()); + tpaRequests.add(tpaRequest); + + int timeoutTime = SystemHomes.plugin.getConfig().getInt("warp.request_timeout", 30); + deleteTpaAfterDelay(player, target, timeoutTime, tpaRequest); + + player.sendMessage(Component.text("Teleport request sent to ").color(TextColor.fromHexString("#55FF55")) + .append(Component.text(target.getName()).color(TextColor.fromHexString("#00AA00"))) + .append(Component.text(".\nRequest will time out in ").color(TextColor.fromHexString("#55FF55"))) + .append(Component.text(timeoutTime).color(TextColor.fromHexString("#00AA00"))) + .append(Component.text(" seconds.").color(TextColor.fromHexString("#55FF55")))); + + target.sendMessage(Component.text(player.getName()).color(TextColor.fromHexString("#00AA00")) + .append(Component.text(" has requested to teleport to you.").color(TextColor.fromHexString("#55FF55"))) + .append(Component.text("\nWrite /tpaccept to accept this request.").color(TextColor.fromHexString("#55FF55")) + .clickEvent(ClickEvent.runCommand("/tpaccept")) + .hoverEvent(HoverEvent.showText(Component.text("Accepts the TPA request").color(TextColor.fromHexString("#55FF55"))))) + .append(Component.text("\nWrite /tpdeny to deny this request.").color(TextColor.fromHexString("#FF5555")) + .clickEvent(ClickEvent.runCommand("/tpdeny")) + .hoverEvent(HoverEvent.showText(Component.text("Denies the TPA request").color(TextColor.fromHexString("#FF5555")))))); + } + + @CommandAlias("tpahere") + @CommandCompletion("@players") + @SuppressWarnings("DuplicatedCode") + public void tpahere(CommandSender sender, String[] args) { + if (!(sender instanceof Player player)) { + sender.sendMessage(Component.text("Only a player can run this command.").color(TextColor.fromHexString("#FF5555"))); + return; + } + if(args.length < 1) { + player.sendMessage(Component.text("Please mention a player you'd want to teleport to.").color(TextColor.fromHexString("#FF5555"))); + return; + } + + Player target = Bukkit.getPlayer(args[0]); + if(target == null) { + player.sendMessage(Component.text("You can not teleport to an offline player.").color(TextColor.fromHexString("#FF5555"))); + return; + } + if(target.getUniqueId().equals(player.getUniqueId())) { + player.sendMessage(Component.text("You can not teleport to yourself.").color(TextColor.fromHexString("#FF5555"))); + return; + } + + TpaRequest tpaRequest = new TpaRequest(player.getUniqueId(), target.getUniqueId(), TpaType.TPA_HERE); + tpaRequests.add(tpaRequest); + + int timeoutTime = SystemHomes.plugin.getConfig().getInt("tpa.request_timeout", 30); + deleteTpaAfterDelay(player, target, timeoutTime, tpaRequest); + + player.sendMessage(Component.text("Teleport request sent to ").color(TextColor.fromHexString("#55FF55")) + .append(Component.text(target.getName()).color(TextColor.fromHexString("#00AA00"))) + .append(Component.text(".\nRequest will time out in ").color(TextColor.fromHexString("#55FF55"))) + .append(Component.text(timeoutTime).color(TextColor.fromHexString("#00AA00"))) + .append(Component.text(" seconds.").color(TextColor.fromHexString("#55FF55")))); + + target.sendMessage(Component.text(player.getName()).color(TextColor.fromHexString("#00AA00")) + .append(Component.text(" has requested you to teleport to them.").color(TextColor.fromHexString("#55FF55"))) + .append(Component.text("\nWrite /tpaccept to accept this request.").color(TextColor.fromHexString("#55FF55")) + .clickEvent(ClickEvent.runCommand("/tpaccept")) + .hoverEvent(HoverEvent.showText(Component.text("Accepts the TPA request").color(TextColor.fromHexString("#55FF55"))))) + .append(Component.text("\nWrite /tpdeny to deny this request.").color(TextColor.fromHexString("#FF5555")) + .clickEvent(ClickEvent.runCommand("/tpdeny")) + .hoverEvent(HoverEvent.showText(Component.text("Denies the TPA request").color(TextColor.fromHexString("#FF5555")))))); + } + + @CommandAlias("tpaccept|tpyes") + @SuppressWarnings("DuplicatedCode") + public void tpaccept(CommandSender sender) { + if (!(sender instanceof Player player)) { + sender.sendMessage(Component.text("Only a player can run this command.").color(TextColor.fromHexString("#FF5555"))); + return; + } + + TpaRequest tpaRequest = null; + for(TpaRequest r : tpaRequests) { + if(r.getTarget().equals(player.getUniqueId())) { + tpaRequest = r; + break; + } + } + if(tpaRequest == null){ + player.sendMessage(Component.text("You don't have any outgoing TPA requests.").color(TextColor.fromHexString("#FF5555"))); + return; + } + Player target = Bukkit.getPlayer(tpaRequest.getRequester()); + + if(target == null) { + player.sendMessage(Component.text("Player is no longer online.").color(TextColor.fromHexString("#FF5555"))); + tpaRequests.remove(tpaRequest); + return; + } + int tpTime = SystemHomes.plugin.getConfig().getInt("tpa.teleport_delay", 2); + tpaRequests.remove(tpaRequest); + + if (tpaRequest.getType() == TpaType.TPA_HERE) { + player.sendMessage(Component.text("TPA request to ").color(TextColor.fromHexString("#55FF55")) + .append(Component.text(target.getName()).color(TextColor.fromHexString("#00AA00"))) + .append(Component.text(" has been accepted.\nYou will be teleported in ").color(TextColor.fromHexString("#55FF55"))) + .append(Component.text(tpTime).color(TextColor.fromHexString("#00AA00"))) + .append(Component.text(" seconds.").color(TextColor.fromHexString("#55FF55")))); + + target.sendMessage(Component.text("The TPA request from ").color(TextColor.fromHexString("#55FF55")) + .append(Component.text(player.getName()).color(TextColor.fromHexString("#00AA00"))) + .append(Component.text(" has been accepted.\nThey will be teleported to you in ").color(TextColor.fromHexString("#55FF55"))) + .append(Component.text(tpTime).color(TextColor.fromHexString("#00AA00"))) + .append(Component.text(" seconds.").color(TextColor.fromHexString("#55FF55")))); + + Bukkit.getScheduler().runTaskLater(SystemHomes.plugin, () -> { + player.teleport(target); + }, tpTime * 20L); + + } else if (tpaRequest.getType() == TpaType.TPA_THERE) { + target.sendMessage(Component.text("TPA request to ").color(TextColor.fromHexString("#55FF55")) + .append(Component.text(player.getName()).color(TextColor.fromHexString("#00AA00"))) + .append(Component.text(" has been accepted.\nYou will be teleported in ").color(TextColor.fromHexString("#55FF55"))) + .append(Component.text(tpTime).color(TextColor.fromHexString("#00AA00"))) + .append(Component.text(" seconds.").color(TextColor.fromHexString("#55FF55")))); + + player.sendMessage(Component.text("The TPA request from ").color(TextColor.fromHexString("#55FF55")) + .append(Component.text(target.getName()).color(TextColor.fromHexString("#00AA00"))) + .append(Component.text(" has been accepted.\nThey will be teleported to you in ").color(TextColor.fromHexString("#55FF55"))) + .append(Component.text(tpTime).color(TextColor.fromHexString("#00AA00"))) + .append(Component.text(" seconds.").color(TextColor.fromHexString("#55FF55")))); + + Bukkit.getScheduler().runTaskLater(SystemHomes.plugin, () -> { + target.teleport(player); + }, tpTime * 20L); + } + } + + @CommandAlias("tpdeny|tpno") + @SuppressWarnings("DuplicatedCode") + public void tpdeny(CommandSender sender, String[] args) { + if (!(sender instanceof Player player)) { + sender.sendMessage(Component.text("Only a player can run this command.").color(TextColor.fromHexString("#FF5555"))); + return; + } + + TpaRequest tpaRequest = null; + for(TpaRequest r : tpaRequests) { + if(r.getTarget().equals(player.getUniqueId())) { + tpaRequest = r; + break; + } + } + if(tpaRequest == null){ + player.sendMessage(Component.text("You don't have any outgoing TPA requests.").color(TextColor.fromHexString("#FF5555"))); + return; + } + Player target = Bukkit.getPlayer(tpaRequest.getRequester()); + OfflinePlayer targetOffline = Bukkit.getOfflinePlayer(tpaRequest.getRequester()); + + tpaRequests.remove(tpaRequest); + + player.sendMessage(Component.text("Declined ").color(TextColor.fromHexString("#FF5555")) + .append(Component.text(targetOffline.getName() == null ? "Unknown" : targetOffline.getName()).color(TextColor.fromHexString("#AA0000"))) + .append(Component.text("'s TPA request.").color(TextColor.fromHexString("#FF5555")))); + + if(target != null){ + target.sendMessage(Component.text(player.getName()).color(TextColor.fromHexString("#AA0000")) + .append(Component.text(" declined your TPA request.").color(TextColor.fromHexString("#FF5555")))); + } + } + + private void deleteTpaAfterDelay(Player player, Player target, int requestTimeout, TpaRequest tpaRequest) { + Bukkit.getScheduler().runTaskLater(SystemHomes.plugin, () -> { + if(tpaRequests.remove(tpaRequest)){ + player.sendMessage(Component.text("TPA Request to ").color(TextColor.fromHexString("#FF5555")) + .append(Component.text(target.getName()).color(TextColor.fromHexString("#AA0000"))) + .append(Component.text(" has timed out.").color(TextColor.fromHexString("#FF5555")))); + + target.sendMessage(Component.text("TPA Request from ").color(TextColor.fromHexString("#FF5555")) + .append(Component.text(player.getName()).color(TextColor.fromHexString("#AA0000"))) + .append(Component.text(" has timed out.").color(TextColor.fromHexString("#FF5555")))); + } + }, requestTimeout * 20L); + } + +} diff --git a/src/main/java/moe/sebiann/system/commands/WarpCommands.java b/src/main/java/moe/sebiann/system/commands/WarpCommands.java new file mode 100644 index 0000000..a8fa234 --- /dev/null +++ b/src/main/java/moe/sebiann/system/commands/WarpCommands.java @@ -0,0 +1,195 @@ +package moe.sebiann.system.commands; + +import co.aikar.commands.BaseCommand; +import co.aikar.commands.annotation.CommandAlias; +import co.aikar.commands.annotation.CommandCompletion; +import co.aikar.commands.annotation.CommandPermission; +import moe.sebiann.system.Classes.Location; +import moe.sebiann.system.Classes.Warp; +import moe.sebiann.system.SystemHomes; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.event.HoverEvent; +import net.kyori.adventure.text.format.TextColor; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; + +public class WarpCommands extends BaseCommand { + + List pendingOverwrittenConfirmations = new ArrayList<>(); + + @CommandAlias("setwarp") + @CommandCompletion("@nothing") + @CommandPermission("systemhomes.admin.warps.set") + public void setWarp(CommandSender sender, String[] args) { + if(!(sender instanceof Player player)) { + sender.sendMessage(Component.text("Only a player can run this command.").color(TextColor.fromHexString("#FF5555"))); + return; + } + + if(args.length < 1){ + player.sendMessage(Component.text("Please give a name to this warp.").color(TextColor.fromHexString("#FF5555"))); + return; + } + + String warpPath = "warps." + args[0]; + Warp warp = new Warp( + args[0], + new Location(player.getLocation()) + ); + + if(Warp.containsWarp(warpPath)) { + if(pendingOverwrittenConfirmations.contains(args[0])) { + + try{ + warp.uploadWarp(); + pendingOverwrittenConfirmations.remove(args[0]); + }catch(Exception e) { + player.sendMessage(Component.text("Failed to upload Warp, please try again later.").color(TextColor.fromHexString("#FF5555"))); + return; + } + + player.sendMessage(Component.text("Warp ").color(TextColor.fromHexString("#55FF55")) + .append(Component.text(warp.getWarpName()).color(TextColor.fromHexString("#00AA00"))) + .append(Component.text(" has been overridden!").color(TextColor.fromHexString("#55FF55")))); + return; + } + + pendingOverwrittenConfirmations.add(args[0]); + player.sendMessage(Component.text("Warp ").color(TextColor.fromHexString("#FF5555")) + .append(Component.text(warp.getWarpName()).color(TextColor.fromHexString("#AA0000"))) + .append(Component.text(" already exists! Use: ").color(TextColor.fromHexString("#FF5555"))) + .append(Component.text("/setwarp " + warp.getWarpName()).color(TextColor.fromHexString("#AA0000")) + .hoverEvent(HoverEvent.showText(Component.text("Click this to override this warp!").color(TextColor.fromHexString("#FF5555")))) + .clickEvent(ClickEvent.runCommand("/setwarp " + warp.getWarpName()))) + .append(Component.text(" again to override it!").color(TextColor.fromHexString("#FF5555")))); + return; + } + + try{ + warp.uploadWarp(); + }catch(Exception e) { + player.sendMessage(Component.text("Failed to upload Warp, please try again later.").color(TextColor.fromHexString("#FF5555"))); + return; + } + + player.sendMessage(Component.text("Warp ").color(TextColor.fromHexString("#55FF55")) + .append(Component.text(warp.getWarpName()).color(TextColor.fromHexString("#00AA00"))) + .append(Component.text(" has been set to this location!").color(TextColor.fromHexString("#55FF55")))); + } + + @CommandAlias("delwarp") + @CommandCompletion("@warpNames") + @CommandPermission("systemhomes.admin.warps.delete") + public void delWarp(CommandSender sender, String[] args) { + if(!(sender instanceof Player player)) { + sender.sendMessage(Component.text("Only a player can run this command.").color(TextColor.fromHexString("#FF5555"))); + return; + } + if(args.length < 1) { + player.sendMessage(Component.text("Please put in the warp which you want to delete").color(TextColor.fromHexString("#FF5555"))); + return; + } + + String warpName = args[0].toLowerCase(); + Warp warp; + try{ + warp = Warp.getWarp(warpName); + } catch (RuntimeException e) { + player.sendMessage(Component.text("This warp does not exist.").color(TextColor.fromHexString("#FF5555"))); + return; + } + try{ + warp.deleteWarp(); + }catch (RuntimeException e) { + player.sendMessage(Component.text("This warp could not be deleted, please try again later.").color(TextColor.fromHexString("#FF5555"))); + return; + } + + player.sendMessage(Component.text("Warp ").color(TextColor.fromHexString("#FF5555")) + .append(Component.text(warpName).color(TextColor.fromHexString("#AA0000"))) + .append(Component.text(" has been deleted!").color(TextColor.fromHexString("#FF5555")))); + } + + @CommandAlias("warp") + @CommandCompletion("@warpNames") + public void warp(CommandSender sender, String[] args) { + if (!(sender instanceof Player player)) { + sender.sendMessage(Component.text("Only a player can run this command.").color(TextColor.fromHexString("#FF5555"))); + return; + } + if(args.length < 1) { + player.sendMessage(Component.text("Please input to which warp you want to teleport.").color(TextColor.fromHexString("#FF5555"))); + return; + } + + int delayInSeconds = SystemHomes.plugin.getConfig().getInt("warp.teleport_delay", 2); + + Warp warp; + try{ + warp = Warp.getWarp(args[0].toLowerCase()); + }catch (RuntimeException e){ + player.sendMessage(Component.text("This warp does not exist.").color(TextColor.fromHexString("#FF5555"))); + return; + } + + org.bukkit.Location location = warp.getLocation().toBukkitLocation(); + + player.sendMessage(Component.text("Teleporting you to warp: ").color(TextColor.fromHexString("#55FF55")) + .append(Component.text(warp.getWarpName()).color(TextColor.fromHexString("#00AA00"))) + .append(Component.text(" in " + delayInSeconds + " seconds.").color(TextColor.fromHexString("#55FF55")))); + + Bukkit.getScheduler().runTaskLater(SystemHomes.plugin, () -> { + player.teleport(location); + player.sendMessage(Component.text("Teleported you to your warp: ").color(TextColor.fromHexString("#55FF55")) + .append(Component.text(warp.getWarpName()).color(TextColor.fromHexString("#00AA00")))); + }, delayInSeconds * 20L); + } + + @CommandAlias("warps") + @CommandCompletion("@nothing") + public void warpList(CommandSender sender) { + if (!(sender instanceof Player player)) { + sender.sendMessage(Component.text("Only a player can run this command.").color(TextColor.fromHexString("#FF5555"))); + return; + } + + List warps = Warp.getWarps(); + + Component component = Component.text("The server warps:\n").color(TextColor.fromHexString("#FFAA00")); + for (Warp warp : warps) { + component = component.append(Component.text(warp.getWarpName()).color(TextColor.fromHexString("#FFAA00")) + .clickEvent(ClickEvent.runCommand("/warp " + warp.getWarpName())) + .hoverEvent(HoverEvent.showText(Component.text("Teleport to warp: " + warp.getWarpName()).color(TextColor.fromHexString("#FFAA00"))))); + component = component.append(Component.text(" - ").color(TextColor.fromHexString("#AAAAAA"))); + + String worldName = switch (warp.world) { + case "world" -> "Overworld"; + case "world_nether" -> "Nether"; + case "world_the_end" -> "The End"; + default -> warp.world; + }; + + component = component.append(Component.text("(" + worldName + "; " + (int) warp.x + ", " + (int) warp.y + ", " + (int) warp.z + ")\n").color(TextColor.fromHexString("#55FFFF")) + .clickEvent(ClickEvent.runCommand("/warp " + warp.getWarpName())) + .hoverEvent(HoverEvent.showText(Component.text("Teleport to warp: " + warp.getWarpName()).color(TextColor.fromHexString("#FFAA00"))))); + } + + player.sendMessage(component); + } + + public static List warpNameToString(){ + List warpNameList = new ArrayList<>(); + List warps = Warp.getWarps(); + + for(Warp w : warps){ + warpNameList.add(w.getWarpName()); + } + return warpNameList; + } + +} diff --git a/src/main/java/moe/sebiann/system/commands/home/DelHomeCommand.java b/src/main/java/moe/sebiann/system/commands/home/DelHomeCommand.java deleted file mode 100644 index 5c00f3f..0000000 --- a/src/main/java/moe/sebiann/system/commands/home/DelHomeCommand.java +++ /dev/null @@ -1,59 +0,0 @@ -package moe.sebiann.system.commands.home; - -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; - -import java.io.File; -import java.io.IOException; - -public class DelHomeCommand implements CommandExecutor { - - private final File homesFile; - - public DelHomeCommand(File homesFile) { - this.homesFile = homesFile; - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (sender instanceof Player player) { - // Reload the configuration to reflect recent updates - FileConfiguration homesConfig = YamlConfiguration.loadConfiguration(homesFile); - - if (args.length < 1) { - player.sendMessage("§cPlease specify a home name: /delhome "); - return true; - } - - String homeName = args[0].toLowerCase(); // Normalize the home name - String playerPath = "homes." + player.getUniqueId(); - - // Check if the player has the specified home - if (!homesConfig.contains(playerPath + "." + homeName)) { - player.sendMessage("§cHome '" + homeName + "' does not exist!"); - return true; - } - - // Remove the home from the configuration - homesConfig.set(playerPath + "." + homeName, null); - - // Save the updated file - try { - homesConfig.save(homesFile); - homesConfig = YamlConfiguration.loadConfiguration(homesFile); // Reload the configuration - player.sendMessage("§aHome '" + homeName + "' has been deleted!"); - } catch (IOException e) { - player.sendMessage("§cAn error occurred while deleting the home."); - e.printStackTrace(); - } - - return true; - } - sender.sendMessage("Only players can use this command!"); - return true; - } -} diff --git a/src/main/java/moe/sebiann/system/commands/home/HomeCommand.java b/src/main/java/moe/sebiann/system/commands/home/HomeCommand.java deleted file mode 100644 index e03bfc9..0000000 --- a/src/main/java/moe/sebiann/system/commands/home/HomeCommand.java +++ /dev/null @@ -1,74 +0,0 @@ -package moe.sebiann.system.commands.home; - -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.plugin.java.JavaPlugin; - -import java.io.File; - -public class HomeCommand implements CommandExecutor { - - private final File homesFile; - private final JavaPlugin plugin; - - public HomeCommand(File homesFile, JavaPlugin plugin) { - this.homesFile = homesFile; - this.plugin = plugin; - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (sender instanceof Player player) { - // Reload the configuration to reflect recent updates - FileConfiguration homesConfig = YamlConfiguration.loadConfiguration(homesFile); - String homeName = "home"; // Default to "home" - if (args.length > 0) { - homeName = args[0].toLowerCase(); // Use the specified home name - } - - String path = "homes." + player.getUniqueId() + "." + homeName; - - if (!homesConfig.contains(path)) { - if (args.length == 0) { - player.sendMessage("§cYou must specify a home name or set a default home named 'home'!"); - } else { - player.sendMessage("§cHome '" + homeName + "' does not exist!"); - } - return true; - } - final String finalHomeName = homeName; // Declare as final for use in lambda - String worldName = homesConfig.getString(path + ".world"); - double x = homesConfig.getDouble(path + ".x"); - double y = homesConfig.getDouble(path + ".y"); - double z = homesConfig.getDouble(path + ".z"); - float yaw = (float) homesConfig.getDouble(path + ".yaw"); - float pitch = (float) homesConfig.getDouble(path + ".pitch"); - - if (worldName == null || Bukkit.getWorld(worldName) == null) { - player.sendMessage("§cUnable to teleport: World does not exist."); - return true; - } - - final Location finalHomeLocation = new Location(Bukkit.getWorld(worldName), x, y, z, yaw, pitch); // Final for lambda - - // Read the delay from the config - int delayInSeconds = plugin.getConfig().getInt("home.teleport_delay", 2); // Default to 2 seconds - long delayInTicks = delayInSeconds * 20L; // Convert seconds to ticks - - player.sendMessage("§eTeleporting to '" + finalHomeName + "' in " + delayInSeconds + " seconds..."); - Bukkit.getScheduler().runTaskLater(plugin, () -> { - player.teleport(finalHomeLocation); - player.sendMessage("§aYou have been teleported to '" + finalHomeName + "'!"); - }, delayInTicks); - return true; - } - sender.sendMessage("Only players can use this command!"); - return true; - } -} diff --git a/src/main/java/moe/sebiann/system/commands/home/HomeTabCompleter.java b/src/main/java/moe/sebiann/system/commands/home/HomeTabCompleter.java deleted file mode 100644 index 8c53153..0000000 --- a/src/main/java/moe/sebiann/system/commands/home/HomeTabCompleter.java +++ /dev/null @@ -1,48 +0,0 @@ -package moe.sebiann.system.commands.home; - -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.command.TabCompleter; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; - -import java.io.File; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class HomeTabCompleter implements TabCompleter { - - private final File homesFile; - private FileConfiguration homesConfig; - - public HomeTabCompleter(File homesFile) { - this.homesFile = homesFile; - this.homesConfig = YamlConfiguration.loadConfiguration(homesFile); - } - - @Override - public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { - // Reload the configuration at the beginning - this.homesConfig = YamlConfiguration.loadConfiguration(homesFile); - - if (args.length == 1) { - // Get all warp names for suggestion - var homesSection = (homesConfig.getConfigurationSection("homes") != null ? homesConfig.getConfigurationSection("homes") : homesConfig.createSection("homes")); - if (homesSection != null) { - if (sender instanceof org.bukkit.entity.Player player) { - var playerSection = homesSection.getConfigurationSection(player.getUniqueId().toString()); - if (playerSection != null) { - List homes = new ArrayList<>(playerSection.getKeys(false)); - // Filter based on partial input - String partial = args[0].toLowerCase(); - homes.removeIf(home -> !home.startsWith(partial)); - return homes; - } - } - } - } - - return Collections.emptyList(); // No suggestions - } -} diff --git a/src/main/java/moe/sebiann/system/commands/home/ListHomesCommand.java b/src/main/java/moe/sebiann/system/commands/home/ListHomesCommand.java deleted file mode 100644 index 1d055dd..0000000 --- a/src/main/java/moe/sebiann/system/commands/home/ListHomesCommand.java +++ /dev/null @@ -1,56 +0,0 @@ -package moe.sebiann.system.commands.home; - -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; - -import java.io.File; - -public class ListHomesCommand implements CommandExecutor { - - private final File homesFile; - - public ListHomesCommand(File homesFile) { - this.homesFile = homesFile; - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (sender instanceof Player player) { - // Reload the configuration to reflect recent updates - FileConfiguration homesConfig = YamlConfiguration.loadConfiguration(homesFile); - - String playerPath = "homes." + player.getUniqueId(); - - // Check if the player has any homes - if (!homesConfig.contains(playerPath)) { - player.sendMessage("§cYou don't have any homes set!"); - return true; - } - - // Get the list of home names - var homesSection = homesConfig.getConfigurationSection(playerPath); - if (homesSection == null || homesSection.getKeys(false).isEmpty()) { - player.sendMessage("§cYou don't have any homes set!"); - return true; - } - - // Send the list of home names with dimensions to the player - player.sendMessage("§aYour homes:"); - int totalHomes = 0; // Counter for total homes - for (String homeName : homesSection.getKeys(false)) { - String world = homesConfig.getString(playerPath + "." + homeName + ".world", "Unknown"); - player.sendMessage(" - §e" + homeName + " §7(in §b" + world + "§7)"); - totalHomes++; - } - // Display the total number of homes - player.sendMessage("§aTotal homes: §e" + totalHomes); - return true; - } - sender.sendMessage("Only players can use this command!"); - return true; - } -} diff --git a/src/main/java/moe/sebiann/system/commands/home/SetHomeCommand.java b/src/main/java/moe/sebiann/system/commands/home/SetHomeCommand.java deleted file mode 100644 index ad51c36..0000000 --- a/src/main/java/moe/sebiann/system/commands/home/SetHomeCommand.java +++ /dev/null @@ -1,95 +0,0 @@ -package moe.sebiann.system.commands.home; - -import org.bukkit.Location; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.plugin.java.JavaPlugin; - -import java.io.File; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -public class SetHomeCommand implements CommandExecutor { - - private final File homesFile; - private FileConfiguration homesConfig; - private final JavaPlugin plugin; - private final Map pendingConfirmations = new HashMap<>(); - - public SetHomeCommand(File homesFile, JavaPlugin plugin) { - this.homesFile = homesFile; - this.homesConfig = YamlConfiguration.loadConfiguration(homesFile); - this.plugin = plugin; - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (sender instanceof Player player) { - // Reload the configuration to reflect recent updates - FileConfiguration homesConfig = YamlConfiguration.loadConfiguration(homesFile); - - if (args.length < 1) { - player.sendMessage("§cPlease specify a home name: /sethome "); - return true; - } - - String homeName = args[0].toLowerCase(); // Normalize the home name - String playerPath = "homes." + player.getUniqueId() + "." + homeName; - - // Check if the home already exists - if (homesConfig.contains(playerPath)) { - // If confirmation is pending, override the home - if (pendingConfirmations.containsKey(player.getUniqueId()) && - pendingConfirmations.get(player.getUniqueId()).equals(homeName)) { - - pendingConfirmations.remove(player.getUniqueId()); - saveHome(player, homeName); - player.sendMessage("§aHome '" + homeName + "' has been overridden!"); - return true; - } - - // Prompt for confirmation - pendingConfirmations.put(player.getUniqueId(), homeName); - player.sendMessage("§cA home named '" + homeName + "' already exists. Use /sethome again to override it."); - return true; - } - - // Save the home if it doesn't already exist - saveHome(player, homeName); - player.sendMessage("§aHome '" + homeName + "' has been set!"); - return true; - } - - sender.sendMessage("Only players can use this command!"); - return true; - } - - private void saveHome(Player player, String homeName) { - Location location = player.getLocation(); - String path = "homes." + player.getUniqueId() + "." + homeName; - - homesConfig.set(path + ".world", location.getWorld().getName()); - homesConfig.set(path + ".x", location.getX()); - homesConfig.set(path + ".y", location.getY()); - homesConfig.set(path + ".z", location.getZ()); - homesConfig.set(path + ".yaw", location.getYaw()); - homesConfig.set(path + ".pitch", location.getPitch()); - - saveHomesFile(); - } - private void saveHomesFile() { - try { - homesConfig.save(homesFile); - homesConfig = YamlConfiguration.loadConfiguration(homesFile); // Reload the configuration - } catch (IOException e) { - plugin.getLogger().severe("Could not save homes.yml file!"); - e.printStackTrace(); - } - } -} \ No newline at end of file diff --git a/src/main/java/moe/sebiann/system/commands/tpa/TpAcceptCommand.java b/src/main/java/moe/sebiann/system/commands/tpa/TpAcceptCommand.java deleted file mode 100644 index abb149f..0000000 --- a/src/main/java/moe/sebiann/system/commands/tpa/TpAcceptCommand.java +++ /dev/null @@ -1,102 +0,0 @@ -package moe.sebiann.system.commands.tpa; - -import org.bukkit.Bukkit; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.bukkit.plugin.java.JavaPlugin; - -public class TpAcceptCommand implements CommandExecutor { - - private final TpaManager tpaManager; - private final JavaPlugin plugin; - - public TpAcceptCommand(TpaManager tpaManager, JavaPlugin plugin) { - this.tpaManager = tpaManager; - this.plugin = plugin; - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (sender instanceof Player recipient) { - if (tpaManager.hasTpaRequest(recipient.getUniqueId())) { - handleTpaRequest(recipient); - } else if (tpaManager.hasTpahereRequest(recipient.getUniqueId())) { - handleTpahereRequest(recipient); - } else { - recipient.sendMessage("§cYou don't have any teleport requests!"); - } - return true; - } - - sender.sendMessage("Only players can use this command!"); - return true; - } - - private void handleTpaRequest(Player recipient) { - Player requester = Bukkit.getPlayer(tpaManager.getTpaRequester(recipient.getUniqueId())); - if (requester == null || !requester.isOnline()) { - recipient.sendMessage("§cThe player who sent the request is no longer online."); - tpaManager.removeTpaRequest(recipient.getUniqueId()); - return; - } - - tpaManager.removeTpaRequest(recipient.getUniqueId()); - - // Configurable delay - int delayInSeconds = plugin.getConfig().getInt("tpa.teleport_delay", 2); - long delayInTicks = delayInSeconds * 20L; - - // Countdown task - final int[] secondsLeft = {delayInSeconds}; // Using an array to modify inside lambda - int taskId = Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, () -> { - if (secondsLeft[0] > 0) { - recipient.sendMessage("§eTeleporting " + requester.getName() + " to you in " + secondsLeft[0] + " second(s)..."); - requester.sendMessage("§eTeleporting to " + recipient.getName() + " in " + secondsLeft[0] + " second(s)..."); - secondsLeft[0]--; - } - }, 0L, 20L); // Repeats every second - - // Final teleportation task - Bukkit.getScheduler().runTaskLater(plugin, () -> { - Bukkit.getScheduler().cancelTask(taskId); // Stop the countdown - requester.teleport(recipient.getLocation()); - recipient.sendMessage("§a" + requester.getName() + " has been teleported to you!"); - requester.sendMessage("§aYou have been teleported to " + recipient.getName() + "!"); - }, delayInTicks); - } - - private void handleTpahereRequest(Player recipient) { - Player requester = Bukkit.getPlayer(tpaManager.getTpahereRequester(recipient.getUniqueId())); - if (requester == null || !requester.isOnline()) { - recipient.sendMessage("§cThe player who sent the request is no longer online."); - tpaManager.removeTpahereRequest(recipient.getUniqueId()); - return; - } - - tpaManager.removeTpahereRequest(recipient.getUniqueId()); - - // Configurable delay - int delayInSeconds = plugin.getConfig().getInt("tpa.teleport_delay", 2); - long delayInTicks = delayInSeconds * 20L; - - // Countdown task - final int[] secondsLeft = {delayInSeconds}; // Using an array to modify inside lambda - int taskId = Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, () -> { - if (secondsLeft[0] > 0) { - recipient.sendMessage("§eTeleporting to " + requester.getName() + " in " + secondsLeft[0] + " second(s)..."); - requester.sendMessage("§eTeleporting " + recipient.getName() + " to you in " + secondsLeft[0] + " second(s)..."); - secondsLeft[0]--; - } - }, 0L, 20L); // Repeats every second - - // Final teleportation task - Bukkit.getScheduler().runTaskLater(plugin, () -> { - Bukkit.getScheduler().cancelTask(taskId); // Stop the countdown - recipient.teleport(requester.getLocation()); - recipient.sendMessage("§aYou have been teleported to " + requester.getName() + "!"); - requester.sendMessage("§a" + recipient.getName() + " has teleported to you!"); - }, delayInTicks); - } -} diff --git a/src/main/java/moe/sebiann/system/commands/tpa/TpDenyCommand.java b/src/main/java/moe/sebiann/system/commands/tpa/TpDenyCommand.java deleted file mode 100644 index e9e0073..0000000 --- a/src/main/java/moe/sebiann/system/commands/tpa/TpDenyCommand.java +++ /dev/null @@ -1,38 +0,0 @@ -package moe.sebiann.system.commands.tpa; - -import org.bukkit.Bukkit; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -public class TpDenyCommand implements CommandExecutor { - - private final TpaManager tpaManager; - - public TpDenyCommand(TpaManager tpaManager) { - this.tpaManager = tpaManager; - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (sender instanceof Player recipient) { - if (!tpaManager.hasTpaRequest(recipient.getUniqueId())) { - recipient.sendMessage("§cYou don't have any teleport requests!"); - return true; - } - - Player requester = Bukkit.getPlayer(tpaManager.getTpaRequester(recipient.getUniqueId())); - if (requester != null && requester.isOnline()) { - requester.sendMessage("§cYour teleport request to " + recipient.getName() + " was denied."); - } - - tpaManager.removeTpaRequest(recipient.getUniqueId()); - recipient.sendMessage("§aYou denied the teleport request."); - return true; - } - - sender.sendMessage("Only players can use this command!"); - return true; - } -} diff --git a/src/main/java/moe/sebiann/system/commands/tpa/TpaCommand.java b/src/main/java/moe/sebiann/system/commands/tpa/TpaCommand.java deleted file mode 100644 index 6eea861..0000000 --- a/src/main/java/moe/sebiann/system/commands/tpa/TpaCommand.java +++ /dev/null @@ -1,45 +0,0 @@ -package moe.sebiann.system.commands.tpa; - -import org.bukkit.Bukkit; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -public class TpaCommand implements CommandExecutor { - - private final TpaManager tpaManager; - - public TpaCommand(TpaManager tpaManager) { - this.tpaManager = tpaManager; - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (sender instanceof Player requester) { - if (args.length < 1) { - requester.sendMessage("§cPlease specify a player to teleport to: /tpa "); - return true; - } - - Player recipient = Bukkit.getPlayer(args[0]); - if (recipient == null || !recipient.isOnline()) { - requester.sendMessage("§cPlayer not found or not online!"); - return true; - } - - if (recipient.equals(requester)) { - requester.sendMessage("§cYou cannot send a teleport request to yourself!"); - return true; - } - - tpaManager.addTpaRequest(requester.getUniqueId(), recipient.getUniqueId()); - requester.sendMessage("§aTeleport request sent to " + recipient.getName() + "!"); - recipient.sendMessage("§e" + requester.getName() + " wants to teleport to you. Use /tpaccept or /tpdeny."); - return true; - } - - sender.sendMessage("Only players can use this command!"); - return true; - } -} diff --git a/src/main/java/moe/sebiann/system/commands/tpa/TpaManager.java b/src/main/java/moe/sebiann/system/commands/tpa/TpaManager.java deleted file mode 100644 index 5494b5d..0000000 --- a/src/main/java/moe/sebiann/system/commands/tpa/TpaManager.java +++ /dev/null @@ -1,42 +0,0 @@ -package moe.sebiann.system.commands.tpa; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -public class TpaManager { - private final Map pendingRequests = new HashMap<>(); - private final Map tpahereRequests = new HashMap<>(); - - public void addTpaRequest(UUID requester, UUID recipient) { - pendingRequests.put(recipient, requester); - } - - public UUID getTpaRequester(UUID recipient) { - return pendingRequests.get(recipient); - } - - public void removeTpaRequest(UUID recipient) { - pendingRequests.remove(recipient); - } - - public boolean hasTpaRequest(UUID recipient) { - return pendingRequests.containsKey(recipient); - } - - public void addTpahereRequest(UUID requester, UUID recipient) { - tpahereRequests.put(recipient, requester); - } - - public UUID getTpahereRequester(UUID recipient) { - return tpahereRequests.get(recipient); - } - - public void removeTpahereRequest(UUID recipient) { - tpahereRequests.remove(recipient); - } - - public boolean hasTpahereRequest(UUID recipient) { - return tpahereRequests.containsKey(recipient); - } -} diff --git a/src/main/java/moe/sebiann/system/commands/tpa/TpahereCommand.java b/src/main/java/moe/sebiann/system/commands/tpa/TpahereCommand.java deleted file mode 100644 index 4507268..0000000 --- a/src/main/java/moe/sebiann/system/commands/tpa/TpahereCommand.java +++ /dev/null @@ -1,45 +0,0 @@ -package moe.sebiann.system.commands.tpa; - -import org.bukkit.Bukkit; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -public class TpahereCommand implements CommandExecutor { - - private final TpaManager tpaManager; - - public TpahereCommand(TpaManager tpaManager) { - this.tpaManager = tpaManager; - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (sender instanceof Player requester) { - if (args.length < 1) { - requester.sendMessage("§cPlease specify a player to teleport here: /tpahere "); - return true; - } - - Player recipient = Bukkit.getPlayer(args[0]); - if (recipient == null || !recipient.isOnline()) { - requester.sendMessage("§cPlayer not found or not online!"); - return true; - } - - if (recipient.equals(requester)) { - requester.sendMessage("§cYou cannot send a teleport request to yourself!"); - return true; - } - - tpaManager.addTpahereRequest(requester.getUniqueId(), recipient.getUniqueId()); - requester.sendMessage("§aTeleport request sent to " + recipient.getName() + "!"); - recipient.sendMessage("§e" + requester.getName() + " wants you to teleport to them. Use /tpaccept or /tpdeny."); - return true; - } - - sender.sendMessage("Only players can use this command!"); - return true; - } -} diff --git a/src/main/java/moe/sebiann/system/commands/warp/DelWarpCommand.java b/src/main/java/moe/sebiann/system/commands/warp/DelWarpCommand.java deleted file mode 100644 index ccb253e..0000000 --- a/src/main/java/moe/sebiann/system/commands/warp/DelWarpCommand.java +++ /dev/null @@ -1,55 +0,0 @@ -package moe.sebiann.system.commands.warp; - -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; - -import java.io.File; -import java.io.IOException; - -public class DelWarpCommand implements CommandExecutor { - private final File warpsFile; - - public DelWarpCommand(File warpsFile) { - this.warpsFile = warpsFile; - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (sender instanceof Player player) { - // Reload the configuration to reflect recent updates - FileConfiguration warpsConfig = YamlConfiguration.loadConfiguration(warpsFile); - - if (args.length < 1) { - player.sendMessage("§cPlease specify a warp name: /delwarp "); - return true; - } - - String warpName = args[0].toLowerCase(); // Normalize warp name - String path = "warps." + warpName; - - if (!warpsConfig.contains(path)) { - player.sendMessage("§cWarp '" + warpName + "' does not exist!"); - return true; - } - - warpsConfig.set(path, null); - - try { - warpsConfig.save(warpsFile); - player.sendMessage("§aWarp '" + warpName + "' has been deleted!"); - } catch (IOException e) { - player.sendMessage("§cAn error occurred while deleting the warp."); - e.printStackTrace(); - } - - return true; - } - - sender.sendMessage("Only players can use this command!"); - return true; - } -} diff --git a/src/main/java/moe/sebiann/system/commands/warp/ListWarpsCommand.java b/src/main/java/moe/sebiann/system/commands/warp/ListWarpsCommand.java deleted file mode 100644 index 52c1e62..0000000 --- a/src/main/java/moe/sebiann/system/commands/warp/ListWarpsCommand.java +++ /dev/null @@ -1,44 +0,0 @@ -package moe.sebiann.system.commands.warp; - -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; - -import java.io.File; - -public class ListWarpsCommand implements CommandExecutor { - private final File warpsFile; - - public ListWarpsCommand(File warpsFile) { - this.warpsFile = warpsFile; - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (sender instanceof Player player) { - // Reload the configuration to reflect recent updates - FileConfiguration warpsConfig = YamlConfiguration.loadConfiguration(warpsFile); - - var warpsSection = warpsConfig.getConfigurationSection("warps"); - - if (warpsSection == null || warpsSection.getKeys(false).isEmpty()) { - player.sendMessage("§cNo warps have been set!"); - return true; - } - - player.sendMessage("§aAvailable warps:"); - for (String warpName : warpsSection.getKeys(false)) { - String world = warpsConfig.getString("warps." + warpName + ".world", "Unknown"); - player.sendMessage(" - §e" + warpName + " §7(in §b" + world + "§7)"); - } - - return true; - } - - sender.sendMessage("Only players can use this command!"); - return true; - } -} diff --git a/src/main/java/moe/sebiann/system/commands/warp/SetWarpCommand.java b/src/main/java/moe/sebiann/system/commands/warp/SetWarpCommand.java deleted file mode 100644 index d0749d2..0000000 --- a/src/main/java/moe/sebiann/system/commands/warp/SetWarpCommand.java +++ /dev/null @@ -1,74 +0,0 @@ -package moe.sebiann.system.commands.warp; - -import org.bukkit.Location; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; - -import java.io.File; -import java.io.IOException; -import java.util.Map; -import java.util.HashMap; -import java.util.UUID; - -// SetWarpCommand -public class SetWarpCommand implements CommandExecutor { - private final File warpsFile; - private final Map pendingConfirmations = new HashMap<>(); - - public SetWarpCommand(File warpsFile) { - this.warpsFile = warpsFile; - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (sender instanceof Player player) { - // Reload the configuration to reflect recent updates - FileConfiguration warpsConfig = YamlConfiguration.loadConfiguration(warpsFile); - - if (args.length < 1) { - player.sendMessage("§cPlease specify a warp name: /setwarp "); - return true; - } - - String warpName = args[0].toLowerCase(); // Normalize warp name - Location location = player.getLocation(); - - String path = "warps." + warpName; - - // Confirmation logic - if (warpsConfig.contains(path)) { - if (pendingConfirmations.containsKey(player.getUniqueId()) && - pendingConfirmations.get(player.getUniqueId()).equals(warpName)) { - pendingConfirmations.remove(player.getUniqueId()); - } else { - pendingConfirmations.put(player.getUniqueId(), warpName); - player.sendMessage("§cWarp '" + warpName + "' already exists. Use /setwarp again to override."); - return true; - } - } - - warpsConfig.set(path + ".world", location.getWorld().getName()); - warpsConfig.set(path + ".x", location.getX()); - warpsConfig.set(path + ".y", location.getY()); - warpsConfig.set(path + ".z", location.getZ()); - warpsConfig.set(path + ".yaw", location.getYaw()); - warpsConfig.set(path + ".pitch", location.getPitch()); - - try { - warpsConfig.save(warpsFile); - player.sendMessage("§aWarp '" + warpName + "' has been set!"); - } catch (IOException e) { - player.sendMessage("§cAn error occurred while saving the warp."); - e.printStackTrace(); - } - return true; - } - - sender.sendMessage("Only players can use this command!"); - return true; - } -} diff --git a/src/main/java/moe/sebiann/system/commands/warp/WarpCommand.java b/src/main/java/moe/sebiann/system/commands/warp/WarpCommand.java deleted file mode 100644 index 48b9212..0000000 --- a/src/main/java/moe/sebiann/system/commands/warp/WarpCommand.java +++ /dev/null @@ -1,71 +0,0 @@ -package moe.sebiann.system.commands.warp; - -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.plugin.java.JavaPlugin; - -import java.io.File; - -public class WarpCommand implements CommandExecutor { - private final File warpsFile; - private final JavaPlugin plugin; - - public WarpCommand(File warpsFile, JavaPlugin plugin) { - this.warpsFile = warpsFile; - this.plugin = plugin; - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (sender instanceof Player player) { - // Reload the configuration to reflect recent updates - FileConfiguration warpsConfig = YamlConfiguration.loadConfiguration(warpsFile); - - if (args.length < 1) { - player.sendMessage("§cPlease specify a warp name: /warp "); - return true; - } - - String warpName = args[0].toLowerCase(); // Normalize warp name - String path = "warps." + warpName; - - if (!warpsConfig.contains(path)) { - player.sendMessage("§cWarp '" + warpName + "' does not exist!"); - return true; - } - - String worldName = warpsConfig.getString(path + ".world"); - double x = warpsConfig.getDouble(path + ".x"); - double y = warpsConfig.getDouble(path + ".y"); - double z = warpsConfig.getDouble(path + ".z"); - float yaw = (float) warpsConfig.getDouble(path + ".yaw"); - float pitch = (float) warpsConfig.getDouble(path + ".pitch"); - - if (worldName == null || Bukkit.getWorld(worldName) == null) { - player.sendMessage("§cWarp world does not exist!"); - return true; - } - - Location warpLocation = new Location(Bukkit.getWorld(worldName), x, y, z, yaw, pitch); - // Read the delay from the config - int delayInSeconds = plugin.getConfig().getInt("warp.teleport_delay", 3); // Default to 3 seconds - long delayInTicks = delayInSeconds * 20L; - - player.sendMessage("§eTeleporting to warp '" + warpName + "' in " + delayInSeconds + " seconds..."); - Bukkit.getScheduler().runTaskLater(plugin, () -> { - player.teleport(warpLocation); - player.sendMessage("§aYou have been teleported to warp '" + warpName + "'!"); - }, delayInTicks); - return true; - } - - sender.sendMessage("Only players can use this command!"); - return true; - } -} \ No newline at end of file diff --git a/src/main/java/moe/sebiann/system/commands/warp/WarpTabCompleter.java b/src/main/java/moe/sebiann/system/commands/warp/WarpTabCompleter.java deleted file mode 100644 index 60252c5..0000000 --- a/src/main/java/moe/sebiann/system/commands/warp/WarpTabCompleter.java +++ /dev/null @@ -1,43 +0,0 @@ -package moe.sebiann.system.commands.warp; - -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.command.TabCompleter; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; - -import java.io.File; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class WarpTabCompleter implements TabCompleter { - - private final File warpsFile; - private FileConfiguration warpsConfig; - - public WarpTabCompleter(File warpsFile) { - this.warpsFile = warpsFile; - this.warpsConfig = YamlConfiguration.loadConfiguration(warpsFile); - } - - @Override - public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { - // Reload the configuration at the beginning - this.warpsConfig = YamlConfiguration.loadConfiguration(warpsFile); - - if (args.length == 1) { - // Get all warp names for suggestion - var warpsSection = warpsConfig.getConfigurationSection("warps"); - if (warpsSection != null) { - List warps = new ArrayList<>(warpsSection.getKeys(false)); - // Filter based on partial input - String partial = args[0].toLowerCase(); - warps.removeIf(warp -> !warp.startsWith(partial)); - return warps; - } - } - - return Collections.emptyList(); // No suggestions - } -} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 34113d6..6c11e7c 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -3,4 +3,5 @@ home: warp: teleport_delay: 2 tpa: - teleport_delay: 2 \ No newline at end of file + teleport_delay: 2 + request_timeout: 30 \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index edb362b..b0cacd7 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -3,82 +3,82 @@ version: ${version} main: moe.sebiann.system.SystemHomes api-version: '1.21.4' load: POSTWORLD -authors: [ Sebastian, Beauver ] +authors: [ Sebiann, Beauver ] website: sebiann.moe prefix: SystemHomes -permissions : - systemhomes.home: - description: "Permission to do homes" - default: true - systemhomes.warp: - description: "Permission to warp" - default: true - children: - systemhomes.warp.admin: false - systemhomes.tpa: - description: "Permission to request teleports" - default: true - systemhomes.spawn: - description: "Permission to teleport to spawn" - default: true - systemhomes.admin.reload: - description: "Permission to reload the plugin" - default: false -commands: - systemhomes: - description: "Reload the plugin configuration." - usage: "/systemhomes " - permission: systemhomes.admin.reload - sethome: - description: "Set home" - usage: "/sethome " - permission: systemhomes.home - home: - description: "Teleport home" - usage: "/home " - permission: systemhomes.home - homes: - description: "List all homes" - usage: "/homes" - permission: systemhomes.home - delhome: - description: "delete a home" - usage: "/delhome " - permission: systemhomes.home - setwarp: - description: "Sets a warp at your location." - usage: "/setwarp " - permission: systemhomes.warp.admin - warp: - description: "Teleports you to a warp." - usage: "/warp " - permission: systemhomes.warp - delwarp: - description: "Deletes a specific warp." - usage: "/delwarp " - permission: systemhomes.warp.admin - warps: - description: "Lists all available warps." - usage: "/warps" - permission: systemhomes.warp - tpa: - description: "Request to teleport to another player." - usage: "/tpa " - permission: systemhomes.tpa - tpahere: - description: "Request a player to teleport to you." - usage: "/tpahere " - permission: systemhomes.tpa - tpaccept: - description: "Accept a teleport request." - usage: "/tpaccept" - permission: systemhomes.tpa - tpdeny: - description: "Deny a teleport request." - usage: "/tpdeny" - permission: systemhomes.tpa - spawn: - description: "Teleport to the spawn location." - usage: "/spawn" - permission: systemhomes.spawn -depend: [Vault] # Vault is essential for handling permissions and economy. +#permissions : +# systemhomes.home: +# description: "Permission to do homes" +# default: true +# systemhomes.warp: +# description: "Permission to warp" +# default: true +# children: +# systemhomes.warp.admin: false +# systemhomes.tpa: +# description: "Permission to request teleports" +# default: true +# systemhomes.spawn: +# description: "Permission to teleport to spawn" +# default: true +# systemhomes.admin.reload: +# description: "Permission to reload the plugin" +# default: false +#commands: +# systemhomes: +# description: "Reload the plugin configuration." +# usage: "/systemhomes " +# permission: systemhomes.admin.reload +# sethome: +# description: "Set home" +# usage: "/sethome " +# permission: systemhomes.home +# home: +# description: "Teleport home" +# usage: "/home " +# permission: systemhomes.home +# homes: +# description: "List all homes" +# usage: "/homes" +# permission: systemhomes.home +# delhome: +# description: "delete a home" +# usage: "/delhome " +# permission: systemhomes.home +# setwarp: +# description: "Sets a warp at your location." +# usage: "/setwarp " +# permission: systemhomes.warp.admin +# warp: +# description: "Teleports you to a warp." +# usage: "/warp " +# permission: systemhomes.warp +# delwarp: +# description: "Deletes a specific warp." +# usage: "/delwarp " +# permission: systemhomes.warp.admin +# warps: +# description: "Lists all available warps." +# usage: "/warps" +# permission: systemhomes.warp +# tpa: +# description: "Request to teleport to another player." +# usage: "/tpa " +# permission: systemhomes.tpa +# tpahere: +# description: "Request a player to teleport to you." +# usage: "/tpahere " +# permission: systemhomes.tpa +# tpaccept: +# description: "Accept a teleport request." +# usage: "/tpaccept" +# permission: systemhomes.tpa +# tpdeny: +# description: "Deny a teleport request." +# usage: "/tpdeny" +# permission: systemhomes.tpa +# spawn: +# description: "Teleport to the spawn location." +# usage: "/spawn" +# permission: systemhomes.spawn +# depend: [Vault] \ No newline at end of file