diff --git a/Jenkinsfile b/Jenkinsfile index b0b0e22..c018d67 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -23,7 +23,8 @@ pipeline { #!/bin/bash chmod +x gradlew - ./gradlew build release + ./gradlew build + ./gradlew release ''' } } diff --git a/build.gradle b/build.gradle index 1de136b..c7d85eb 100644 --- a/build.gradle +++ b/build.gradle @@ -11,12 +11,12 @@ println "Java version: ${JavaVersion.current()}" static def getTime() { SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd-HHmm") - sdf.setTimeZone(TimeZone.getTimeZone("UTC")) + sdf.setTimeZone(TimeZone.getTimeZone("MST")) return sdf.format(new Date()).toString() } // Set version to version property if supplied -String shortVersion = null +String shortVersion = "v1.0" if (hasProperty('ver')) { if (ver.charAt(0) == "v") { shortVersion = ver.substring(1).toUpperCase() @@ -32,7 +32,7 @@ if (shortVersion == null || shortVersion == "") { } else if ((rcIdx = shortVersion.indexOf("-RC-")) != -1) { version = shortVersion.substring(0, rcIdx) + "-SNAPSHOT" } else { - version = shortVersion + version = shortVersion + "-" + getTime() + "-SNAPSHOT" } java { @@ -78,6 +78,9 @@ processResources { filesMatching("**/plugin.yml") { expand ( NAME: rootProject.name, VERSION: version, PACKAGE: project.group.toString() ) } + filesMatching("**/paper-plugin.yml") { + expand( NAME: rootProject.name, VERSION: version, PACKAGE: project.group.toString()) + } } shadowJar { diff --git a/src/main/java/dev/zontreck/ase/AriasServerEssentials.java b/src/main/java/dev/zontreck/ase/AriasServerEssentials.java index 67c9dd3..8d954ce 100644 --- a/src/main/java/dev/zontreck/ase/AriasServerEssentials.java +++ b/src/main/java/dev/zontreck/ase/AriasServerEssentials.java @@ -1,15 +1,64 @@ package dev.zontreck.ase; +import java.util.HashMap; +import java.util.Map; + +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.plugin.java.JavaPlugin; +import com.google.common.eventbus.Subscribe; + import io.papermc.lib.PaperLib; -public class AriasServerEssentials extends JavaPlugin { +public class AriasServerEssentials extends JavaPlugin implements Listener { + private static JavaPlugin plugin; + private static Map cachedPlayerData = new HashMap<>(); + @Override public void onEnable() { + plugin = this; PaperLib.suggestPaper(this); saveDefaultConfig(); reloadConfig(); } + + @Override + public void onDisable() { + plugin = null; + } + + public static JavaPlugin getSelf() { + return plugin; + } + + public static SavedData getPlayerData(String playerID) { + if (!cachedPlayerData.containsKey(playerID)) { + ConfigurationSection cfg = getSelf().getConfig().getConfigurationSection("playerData"); + SavedData data = SavedData.deserialize(cfg.getConfigurationSection(playerID)); + cachedPlayerData.put(playerID, data); + return data; + } else { + // Return cached data + return cachedPlayerData.get(playerID); + } + } + + @Subscribe + public static void onPlayerJoin(PlayerJoinEvent ev) { + getPlayerData(ev.getPlayer().getUniqueId().toString()); // Pre-cache it + } + + @Subscribe + public static void onPlayerLeave(PlayerQuitEvent ev) { + // Save the player's data and remove from object cache + String id = ev.getPlayer().getUniqueId().toString(); + SavedData data = getPlayerData(id); + data.save(id); + + cachedPlayerData.remove(id); + } } diff --git a/src/main/java/dev/zontreck/ase/SavedData.java b/src/main/java/dev/zontreck/ase/SavedData.java new file mode 100644 index 0000000..37225c4 --- /dev/null +++ b/src/main/java/dev/zontreck/ase/SavedData.java @@ -0,0 +1,58 @@ +package dev.zontreck.ase; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.bukkit.configuration.ConfigurationSection; + +import dev.zontreck.ase.homes.Home; + +public class SavedData { + public Map homes; + + public SavedData() { + homes = new HashMap<>(); + } + + public void save(String playerID) { + // Begin processing save action + ConfigurationSection player = AriasServerEssentials.getSelf().getConfig().getConfigurationSection("playerData") + .getConfigurationSection(playerID); + if (player == null) + player = AriasServerEssentials.getSelf().getConfig().getConfigurationSection("playerData") + .createSection(playerID); + + ConfigurationSection homes = player.createSection("homes"); + // Begin serialization + for (Map.Entry entry : this.homes.entrySet()) { + Home home = entry.getValue(); + ConfigurationSection h = homes.createSection(home.getName()); + h.set("name", home.getName()); + h.set("location", home.getLocation()); + + homes.set(home.getName(), h); + } + player.set("homes", homes); + + // Apply to main configuration + AriasServerEssentials.getSelf().getConfig().getConfigurationSection("playerData").set(playerID, player); + AriasServerEssentials.getSelf().saveConfig(); + } + + public static SavedData deserialize(ConfigurationSection section) { + SavedData sd = new SavedData(); + if (section == null) + return sd; + for (String home : section.getConfigurationSection("homes").getKeys(false)) { + ConfigurationSection sect = section.getConfigurationSection("homes").getConfigurationSection(home); + Home h = new Home(); + h.restore(sect); + + sd.homes.put(h.getName(), h); + } + + return sd; + } +} diff --git a/src/main/java/dev/zontreck/ase/commands/CommandRegistry.java b/src/main/java/dev/zontreck/ase/commands/CommandRegistry.java index 37ce3f5..db0ee4e 100644 --- a/src/main/java/dev/zontreck/ase/commands/CommandRegistry.java +++ b/src/main/java/dev/zontreck/ase/commands/CommandRegistry.java @@ -1,10 +1,24 @@ package dev.zontreck.ase.commands; +import com.mojang.brigadier.arguments.StringArgumentType; + import io.papermc.paper.command.brigadier.Commands; public class CommandRegistry { public static void register(Commands cmds) { cmds.register(Commands.literal("homes").requires(x -> x.getSender().hasPermission(HomesCommand.PERMISSION)) .executes(ctx -> HomesCommand.execute(ctx)).build()); + cmds.register(Commands.literal("sethome") + .requires(x -> x.getSender().hasPermission(SetHomeCommand.PERMISSION)) + .executes(ctx -> SetHomeCommand.execute(ctx, "Default")) + .then(Commands.argument("name", StringArgumentType.string()) + .executes(ctx -> SetHomeCommand.execute(ctx, StringArgumentType.getString(ctx, "name")))) + .build()); + cmds.register(Commands.literal("home") + .requires(x -> x.getSender().hasPermission(HomeCommand.PERMISSION)) + .executes(ctx -> HomeCommand.execute(ctx, "Default")) + .then(Commands.argument("name", StringArgumentType.string()) + .executes(ctx -> HomeCommand.execute(ctx, StringArgumentType.getString(ctx, "name")))) + .build()); } } diff --git a/src/main/java/dev/zontreck/ase/commands/HomeCommand.java b/src/main/java/dev/zontreck/ase/commands/HomeCommand.java new file mode 100644 index 0000000..4555920 --- /dev/null +++ b/src/main/java/dev/zontreck/ase/commands/HomeCommand.java @@ -0,0 +1,30 @@ +package dev.zontreck.ase.commands; + +import org.bukkit.entity.Player; + +import com.mojang.brigadier.Command; +import com.mojang.brigadier.context.CommandContext; + +import dev.zontreck.ase.AriasServerEssentials; +import dev.zontreck.ase.SavedData; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import net.md_5.bungee.api.ChatColor; + +public class HomeCommand { + public static final String PERMISSION = "ase.commands.home"; + + public static int execute(CommandContext ctx, String homeName) { + // We can now teleport to the home + Player player = (Player) ctx.getSource().getSender(); + SavedData data = AriasServerEssentials.getPlayerData(player.getUniqueId().toString()); + + if (data.homes.containsKey(homeName)) { + data.homes.get(homeName).apply(player); + player.sendMessage(ChatColor.DARK_GREEN + "Teleporting home..."); + } else { + player.sendMessage(ChatColor.DARK_RED + "No such home could be found"); + } + + return Command.SINGLE_SUCCESS; + } +} diff --git a/src/main/java/dev/zontreck/ase/commands/HomesCommand.java b/src/main/java/dev/zontreck/ase/commands/HomesCommand.java index a705df1..274a938 100644 --- a/src/main/java/dev/zontreck/ase/commands/HomesCommand.java +++ b/src/main/java/dev/zontreck/ase/commands/HomesCommand.java @@ -1,15 +1,41 @@ package dev.zontreck.ase.commands; +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.entity.Player; + import com.mojang.brigadier.Command; import com.mojang.brigadier.context.CommandContext; +import dev.zontreck.ase.AriasServerEssentials; +import dev.zontreck.ase.homes.Home; +import dev.zontreck.ase.utils.PermissionUtils; import io.papermc.paper.command.brigadier.CommandSourceStack; +import net.md_5.bungee.api.ChatColor; public class HomesCommand { public static final String PERMISSION = "ase.commands.homes"; public static int execute(CommandContext ctx) { - ctx.getSource().getSender().sendMessage("TEST MESSAGE"); + // List all Homes in a readable format + Player player = (Player) ctx.getSource().getSender(); + + // Check player's max homes permission + int max = PermissionUtils.getMaxPermission("ase.homes", player); + if (max == -1) { + max = AriasServerEssentials.getSelf().getConfig().getInt("maxHomes"); + } + + player.sendMessage(ChatColor.DARK_GREEN + "You have [" + ChatColor.DARK_PURPLE + + AriasServerEssentials.getPlayerData(player.getUniqueId().toString()).homes.size() + + ChatColor.DARK_GREEN + + "/" + max + "] home(s)"); + + for (Home home : AriasServerEssentials.getPlayerData(player.getUniqueId().toString()).homes.values()) { + player.sendMessage(ChatColor.YELLOW + "Home: " + ChatColor.DARK_GREEN + home.getName()); + } + return Command.SINGLE_SUCCESS; } } diff --git a/src/main/java/dev/zontreck/ase/commands/SetHomeCommand.java b/src/main/java/dev/zontreck/ase/commands/SetHomeCommand.java new file mode 100644 index 0000000..136ca2a --- /dev/null +++ b/src/main/java/dev/zontreck/ase/commands/SetHomeCommand.java @@ -0,0 +1,54 @@ +package dev.zontreck.ase.commands; + +import org.bukkit.entity.Player; + +import com.mojang.brigadier.Command; +import com.mojang.brigadier.context.CommandContext; + +import dev.zontreck.ase.AriasServerEssentials; +import dev.zontreck.ase.SavedData; +import dev.zontreck.ase.homes.Home; +import dev.zontreck.ase.utils.PermissionUtils; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import net.md_5.bungee.api.ChatColor; + +public class SetHomeCommand { + public static final String PERMISSION = "ase.commands.sethome"; + + public static int execute(CommandContext ctx, String homeName) { + // Check player's home count + Player player = (Player) ctx.getSource().getSender(); + SavedData playerData = AriasServerEssentials.getPlayerData(player.getUniqueId().toString()); + int count = playerData.homes.size(); + + // Check player's max homes permission + int max = PermissionUtils.getMaxPermission("ase.homes", player); + if (max == -1) { + max = AriasServerEssentials.getSelf().getConfig().getInt("maxHomes"); + } + boolean canAddNew = !(count >= max); + + boolean isUpdate = playerData.homes.containsKey(homeName); + if (isUpdate) { + // Ignore canAddNew, we're only replacing a home + Home newHome = Home.fromPlayer(player, homeName); + playerData.homes.put(homeName, newHome); + } else { + if (canAddNew) { + Home newHome = Home.fromPlayer(player, homeName); + playerData.homes.put(homeName, newHome); + } else { + player.sendMessage(ChatColor.DARK_RED + "You cannot create any more homes. You are at your maximum of " + + max + " homes."); + } + } + + // Save the homes data + if (isUpdate || canAddNew) { + playerData.save(player.getUniqueId().toString()); + player.sendMessage(ChatColor.DARK_GREEN + "Home has been created or updated."); + } + + return Command.SINGLE_SUCCESS; + } +} diff --git a/src/main/java/dev/zontreck/ase/homes/Home.java b/src/main/java/dev/zontreck/ase/homes/Home.java index bee7991..691411e 100644 --- a/src/main/java/dev/zontreck/ase/homes/Home.java +++ b/src/main/java/dev/zontreck/ase/homes/Home.java @@ -1,6 +1,38 @@ package dev.zontreck.ase.homes; +import org.bukkit.EntityEffect; +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; + public class Home { String homeName; + Location location; + public static Home fromPlayer(Player player, String homeName) { + Home h = new Home(); + + h.homeName = homeName; + h.location = player.getLocation(); + + return h; + } + + public void restore(ConfigurationSection section) { + homeName = section.getString("name"); + location = section.getLocation("location"); + } + + public void apply(Player player) { + player.teleport(location); + } + + public String getName() { + return homeName; + } + + public Location getLocation() { + return location; + } } diff --git a/src/main/java/dev/zontreck/ase/utils/PermissionUtils.java b/src/main/java/dev/zontreck/ase/utils/PermissionUtils.java new file mode 100644 index 0000000..d361929 --- /dev/null +++ b/src/main/java/dev/zontreck/ase/utils/PermissionUtils.java @@ -0,0 +1,16 @@ +package dev.zontreck.ase.utils; + +import org.bukkit.entity.Player; + +public class PermissionUtils { + public static int getMaxPermission(String sNode, Player pPlayer) { + int i = 0; + int end = 255; + for (i = 0; i <= end; i++) { + if (pPlayer.isPermissionSet(sNode + "." + i)) { + return i; + } + } + return -1; + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index e69de29..984d904 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -0,0 +1,5 @@ +# Max homes are controlled by permissions, but can be set here too. Set max homes with: ase.homes.[number] +maxHomes: 2 +# DO NOT REMOVE THIS +playerData: + KEEPME: 0 diff --git a/src/main/resources/paper-plugin.yml b/src/main/resources/paper-plugin.yml new file mode 100644 index 0000000..abab4d0 --- /dev/null +++ b/src/main/resources/paper-plugin.yml @@ -0,0 +1,39 @@ +main: ${PACKAGE}.${NAME} +name: ${NAME} +version: "${VERSION}" +api-version: "1.21.1" +bootstrapper: dev.zontreck.ase.Bootstrapper +author: AUTHOR +description: DESCRIPTION +commands: + home: + description: Just click your heels three times. + usage: "- /home [optional:name] -" + homes: + description: Lists all homes + usage: "- /homes -" + sethome: + description: Sets a home position + usage: "- /sethome [optional:name] -" + delhome: + description: Deletes a saved home + usage: "- /delhome [optional:name] -" +permissions: + ase.commands.*: + description: Allow all commands + default: false + children: + ase.commands.home: true + ase.commands.homes: true + ase.commands.home: + description: Allows usage of the /home command + default: true + ase.commands.homes: + description: Allows usage of the /homes command + default: true + ase.commands.sethome: + description: Allows usage of /sethome + default: true + ase.commands.delhome: + description: Allows usage of /delhome + default: true