Use luckperms for permissions

This commit is contained in:
NotAlexNoyle committed 2025-06-27 15:31:41 -04:00
1 parent 0ec40052bb
commit 290ad0ef1e
5 files changed
+169 -142

No files matched your search

+14 -11
View File
@@ -1,9 +1,10 @@
plugins {
id("java")
id("java-library")
id("com.diffplug.spotless") version "7.0.4"
id("com.gradleup.shadow") version "8.3.6"
eclipse
id("java") // Tell gradle this is a java project.
id("java-library") // Import helper for source-based libraries.
id("com.diffplug.spotless") version "7.0.4" // Import auto-formatter.
id("com.gradleup.shadow") version "8.3.6" // Import shadow API.
eclipse // Import eclipse plugin for IDE integration.
id("io.freefair.lombok") version "8.13.1" // Automatic lombok support.
}
java { sourceCompatibility = JavaVersion.VERSION_17 }
@@ -25,22 +26,24 @@ repositories {
mavenCentral()
gradlePluginPortal()
maven { url = uri("https://repo.purpurmc.org/snapshots") }
maven {
url = uri("https://repo.codemc.io/repository/maven-public/") // Import the CodeMC Maven Repository.
}
}
dependencies {
compileOnly("org.purpurmc.purpur:purpur-api:1.19.4-R0.1-SNAPSHOT")
compileOnly("org.projectlombok:lombok:1.18.26")
annotationProcessor("org.projectlombok:lombok:1.18.26")
compileOnly("net.luckperms:api:5.4") // Import LuckPerms API.
}
tasks.withType<AbstractArchiveTask>().configureEach {
tasks.withType<AbstractArchiveTask>().configureEach { // Ensure reproducible .jars
isPreserveFileTimestamps = false
isReproducibleFileOrder = true
}
tasks.shadowJar {
exclude("io.github.miniplaceholders.*")
archiveClassifier.set("")
exclude("io.github.miniplaceholders.*") // Exclude the MiniPlaceholders package from being shadowed.
archiveClassifier.set("") // Use empty string instead of null.
minimize()
}
@@ -53,7 +56,7 @@ tasks.jar { archiveClassifier.set("part") }
tasks.withType<JavaCompile>().configureEach {
options.compilerArgs.add("-parameters")
options.compilerArgs.add("-Xlint:deprecation")
options.compilerArgs.add("-Xlint:deprecation") // Triggers deprecation warning messages.
options.encoding = "UTF-8"
options.isFork = true
}
+16 -13
View File
@@ -2,8 +2,8 @@ package spawnog;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.PluginCommand;
import net.luckperms.api.LuckPerms;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import spawnog.commands.SetSpawnCommand;
import spawnog.commands.SpawnCommand;
@@ -15,30 +15,33 @@ public final class SpawnOG extends JavaPlugin {
@Getter
private static SpawnOG instance;
@Getter
private LuckPerms luckPerms;
@Override
public void onEnable() {
instance = this;
saveDefaultConfig();
registerCommand("spawn", new SpawnCommand(), "spawnog.teleport");
registerCommand("setspawn", new SetSpawnCommand(), "spawnog.admin");
RegisteredServiceProvider<LuckPerms> rsp =
getServer().getServicesManager().getRegistration(LuckPerms.class);
if (rsp != null) luckPerms = rsp.getProvider();
register("spawn", new SpawnCommand(), "essentials.spawn");
register("setspawn", new SetSpawnCommand(), "essentials.setspawn");
getServer().getPluginManager().registerEvents(new SpawnListener(), this);
}
@Override
public void onDisable() {
log.info("Plugin disabled.");
}
private void registerCommand(String name, CommandExecutor exec, String perm) {
PluginCommand cmd = getCommand(name);
private void register(String name, Object exec, String perm) {
var cmd = getCommand(name);
if (cmd == null) {
getLogger().severe("Command '" + name + "' is missing from plugin.yml!");
getLogger().severe("Command '" + name + "' missing from plugin.yml!");
getServer().getPluginManager().disablePlugin(this);
return;
}
cmd.setPermission(perm);
cmd.setExecutor(exec);
if (exec instanceof org.bukkit.command.CommandExecutor e) cmd.setExecutor(e);
if (exec instanceof org.bukkit.command.TabCompleter t) cmd.setTabCompleter(t);
}
}
@@ -1,102 +1,92 @@
package spawnog.commands;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.*;
import javax.management.openmbean.InvalidOpenTypeException;
import org.bukkit.Location;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.command.*;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import spawnog.SpawnOG;
public class SetSpawnCommand implements CommandExecutor, TabCompleter {
private final JavaPlugin plugin = SpawnOG.getInstance();
private final FileConfiguration config = this.plugin.getConfig();
private static String locationPath = "general.location";
private final FileConfiguration cfg = SpawnOG.getInstance().getConfig();
private static final Set<String> FLAGS = Set.of("normalize-view", "normalize-position", "unset");
@Override
public boolean onCommand(
@NotNull CommandSender sender,
@NotNull Command command,
@NotNull String commandLabel,
@NotNull String[] args) {
// only allow commands from players
if (!(sender instanceof Player)) return false;
Player player = (Player) sender;
List<String> argsList = Arrays.asList(args);
@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String lbl, @NotNull String[] args) {
// permission check
if (!player.hasPermission(command.getPermission())) {
player.sendMessage(
this.config.getString("locale.missingPermission", "You are lacking the required permissions."));
if (!(sender instanceof Player p)) return false;
if (!p.hasPermission(cmd.getPermission())) {
p.sendMessage(cfg.getString("locale.missingPermission", "You are lacking the required permissions."));
return true;
}
// if unset
if (argsList.contains("unset")) {
this.config.set(locationPath, null);
this.plugin.saveConfig();
player.sendMessage(this.config.getString("locale.spawnSet", "Spawn location updated."));
String group = null;
var flags = new HashSet<String>();
for (String a : args) {
if (FLAGS.contains(a.toLowerCase())) flags.add(a.toLowerCase());
else if (group == null) group = a.toLowerCase();
}
String path = "spawns." + (group == null ? "global" : group) + ".location";
if (flags.contains("unset")) {
cfg.set(path, null);
SpawnOG.getInstance().saveConfig();
p.sendMessage(cfg.getString("locale.spawnSet", "Spawn location updated."));
return true;
}
// get location
Location location = player.getLocation();
Location l = p.getLocation();
// normalize view if necessary
if (argsList.contains("normalize-view")) {
location.setYaw((float) this.getClosestDegree(location.getYaw(), new double[] {-180, -90, 0, 90, 180}));
location.setPitch((float) this.getClosestDegree(location.getPitch(), new double[] {-180, -90, 0, 90, 180}));
if (flags.contains("normalize-view")) {
l.setYaw((float) closest(l.getYaw()));
l.setPitch((float) closest(l.getPitch()));
}
if (flags.contains("normalize-position")) {
l.setX(l.getX() > l.getBlockX() ? l.getBlockX() + .5 : l.getBlockX() - .5);
l.setZ(l.getZ() > l.getBlockZ() ? l.getBlockZ() + .5 : l.getBlockZ() - .5);
l.setY(l.getBlockY());
}
// normalize position if necessary
if (argsList.contains("normalize-position")) {
location.setX(location.getX() > location.blockX() ? location.blockX() + .5 : location.blockX() - .5);
location.setZ(location.getZ() > location.blockZ() ? location.blockZ() + .5 : location.blockZ() - .5);
location.setY(location.blockY()); // no normalizing needed
}
// store location
this.config.set(locationPath, location);
this.plugin.saveConfig();
player.sendMessage(this.config.getString("locale.spawnSet", "Spawn location updated."));
cfg.set(path, l);
SpawnOG.getInstance().saveConfig();
p.sendMessage(cfg.getString("locale.spawnSet", "Spawn location updated."));
return true;
}
@Override
public @Nullable List<String> onTabComplete(
@NotNull CommandSender sender,
@NotNull Command command,
@NotNull String commandLabel,
@NotNull String[] args) {
List<String> completes = new ArrayList<>();
List<String> argsList = Arrays.asList(args);
@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String lbl, @NotNull String[] args) {
if (argsList.contains("unset")) return completes;
var current = Arrays.asList(args);
var out = new ArrayList<String>();
completes.add("normalize-view");
completes.add("normalize-position");
completes.add("unset");
if (args.length <= 1) {
out.addAll(
cfg.getConfigurationSection("spawns") == null
? List.of()
: cfg.getConfigurationSection("spawns").getKeys(false));
}
out.addAll(FLAGS);
return completes.stream().filter(c -> !argsList.contains(c)).toList();
return out.stream()
.filter(s -> !current.contains(s))
.filter(s -> s.startsWith(args[args.length - 1].toLowerCase()))
.toList();
}
private double getClosestDegree(double degree, double[] possibleDegrees) {
if (possibleDegrees.length == 0)
throw new InvalidOpenTypeException("You need to specify at least one possible degree");
return Arrays.stream(possibleDegrees)
private double closest(double d) {
double[] arr = {-180, -90, 0, 90, 180};
if (arr.length == 0) throw new InvalidOpenTypeException();
return Arrays.stream(arr)
.boxed()
.min(Comparator.comparing(d -> Math.abs(d - degree)))
.orElse(possibleDegrees[0]);
.min(Comparator.comparing(a -> Math.abs(a - d)))
.orElse(arr[0]);
}
}
@@ -1,14 +1,12 @@
package spawnog.commands;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
import net.luckperms.api.LuckPerms;
import net.luckperms.api.model.user.User;
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.command.TabCompleter;
import org.bukkit.command.*;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
@@ -16,42 +14,42 @@ import org.jetbrains.annotations.Nullable;
import spawnog.SpawnOG;
public class SpawnCommand implements CommandExecutor, TabCompleter {
private final FileConfiguration config = SpawnOG.getInstance().getConfig();
private static final String LOCATION_PATH = "general.location";
private final SpawnOG plugin = SpawnOG.getInstance();
private final FileConfiguration cfg = plugin.getConfig();
@Override
public boolean onCommand(
@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
Location base = config.getLocation(LOCATION_PATH);
if (base == null) {
sender.sendMessage(config.getString("locale.spawnNotSet", "Server spawn not set."));
return true;
}
Location dest = base.clone();
dest.setYaw(0f);
dest.setPitch(0f);
@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String lbl, @NotNull String[] args) {
if (args.length == 0) {
if (!(sender instanceof Player)) return false;
Player player = (Player) sender;
if (!player.hasPermission(command.getPermission())) {
player.sendMessage(
config.getString("locale.missingPermission", "You are lacking the required permissions."));
if (!(sender instanceof Player p)) return false;
if (!p.hasPermission(cmd.getPermission())) {
p.sendMessage(cfg.getString("locale.missingPermission", "You are lacking the required permissions."));
return true;
}
player.teleportAsync(dest);
Location dest = resolve(p);
if (dest == null) {
sender.sendMessage(cfg.getString("locale.spawnNotSet", "Server spawn not set."));
return true;
}
p.teleportAsync(dest);
return true;
}
if (!sender.hasPermission("spawn.others")) {
sender.sendMessage(
config.getString("locale.missingPermission", "You are lacking the required permissions."));
if (!sender.hasPermission("essentials.spawn.others")) {
sender.sendMessage(cfg.getString("locale.missingPermission", "You are lacking the required permissions."));
return true;
}
Player target = Bukkit.getPlayerExact(args[0]);
if (target == null) {
sender.sendMessage(config.getString("locale.playerNotFound", "Player not found."));
sender.sendMessage(cfg.getString("locale.playerNotFound", "Player not found."));
return true;
}
Location dest = resolve(target);
if (dest == null) {
sender.sendMessage(cfg.getString("locale.spawnNotSet", "Server spawn not set."));
return true;
}
target.teleportAsync(dest);
@@ -60,13 +58,29 @@ public class SpawnCommand implements CommandExecutor, TabCompleter {
@Override
public @Nullable List<String> onTabComplete(
@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (args.length == 1 && sender.hasPermission("spawn.others")) {
@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String lbl, @NotNull String[] args) {
if (args.length == 1 && sender.hasPermission("essentials.spawn.others")) {
return Bukkit.getOnlinePlayers().stream()
.map(Player::getName)
.filter(n -> n.toLowerCase().startsWith(args[0].toLowerCase()))
.collect(Collectors.toList());
}
return new ArrayList<>();
return List.of();
}
private Location resolve(Player p) {
String group = null;
LuckPerms lp = plugin.getLuckPerms();
if (lp != null) {
User u = lp.getUserManager().getUser(p.getUniqueId());
if (u != null) group = u.getPrimaryGroup();
}
if (group != null) {
Location g = cfg.getLocation("spawns." + group.toLowerCase() + ".location");
if (g != null) return g.clone();
}
Location def = cfg.getLocation("spawns.global.location");
return def == null ? null : def.clone();
}
}
@@ -2,40 +2,57 @@ package spawnog.listener;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.*;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import spawnog.SpawnOG;
public class SpawnListener implements Listener {
private Location spawn() {
return SpawnOG.getInstance().getConfig().getLocation("general.location");
private final SpawnOG plugin = SpawnOG.getInstance();
@EventHandler
public void onJoin(PlayerJoinEvent e) {
Player p = e.getPlayer();
boolean first = !p.hasPlayedBefore();
boolean force = plugin.getConfig().getBoolean("spawn-on-join", false);
if (!first && !force) return;
Location dest;
if (first) {
String nb =
plugin.getConfig().getString("newbies.spawnpoint", "newbie").toLowerCase();
dest = plugin.getConfig().getLocation("spawns." + nb + ".location");
if (dest == null) dest = plugin.getConfig().getLocation("spawns.global.location");
} else {
dest = plugin.getConfig().getLocation("spawns.global.location");
}
if (dest != null) p.teleportAsync(dest.clone());
}
@EventHandler
public void onJoin(PlayerJoinEvent event) {
if (!event.getPlayer().hasPlayedBefore()) {
Location s = spawn();
if (s != null) {
Location loc = s.clone();
loc.setYaw(0f);
loc.setPitch(0f);
event.getPlayer().teleportAsync(loc);
public void onRespawn(PlayerRespawnEvent e) {
Player p = e.getPlayer();
boolean atHome = plugin.getConfig().getBoolean("respawn-at-home", true);
if (atHome && (p.getBedSpawnLocation() != null)) return;
if (atHome && plugin.getServer().getPluginManager().isPluginEnabled("Essentials")) {
try {
Object ess = plugin.getServer().getPluginManager().getPlugin("Essentials");
Object user = ess.getClass().getMethod("getUser", Player.class).invoke(ess, p);
Location home = (Location)
user.getClass().getMethod("getHome", String.class).invoke(user, "home");
if (home != null) {
e.setRespawnLocation(home.clone());
return;
}
} catch (Throwable ignored) {
}
}
}
@EventHandler
public void onRespawn(PlayerRespawnEvent event) {
Player p = event.getPlayer();
if (p.getBedSpawnLocation() != null) return;
Location s = spawn();
if (s != null) {
Location loc = s.clone();
loc.setYaw(0f);
loc.setPitch(0f);
event.setRespawnLocation(loc);
}
Location def = plugin.getConfig().getLocation("spawns.global.location");
if (def != null) e.setRespawnLocation(def.clone());
}
}