Move stuff into commons, rename PermissionObject, add more javadocs to api
This commit is contained in:
parent
03450c3339
commit
caf03379f2
@ -4,14 +4,22 @@ import lombok.AccessLevel;
|
|||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import me.lucko.luckperms.api.LuckPermsApi;
|
import me.lucko.luckperms.api.LuckPermsApi;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static access to LuckPerms
|
* Static access to LuckPerms
|
||||||
*/
|
*/
|
||||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
public class LuckPerms {
|
public final class LuckPerms {
|
||||||
|
|
||||||
private static LuckPermsApi api = null;
|
private static LuckPermsApi api = null;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an instance of {@link LuckPermsApi}
|
||||||
|
* @return an api instance
|
||||||
|
* @throws IllegalStateException if the api is not loaded
|
||||||
|
*/
|
||||||
public static LuckPermsApi getApi() {
|
public static LuckPermsApi getApi() {
|
||||||
if (api == null) {
|
if (api == null) {
|
||||||
throw new IllegalStateException("API is not loaded.");
|
throw new IllegalStateException("API is not loaded.");
|
||||||
@ -19,6 +27,15 @@ public class LuckPerms {
|
|||||||
return api;
|
return api;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an instance of {@link LuckPermsApi} safely. Unlike {@link LuckPerms#getApi}, this method will not throw an
|
||||||
|
* {@link IllegalStateException} if the api is not loaded, rather return an empty {@link Optional}.
|
||||||
|
* @return an optional api instance
|
||||||
|
*/
|
||||||
|
public static Optional<LuckPermsApi> getApiSafe() {
|
||||||
|
return Optional.ofNullable(api);
|
||||||
|
}
|
||||||
|
|
||||||
static void registerProvider(LuckPermsApi luckPermsApi) {
|
static void registerProvider(LuckPermsApi luckPermsApi) {
|
||||||
api = luckPermsApi;
|
api = luckPermsApi;
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ import java.util.List;
|
|||||||
* errors and ensure all API interactions to not damage the state of the group.
|
* errors and ensure all API interactions to not damage the state of the group.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public interface Group extends PermissionObject {
|
public interface Group extends PermissionHolder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the name of the group
|
* @return the name of the group
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
package me.lucko.luckperms.api;
|
package me.lucko.luckperms.api;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A wrapper class for platform logger instances.
|
||||||
|
* Bukkit/Bungee both use java.util.logging, and Sponge uses org.slf4j. This class wraps those classes so the commons
|
||||||
|
* module can access a logger.
|
||||||
|
*/
|
||||||
public interface Logger {
|
public interface Logger {
|
||||||
|
|
||||||
void info(String s);
|
void info(String s);
|
||||||
|
@ -2,23 +2,81 @@ package me.lucko.luckperms.api;
|
|||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The root Api interface in LuckPerms
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public interface LuckPermsApi {
|
public interface LuckPermsApi {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules an update task to run
|
||||||
|
*/
|
||||||
void runUpdateTask();
|
void runUpdateTask();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the version of the plugin running on the platform
|
||||||
|
*/
|
||||||
String getVersion();
|
String getVersion();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a wrapped {@link Datastore} instance, with somewhat limited access
|
||||||
|
* @return a datastore instance
|
||||||
|
*/
|
||||||
Datastore getDatastore();
|
Datastore getDatastore();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the {@link Logger} wrapping used by the platform
|
||||||
|
* @return the logger instance
|
||||||
|
*/
|
||||||
Logger getLogger();
|
Logger getLogger();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a wrapped user object from the user storage
|
||||||
|
* @param uuid the uuid of the user to get
|
||||||
|
* @return a {@link User} object, if one matching the uuid is loaded, or null if not
|
||||||
|
*/
|
||||||
User getUser(UUID uuid);
|
User getUser(UUID uuid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a wrapped user object from the user storage
|
||||||
|
* @param name the username of the user to get
|
||||||
|
* @return a a {@link User} object, if one matching the uuid is loaded, or null if not
|
||||||
|
*/
|
||||||
User getUser(String name);
|
User getUser(String name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a user is loaded in memory
|
||||||
|
* @param uuid the uuid to check for
|
||||||
|
* @return true if the user is loaded
|
||||||
|
*/
|
||||||
boolean isUserLoaded(UUID uuid);
|
boolean isUserLoaded(UUID uuid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a wrapped group object from the group storage
|
||||||
|
* @param name the name of the group to get
|
||||||
|
* @return a {@link Group} object, if one matching the name exists, or null if not
|
||||||
|
*/
|
||||||
Group getGroup(String name);
|
Group getGroup(String name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a group is loaded in memory
|
||||||
|
* @param name the name to check for
|
||||||
|
* @return true if the group is loaded
|
||||||
|
*/
|
||||||
boolean isGroupLoaded(String name);
|
boolean isGroupLoaded(String name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a wrapped track object from the track storage
|
||||||
|
* @param name the name of the track to get
|
||||||
|
* @return a {@link Track} object, if one matching the name exists, or null if not
|
||||||
|
*/
|
||||||
Track getTrack(String name);
|
Track getTrack(String name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a track is loaded in memory
|
||||||
|
* @param name the name to check for
|
||||||
|
* @return true if the track is loaded
|
||||||
|
*/
|
||||||
boolean isTrackLoaded(String name);
|
boolean isTrackLoaded(String name);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,12 +7,12 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper interface for internal PermissionObject (user/group) instances
|
* Wrapper interface for internal PermissionHolder (user/group) instances
|
||||||
* The implementations of this interface limit access to the object and add parameter checks to further prevent
|
* The implementations of this interface limit access to the object and add parameter checks to further prevent
|
||||||
* errors and ensure all API interactions to not damage the state of the object.
|
* errors and ensure all API interactions to not damage the state of the object.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public interface PermissionObject {
|
public interface PermissionHolder {
|
||||||
|
|
||||||
String getObjectName();
|
String getObjectName();
|
||||||
|
|
@ -12,7 +12,7 @@ import java.util.UUID;
|
|||||||
* errors and ensure all API interactions to not damage the state of the user.
|
* errors and ensure all API interactions to not damage the state of the user.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public interface User extends PermissionObject {
|
public interface User extends PermissionHolder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the users Mojang assigned unique id
|
* @return the users Mojang assigned unique id
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
package me.lucko.luckperms.exceptions;
|
package me.lucko.luckperms.exceptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown when a permission holding object already has a permission, is already a member of a group, or when a track
|
||||||
|
* already contains a group.
|
||||||
|
*/
|
||||||
public class ObjectAlreadyHasException extends Exception {
|
public class ObjectAlreadyHasException extends Exception {
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
package me.lucko.luckperms.exceptions;
|
package me.lucko.luckperms.exceptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown when a permission holding object does not already have a permission, is not already a member of a group,
|
||||||
|
* or when a track doesn't contain a group.
|
||||||
|
*/
|
||||||
public class ObjectLacksException extends Exception {
|
public class ObjectLacksException extends Exception {
|
||||||
}
|
}
|
||||||
|
@ -82,5 +82,19 @@
|
|||||||
<version>1.5</version>
|
<version>1.5</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- HikariCP -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.zaxxer</groupId>
|
||||||
|
<artifactId>HikariCP</artifactId>
|
||||||
|
<version>2.4.7</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- slf4j library -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-simple</artifactId>
|
||||||
|
<version>1.7.9</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
@ -1,49 +1,43 @@
|
|||||||
package me.lucko.luckperms;
|
package me.lucko.luckperms;
|
||||||
|
|
||||||
import me.lucko.luckperms.commands.CommandManager;
|
import me.lucko.luckperms.commands.CommandManager;
|
||||||
import me.lucko.luckperms.commands.Sender;
|
import me.lucko.luckperms.commands.SenderFactory;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
import org.bukkit.command.CommandExecutor;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.command.TabExecutor;
|
import org.bukkit.command.TabExecutor;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
class BukkitCommand extends CommandManager implements CommandExecutor, TabExecutor {
|
class BukkitCommand extends CommandManager implements CommandExecutor, TabExecutor {
|
||||||
|
private static final Factory FACTORY = new Factory();
|
||||||
|
|
||||||
BukkitCommand(LuckPermsPlugin plugin) {
|
BukkitCommand(LuckPermsPlugin plugin) {
|
||||||
super(plugin);
|
super(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||||
return onCommand(makeSender(sender), label, Arrays.asList(args));
|
return onCommand(FACTORY.wrap(sender), label, Arrays.asList(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> onTabComplete(CommandSender sender, Command command, String label, String[] args) {
|
public List<String> onTabComplete(CommandSender sender, Command command, String label, String[] args) {
|
||||||
return onTabComplete(makeSender(sender), Arrays.asList(args));
|
return onTabComplete(FACTORY.wrap(sender), Arrays.asList(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Sender makeSender(CommandSender sender) {
|
private static class Factory extends SenderFactory<CommandSender> {
|
||||||
return new Sender() {
|
|
||||||
final WeakReference<CommandSender> cs = new WeakReference<>(sender);
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendMessage(String s) {
|
protected void sendMessage(CommandSender sender, String s) {
|
||||||
final CommandSender c = cs.get();
|
sender.sendMessage(s);
|
||||||
if (c != null) {
|
|
||||||
c.sendMessage(s);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasPermission(String node) {
|
protected boolean hasPermission(CommandSender sender, String node) {
|
||||||
final CommandSender c = cs.get();
|
return sender.hasPermission(node);
|
||||||
return c != null && c.hasPermission(node);
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
64
bukkit/src/main/java/me/lucko/luckperms/BukkitListener.java
Normal file
64
bukkit/src/main/java/me/lucko/luckperms/BukkitListener.java
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package me.lucko.luckperms;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.constants.Message;
|
||||||
|
import me.lucko.luckperms.users.BukkitUser;
|
||||||
|
import me.lucko.luckperms.users.User;
|
||||||
|
import me.lucko.luckperms.utils.AbstractListener;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.*;
|
||||||
|
|
||||||
|
class BukkitListener extends AbstractListener implements Listener {
|
||||||
|
private final LPBukkitPlugin plugin;
|
||||||
|
|
||||||
|
BukkitListener(LPBukkitPlugin plugin) {
|
||||||
|
super(plugin);
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerPreLogin(AsyncPlayerPreLoginEvent e) {
|
||||||
|
if (!plugin.getDatastore().isAcceptingLogins()) {
|
||||||
|
// Datastore is disabled, prevent players from joining the server
|
||||||
|
e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, Message.LOADING_ERROR.toString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
onAsyncLogin(e.getUniqueId(), e.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerLogin(PlayerLoginEvent e) {
|
||||||
|
final Player player = e.getPlayer();
|
||||||
|
final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(player.getUniqueId()));
|
||||||
|
|
||||||
|
if (user == null) {
|
||||||
|
e.disallow(PlayerLoginEvent.Result.KICK_OTHER, Message.LOADING_ERROR.toString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user instanceof BukkitUser) {
|
||||||
|
BukkitUser u = (BukkitUser) user;
|
||||||
|
u.setAttachment(player.addAttachment(plugin));
|
||||||
|
}
|
||||||
|
|
||||||
|
user.refreshPermissions();
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerJoin(PlayerJoinEvent e) {
|
||||||
|
// Refresh permissions again
|
||||||
|
refreshPlayer(e.getPlayer().getUniqueId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerChangedWorld(PlayerChangedWorldEvent e) {
|
||||||
|
refreshPlayer(e.getPlayer().getUniqueId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerQuit(PlayerQuitEvent e) {
|
||||||
|
onLeave(e.getPlayer().getUniqueId());
|
||||||
|
}
|
||||||
|
}
|
@ -5,12 +5,12 @@ import me.lucko.luckperms.api.Logger;
|
|||||||
import me.lucko.luckperms.api.LuckPermsApi;
|
import me.lucko.luckperms.api.LuckPermsApi;
|
||||||
import me.lucko.luckperms.api.implementation.ApiProvider;
|
import me.lucko.luckperms.api.implementation.ApiProvider;
|
||||||
import me.lucko.luckperms.api.vault.VaultHook;
|
import me.lucko.luckperms.api.vault.VaultHook;
|
||||||
|
import me.lucko.luckperms.constants.Message;
|
||||||
import me.lucko.luckperms.data.Datastore;
|
import me.lucko.luckperms.data.Datastore;
|
||||||
import me.lucko.luckperms.data.methods.FlatfileDatastore;
|
import me.lucko.luckperms.data.methods.FlatfileDatastore;
|
||||||
import me.lucko.luckperms.data.methods.MySQLDatastore;
|
import me.lucko.luckperms.data.methods.MySQLDatastore;
|
||||||
import me.lucko.luckperms.data.methods.SQLiteDatastore;
|
import me.lucko.luckperms.data.methods.SQLiteDatastore;
|
||||||
import me.lucko.luckperms.groups.GroupManager;
|
import me.lucko.luckperms.groups.GroupManager;
|
||||||
import me.lucko.luckperms.listeners.PlayerListener;
|
|
||||||
import me.lucko.luckperms.runnables.UpdateTask;
|
import me.lucko.luckperms.runnables.UpdateTask;
|
||||||
import me.lucko.luckperms.tracks.TrackManager;
|
import me.lucko.luckperms.tracks.TrackManager;
|
||||||
import me.lucko.luckperms.users.BukkitUserManager;
|
import me.lucko.luckperms.users.BukkitUserManager;
|
||||||
@ -47,7 +47,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
|||||||
|
|
||||||
// register events
|
// register events
|
||||||
PluginManager pm = Bukkit.getPluginManager();
|
PluginManager pm = Bukkit.getPluginManager();
|
||||||
pm.registerEvents(new PlayerListener(this), this);
|
pm.registerEvents(new BukkitListener(this), this);
|
||||||
|
|
||||||
// register commands
|
// register commands
|
||||||
getLog().info("Registering commands...");
|
getLog().info("Registering commands...");
|
||||||
@ -149,8 +149,8 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPlayerStatus(UUID uuid) {
|
public Message getPlayerStatus(UUID uuid) {
|
||||||
return getServer().getPlayer(getUuidCache().getExternalUUID(uuid)) != null ? "&aOnline" : "&cOffline";
|
return getServer().getPlayer(getUuidCache().getExternalUUID(uuid)) != null ? Message.PLAYER_ONLINE : Message.PLAYER_OFFLINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -7,7 +7,7 @@ import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
|||||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||||
import me.lucko.luckperms.groups.Group;
|
import me.lucko.luckperms.groups.Group;
|
||||||
import me.lucko.luckperms.users.User;
|
import me.lucko.luckperms.users.User;
|
||||||
import me.lucko.luckperms.utils.PermissionObject;
|
import me.lucko.luckperms.utils.PermissionHolder;
|
||||||
import net.milkbowl.vault.permission.Permission;
|
import net.milkbowl.vault.permission.Permission;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,7 +33,7 @@ class VaultPermissionHook extends Permission {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean objectHas(String world, PermissionObject object, String permission) {
|
private boolean objectHas(String world, PermissionHolder object, String permission) {
|
||||||
if (object == null) return false;
|
if (object == null) return false;
|
||||||
|
|
||||||
if (world != null && !world.equals("")) {
|
if (world != null && !world.equals("")) {
|
||||||
@ -43,7 +43,7 @@ class VaultPermissionHook extends Permission {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean objectAdd(String world, PermissionObject object, String permission) {
|
private boolean objectAdd(String world, PermissionHolder object, String permission) {
|
||||||
if (object == null) return false;
|
if (object == null) return false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -58,7 +58,7 @@ class VaultPermissionHook extends Permission {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean objectRemove(String world, PermissionObject object, String permission) {
|
private boolean objectRemove(String world, PermissionHolder object, String permission) {
|
||||||
if (object == null) return false;
|
if (object == null) return false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -73,7 +73,7 @@ class VaultPermissionHook extends Permission {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void objectSave(PermissionObject t) {
|
private void objectSave(PermissionHolder t) {
|
||||||
if (t instanceof User) {
|
if (t instanceof User) {
|
||||||
((User) t).refreshPermissions();
|
((User) t).refreshPermissions();
|
||||||
plugin.getDatastore().saveUser(((User) t), aBoolean -> {});
|
plugin.getDatastore().saveUser(((User) t), aBoolean -> {});
|
||||||
|
@ -1,101 +0,0 @@
|
|||||||
package me.lucko.luckperms.listeners;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import me.lucko.luckperms.LPBukkitPlugin;
|
|
||||||
import me.lucko.luckperms.commands.Util;
|
|
||||||
import me.lucko.luckperms.constants.Message;
|
|
||||||
import me.lucko.luckperms.users.BukkitUser;
|
|
||||||
import me.lucko.luckperms.users.User;
|
|
||||||
import me.lucko.luckperms.utils.UuidCache;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.EventHandler;
|
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
import org.bukkit.event.player.*;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class PlayerListener implements Listener {
|
|
||||||
private static final String KICK_MESSAGE = Util.color(Message.PREFIX + "User data could not be loaded. Please contact an administrator.");
|
|
||||||
private final LPBukkitPlugin plugin;
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerPreLogin(AsyncPlayerPreLoginEvent e) {
|
|
||||||
final long startTime = System.currentTimeMillis();
|
|
||||||
if (!plugin.getDatastore().isAcceptingLogins()) {
|
|
||||||
// Datastore is disabled, prevent players from joining the server
|
|
||||||
e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, KICK_MESSAGE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final UuidCache cache = plugin.getUuidCache();
|
|
||||||
if (!cache.isOnlineMode()) {
|
|
||||||
UUID uuid = plugin.getDatastore().getUUID(e.getName());
|
|
||||||
if (uuid != null) {
|
|
||||||
cache.addToCache(e.getUniqueId(), uuid);
|
|
||||||
} else {
|
|
||||||
// No previous data for this player
|
|
||||||
cache.addToCache(e.getUniqueId(), e.getUniqueId());
|
|
||||||
plugin.getDatastore().saveUUIDData(e.getName(), e.getUniqueId(), b -> {});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Online mode, no cache needed. This is just for name -> uuid lookup.
|
|
||||||
plugin.getDatastore().saveUUIDData(e.getName(), e.getUniqueId(), b -> {});
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin.getDatastore().loadOrCreateUser(cache.getUUID(e.getUniqueId()), e.getName());
|
|
||||||
final long time = System.currentTimeMillis() - startTime;
|
|
||||||
if (time >= 1000) {
|
|
||||||
plugin.getLog().warn("Processing login for " + e.getName() + " took " + time + "ms.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerLogin(PlayerLoginEvent e) {
|
|
||||||
final Player player = e.getPlayer();
|
|
||||||
final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(player.getUniqueId()));
|
|
||||||
|
|
||||||
if (user == null) {
|
|
||||||
e.disallow(PlayerLoginEvent.Result.KICK_OTHER, KICK_MESSAGE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (user instanceof BukkitUser) {
|
|
||||||
BukkitUser u = (BukkitUser) user;
|
|
||||||
u.setAttachment(player.addAttachment(plugin));
|
|
||||||
}
|
|
||||||
|
|
||||||
user.refreshPermissions();
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerJoin(PlayerJoinEvent e) {
|
|
||||||
// Refresh permissions again
|
|
||||||
refreshPlayer(e.getPlayer());
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerChangedWorld(PlayerChangedWorldEvent e) {
|
|
||||||
refreshPlayer(e.getPlayer());
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerQuit(PlayerQuitEvent e) {
|
|
||||||
final Player player = e.getPlayer();
|
|
||||||
final UuidCache cache = plugin.getUuidCache();
|
|
||||||
|
|
||||||
// Unload the user from memory when they disconnect;
|
|
||||||
cache.clearCache(player.getUniqueId());
|
|
||||||
|
|
||||||
final User user = plugin.getUserManager().getUser(cache.getUUID(player.getUniqueId()));
|
|
||||||
plugin.getUserManager().unloadUser(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refreshPlayer(Player p) {
|
|
||||||
final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(p.getUniqueId()));
|
|
||||||
if (user != null) {
|
|
||||||
user.refreshPermissions();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -75,6 +75,20 @@
|
|||||||
<version>1.5</version>
|
<version>1.5</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- HikariCP -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.zaxxer</groupId>
|
||||||
|
<artifactId>HikariCP</artifactId>
|
||||||
|
<version>2.4.7</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- slf4j library -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-simple</artifactId>
|
||||||
|
<version>1.7.9</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
package me.lucko.luckperms;
|
package me.lucko.luckperms;
|
||||||
|
|
||||||
import me.lucko.luckperms.commands.CommandManager;
|
import me.lucko.luckperms.commands.CommandManager;
|
||||||
import me.lucko.luckperms.commands.Sender;
|
import me.lucko.luckperms.commands.SenderFactory;
|
||||||
import net.md_5.bungee.api.CommandSender;
|
import net.md_5.bungee.api.CommandSender;
|
||||||
import net.md_5.bungee.api.chat.TextComponent;
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
import net.md_5.bungee.api.plugin.Command;
|
import net.md_5.bungee.api.plugin.Command;
|
||||||
import net.md_5.bungee.api.plugin.TabExecutor;
|
import net.md_5.bungee.api.plugin.TabExecutor;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
class BungeeCommand extends Command implements TabExecutor {
|
class BungeeCommand extends Command implements TabExecutor {
|
||||||
|
private static final Factory FACTORY = new Factory();
|
||||||
private final CommandManager manager;
|
private final CommandManager manager;
|
||||||
|
|
||||||
public BungeeCommand(CommandManager manager) {
|
public BungeeCommand(CommandManager manager) {
|
||||||
@ -20,31 +20,24 @@ class BungeeCommand extends Command implements TabExecutor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(CommandSender sender, String[] args) {
|
public void execute(CommandSender sender, String[] args) {
|
||||||
manager.onCommand(makeSender(sender), "bperms", Arrays.asList(args));
|
manager.onCommand(FACTORY.wrap(sender), "bperms", Arrays.asList(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterable<String> onTabComplete(CommandSender sender, String[] args) {
|
public Iterable<String> onTabComplete(CommandSender sender, String[] args) {
|
||||||
return manager.onTabComplete(makeSender(sender), Arrays.asList(args));
|
return manager.onTabComplete(FACTORY.wrap(sender), Arrays.asList(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Sender makeSender(CommandSender sender) {
|
private static class Factory extends SenderFactory<CommandSender> {
|
||||||
return new Sender() {
|
|
||||||
final WeakReference<CommandSender> cs = new WeakReference<>(sender);
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendMessage(String s) {
|
protected void sendMessage(CommandSender sender, String s) {
|
||||||
final CommandSender c = cs.get();
|
sender.sendMessage(new TextComponent(s));
|
||||||
if (c != null) {
|
|
||||||
c.sendMessage(new TextComponent(s));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasPermission(String node) {
|
protected boolean hasPermission(CommandSender sender, String node) {
|
||||||
final CommandSender c = cs.get();
|
return sender.hasPermission(node);
|
||||||
return c != null && c.hasPermission(node);
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
package me.lucko.luckperms.listeners;
|
package me.lucko.luckperms;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import me.lucko.luckperms.LPBungeePlugin;
|
|
||||||
import me.lucko.luckperms.commands.Util;
|
|
||||||
import me.lucko.luckperms.constants.Message;
|
import me.lucko.luckperms.constants.Message;
|
||||||
import me.lucko.luckperms.users.User;
|
import me.lucko.luckperms.users.User;
|
||||||
|
import me.lucko.luckperms.utils.AbstractListener;
|
||||||
import me.lucko.luckperms.utils.UuidCache;
|
import me.lucko.luckperms.utils.UuidCache;
|
||||||
import net.md_5.bungee.api.chat.TextComponent;
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
import net.md_5.bungee.api.connection.PendingConnection;
|
import net.md_5.bungee.api.connection.PendingConnection;
|
||||||
@ -20,13 +18,15 @@ import java.lang.ref.WeakReference;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@AllArgsConstructor
|
class BungeeListener extends AbstractListener implements Listener {
|
||||||
public class PlayerListener implements Listener {
|
private static final TextComponent WARN_MESSAGE = new TextComponent(Message.LOADING_ERROR.toString());
|
||||||
private static final TextComponent WARN_MESSAGE = new TextComponent(Util.color(
|
|
||||||
Message.PREFIX + "Permissions data could not be loaded. Please contact an administrator.")
|
|
||||||
);
|
|
||||||
private final LPBungeePlugin plugin;
|
private final LPBungeePlugin plugin;
|
||||||
|
|
||||||
|
BungeeListener(LPBungeePlugin plugin) {
|
||||||
|
super(plugin);
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerLogin(LoginEvent e) {
|
public void onPlayerLogin(LoginEvent e) {
|
||||||
/* Delay the login here, as we want to cache UUID data before the player is connected to a backend bukkit server.
|
/* Delay the login here, as we want to cache UUID data before the player is connected to a backend bukkit server.
|
||||||
@ -83,21 +83,11 @@ public class PlayerListener implements Listener {
|
|||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerQuit(PlayerDisconnectEvent e) {
|
public void onPlayerQuit(PlayerDisconnectEvent e) {
|
||||||
final ProxiedPlayer player = e.getPlayer();
|
onLeave(e.getPlayer().getUniqueId());
|
||||||
final UuidCache cache = plugin.getUuidCache();
|
|
||||||
|
|
||||||
// Unload the user from memory when they disconnect;
|
|
||||||
cache.clearCache(player.getUniqueId());
|
|
||||||
|
|
||||||
final User user = plugin.getUserManager().getUser(cache.getUUID(player.getUniqueId()));
|
|
||||||
plugin.getUserManager().unloadUser(user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerServerSwitch(ServerSwitchEvent e) {
|
public void onPlayerServerSwitch(ServerSwitchEvent e) {
|
||||||
final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId()));
|
refreshPlayer(e.getPlayer().getUniqueId());
|
||||||
if (user != null) {
|
|
||||||
user.refreshPermissions();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,11 +4,11 @@ import lombok.Getter;
|
|||||||
import me.lucko.luckperms.api.Logger;
|
import me.lucko.luckperms.api.Logger;
|
||||||
import me.lucko.luckperms.api.implementation.ApiProvider;
|
import me.lucko.luckperms.api.implementation.ApiProvider;
|
||||||
import me.lucko.luckperms.commands.CommandManager;
|
import me.lucko.luckperms.commands.CommandManager;
|
||||||
|
import me.lucko.luckperms.constants.Message;
|
||||||
import me.lucko.luckperms.data.Datastore;
|
import me.lucko.luckperms.data.Datastore;
|
||||||
import me.lucko.luckperms.data.methods.FlatfileDatastore;
|
import me.lucko.luckperms.data.methods.FlatfileDatastore;
|
||||||
import me.lucko.luckperms.data.methods.MySQLDatastore;
|
import me.lucko.luckperms.data.methods.MySQLDatastore;
|
||||||
import me.lucko.luckperms.groups.GroupManager;
|
import me.lucko.luckperms.groups.GroupManager;
|
||||||
import me.lucko.luckperms.listeners.PlayerListener;
|
|
||||||
import me.lucko.luckperms.runnables.UpdateTask;
|
import me.lucko.luckperms.runnables.UpdateTask;
|
||||||
import me.lucko.luckperms.tracks.TrackManager;
|
import me.lucko.luckperms.tracks.TrackManager;
|
||||||
import me.lucko.luckperms.users.BungeeUserManager;
|
import me.lucko.luckperms.users.BungeeUserManager;
|
||||||
@ -39,7 +39,7 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
|
|||||||
configuration = new BungeeConfig(this);
|
configuration = new BungeeConfig(this);
|
||||||
|
|
||||||
// register events
|
// register events
|
||||||
getProxy().getPluginManager().registerListener(this, new PlayerListener(this));
|
getProxy().getPluginManager().registerListener(this, new BungeeListener(this));
|
||||||
|
|
||||||
// register commands
|
// register commands
|
||||||
getLog().info("Registering commands...");
|
getLog().info("Registering commands...");
|
||||||
@ -109,8 +109,8 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPlayerStatus(UUID uuid) {
|
public Message getPlayerStatus(UUID uuid) {
|
||||||
return getProxy().getPlayer(getUuidCache().getExternalUUID(uuid)) != null ? "&aOnline" : "&cOffline";
|
return getProxy().getPlayer(getUuidCache().getExternalUUID(uuid)) != null ? Message.PLAYER_ONLINE : Message.PLAYER_OFFLINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -33,6 +33,27 @@
|
|||||||
<version>1.5</version>
|
<version>1.5</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- HikariCP -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.zaxxer</groupId>
|
||||||
|
<artifactId>HikariCP</artifactId>
|
||||||
|
<version>2.4.7</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- slf4j library -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-simple</artifactId>
|
||||||
|
<version>1.7.9</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- gson -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.gson</groupId>
|
||||||
|
<artifactId>gson</artifactId>
|
||||||
|
<version>2.7</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package me.lucko.luckperms;
|
package me.lucko.luckperms;
|
||||||
|
|
||||||
import me.lucko.luckperms.api.Logger;
|
import me.lucko.luckperms.api.Logger;
|
||||||
|
import me.lucko.luckperms.constants.Message;
|
||||||
import me.lucko.luckperms.data.Datastore;
|
import me.lucko.luckperms.data.Datastore;
|
||||||
import me.lucko.luckperms.groups.GroupManager;
|
import me.lucko.luckperms.groups.GroupManager;
|
||||||
import me.lucko.luckperms.tracks.TrackManager;
|
import me.lucko.luckperms.tracks.TrackManager;
|
||||||
@ -11,6 +12,10 @@ import me.lucko.luckperms.utils.UuidCache;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main internal interface for LuckPerms plugins, allowing the luckperms-common module to bind with the plugin instance.
|
||||||
|
* All plugin platforms implement this interface.
|
||||||
|
*/
|
||||||
public interface LuckPermsPlugin {
|
public interface LuckPermsPlugin {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -65,7 +70,7 @@ public interface LuckPermsPlugin {
|
|||||||
* @param uuid The player's uuid
|
* @param uuid The player's uuid
|
||||||
* @return a formatted status string
|
* @return a formatted status string
|
||||||
*/
|
*/
|
||||||
String getPlayerStatus(UUID uuid);
|
Message getPlayerStatus(UUID uuid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the number of users online on the platform
|
* Gets the number of users online on the platform
|
||||||
|
@ -13,7 +13,7 @@ import java.util.List;
|
|||||||
* Provides a link between {@link Group} and {@link me.lucko.luckperms.groups.Group}
|
* Provides a link between {@link Group} and {@link me.lucko.luckperms.groups.Group}
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class GroupLink extends PermissionObjectLink implements Group {
|
public class GroupLink extends PermissionHolderLink implements Group {
|
||||||
|
|
||||||
@Getter(AccessLevel.PACKAGE)
|
@Getter(AccessLevel.PACKAGE)
|
||||||
private final me.lucko.luckperms.groups.Group master;
|
private final me.lucko.luckperms.groups.Group master;
|
||||||
|
@ -3,7 +3,7 @@ package me.lucko.luckperms.api.implementation.internal;
|
|||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import me.lucko.luckperms.api.PermissionObject;
|
import me.lucko.luckperms.api.PermissionHolder;
|
||||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||||
import me.lucko.luckperms.utils.DateUtil;
|
import me.lucko.luckperms.utils.DateUtil;
|
||||||
@ -14,14 +14,14 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a link between {@link PermissionObject} and {@link me.lucko.luckperms.utils.PermissionObject}
|
* Provides a link between {@link PermissionHolder} and {@link me.lucko.luckperms.utils.PermissionHolder}
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@AllArgsConstructor(access = AccessLevel.PACKAGE)
|
@AllArgsConstructor(access = AccessLevel.PACKAGE)
|
||||||
class PermissionObjectLink implements PermissionObject {
|
class PermissionHolderLink implements PermissionHolder {
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private final me.lucko.luckperms.utils.PermissionObject master;
|
private final me.lucko.luckperms.utils.PermissionHolder master;
|
||||||
|
|
||||||
static String checkServer(String s) {
|
static String checkServer(String s) {
|
||||||
if (Patterns.NON_ALPHA_NUMERIC.matcher(s).find()) {
|
if (Patterns.NON_ALPHA_NUMERIC.matcher(s).find()) {
|
@ -15,7 +15,7 @@ import java.util.UUID;
|
|||||||
* Provides a link between {@link User} and {@link me.lucko.luckperms.users.User}
|
* Provides a link between {@link User} and {@link me.lucko.luckperms.users.User}
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class UserLink extends PermissionObjectLink implements User {
|
public class UserLink extends PermissionHolderLink implements User {
|
||||||
|
|
||||||
@Getter(AccessLevel.PACKAGE)
|
@Getter(AccessLevel.PACKAGE)
|
||||||
private final me.lucko.luckperms.users.User master;
|
private final me.lucko.luckperms.users.User master;
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
package me.lucko.luckperms.api.implementation.internal;
|
package me.lucko.luckperms.api.implementation.internal;
|
||||||
|
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
import me.lucko.luckperms.api.Group;
|
import me.lucko.luckperms.api.Group;
|
||||||
import me.lucko.luckperms.api.Track;
|
import me.lucko.luckperms.api.Track;
|
||||||
import me.lucko.luckperms.api.User;
|
import me.lucko.luckperms.api.User;
|
||||||
|
|
||||||
|
@UtilityClass
|
||||||
class Utils {
|
class Utils {
|
||||||
|
|
||||||
static void checkUser(User user) {
|
static void checkUser(User user) {
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
package me.lucko.luckperms.commands;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
public abstract class SenderFactory<T> {
|
||||||
|
|
||||||
|
protected abstract void sendMessage(T t, String s);
|
||||||
|
protected abstract boolean hasPermission(T t, String node);
|
||||||
|
|
||||||
|
public Sender wrap(T t) {
|
||||||
|
final SenderFactory<T> factory = this;
|
||||||
|
return new Sender() {
|
||||||
|
final WeakReference<T> cs = new WeakReference<>(t);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessage(String s) {
|
||||||
|
final T c = cs.get();
|
||||||
|
if (c != null) {
|
||||||
|
factory.sendMessage(c, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasPermission(String node) {
|
||||||
|
final T c = cs.get();
|
||||||
|
return c != null && factory.hasPermission(c, node);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,9 @@ public enum Message {
|
|||||||
*/
|
*/
|
||||||
PREFIX("&7&l[&b&lL&a&lP&7&l] &c", false),
|
PREFIX("&7&l[&b&lL&a&lP&7&l] &c", false),
|
||||||
EMPTY("%s", true),
|
EMPTY("%s", true),
|
||||||
|
PLAYER_ONLINE("&aOnline", false),
|
||||||
|
PLAYER_OFFLINE("&cOffline", false),
|
||||||
|
LOADING_ERROR("Permissions data could not be loaded. Please contact an administrator.", true),
|
||||||
|
|
||||||
COMMAND_NOT_RECOGNISED("Command not recognised.", true),
|
COMMAND_NOT_RECOGNISED("Command not recognised.", true),
|
||||||
COMMAND_NO_PERMISSION("You do not have permission to use this command!", true),
|
COMMAND_NO_PERMISSION("You do not have permission to use this command!", true),
|
||||||
@ -225,7 +228,7 @@ public enum Message {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return message;
|
return Util.color(showPrefix ? PREFIX + message : message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void send(Sender sender, Object... objects) {
|
public void send(Sender sender, Object... objects) {
|
||||||
|
@ -7,7 +7,7 @@ import me.lucko.luckperms.LuckPermsPlugin;
|
|||||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||||
import me.lucko.luckperms.utils.Patterns;
|
import me.lucko.luckperms.utils.Patterns;
|
||||||
import me.lucko.luckperms.utils.PermissionObject;
|
import me.lucko.luckperms.utils.PermissionHolder;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -15,7 +15,7 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
@ToString(of = {"name"})
|
@ToString(of = {"name"})
|
||||||
@EqualsAndHashCode(of = {"name"}, callSuper = false)
|
@EqualsAndHashCode(of = {"name"}, callSuper = false)
|
||||||
public class Group extends PermissionObject {
|
public class Group extends PermissionHolder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the group
|
* The name of the group
|
||||||
@ -263,7 +263,7 @@ public class Group extends PermissionObject {
|
|||||||
Map<String, Boolean> perms = getPermissions(server, world, null, includeGlobal);
|
Map<String, Boolean> perms = getPermissions(server, world, null, includeGlobal);
|
||||||
return perms.keySet().stream()
|
return perms.keySet().stream()
|
||||||
.filter(s -> Patterns.GROUP_MATCH.matcher(s).matches())
|
.filter(s -> Patterns.GROUP_MATCH.matcher(s).matches())
|
||||||
.map(s -> Patterns.DOT_SPLIT.split(s, 2)[1])
|
.map(s -> Patterns.DOT.split(s, 2)[1])
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
|||||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||||
import me.lucko.luckperms.groups.Group;
|
import me.lucko.luckperms.groups.Group;
|
||||||
import me.lucko.luckperms.utils.Patterns;
|
import me.lucko.luckperms.utils.Patterns;
|
||||||
import me.lucko.luckperms.utils.PermissionObject;
|
import me.lucko.luckperms.utils.PermissionHolder;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -18,7 +18,7 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
@ToString(of = {"uuid"})
|
@ToString(of = {"uuid"})
|
||||||
@EqualsAndHashCode(of = {"uuid"}, callSuper = false)
|
@EqualsAndHashCode(of = {"uuid"}, callSuper = false)
|
||||||
public abstract class User extends PermissionObject {
|
public abstract class User extends PermissionHolder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The users Mojang UUID
|
* The users Mojang UUID
|
||||||
@ -294,7 +294,7 @@ public abstract class User extends PermissionObject {
|
|||||||
Map<String, Boolean> perms = getPermissions(server, world, null, includeGlobal);
|
Map<String, Boolean> perms = getPermissions(server, world, null, includeGlobal);
|
||||||
return perms.keySet().stream()
|
return perms.keySet().stream()
|
||||||
.filter(s -> Patterns.GROUP_MATCH.matcher(s).matches())
|
.filter(s -> Patterns.GROUP_MATCH.matcher(s).matches())
|
||||||
.map(s -> Patterns.DOT_SPLIT.split(s, 2)[1])
|
.map(s -> Patterns.DOT.split(s, 2)[1])
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,62 @@
|
|||||||
|
package me.lucko.luckperms.utils;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import me.lucko.luckperms.LuckPermsPlugin;
|
||||||
|
import me.lucko.luckperms.users.User;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class AbstractListener {
|
||||||
|
private final LuckPermsPlugin plugin;
|
||||||
|
|
||||||
|
protected void onAsyncLogin(UUID u, String username) {
|
||||||
|
final long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
final UuidCache cache = plugin.getUuidCache();
|
||||||
|
if (!cache.isOnlineMode()) {
|
||||||
|
UUID uuid = plugin.getDatastore().getUUID(username);
|
||||||
|
if (uuid != null) {
|
||||||
|
cache.addToCache(u, uuid);
|
||||||
|
} else {
|
||||||
|
// No previous data for this player
|
||||||
|
cache.addToCache(u, u);
|
||||||
|
plugin.getDatastore().saveUUIDData(username, u, b -> {});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Online mode, no cache needed. This is just for name -> uuid lookup.
|
||||||
|
plugin.getDatastore().saveUUIDData(username, u, b -> {});
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.getDatastore().loadOrCreateUser(cache.getUUID(u), username);
|
||||||
|
final long time = System.currentTimeMillis() - startTime;
|
||||||
|
if (time >= 1000) {
|
||||||
|
plugin.getLog().warn("Processing login for " + username + " took " + time + "ms.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onLogin(UUID uuid, String username) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onJoin(UUID uuid, String username) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onLeave(UUID uuid) {
|
||||||
|
final UuidCache cache = plugin.getUuidCache();
|
||||||
|
|
||||||
|
// Unload the user from memory when they disconnect;
|
||||||
|
cache.clearCache(uuid);
|
||||||
|
|
||||||
|
final User user = plugin.getUserManager().getUser(cache.getUUID(uuid));
|
||||||
|
plugin.getUserManager().unloadUser(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void refreshPlayer(UUID uuid) {
|
||||||
|
final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(uuid));
|
||||||
|
if (user != null) {
|
||||||
|
user.refreshPermissions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,11 +6,11 @@ import java.util.regex.Pattern;
|
|||||||
|
|
||||||
@UtilityClass
|
@UtilityClass
|
||||||
public class Patterns {
|
public class Patterns {
|
||||||
public static final Pattern SPACE_SPLIT = Pattern.compile(" ");
|
public static final Pattern SPACE = Pattern.compile(" ");
|
||||||
public static final Pattern SERVER_SPLIT = Pattern.compile("\\/");
|
public static final Pattern SERVER_DELIMITER = Pattern.compile("\\/");
|
||||||
public static final Pattern WORLD_SPLIT = Pattern.compile("\\-");
|
public static final Pattern WORLD_DELIMITER = Pattern.compile("\\-");
|
||||||
public static final Pattern TEMP_SPLIT = Pattern.compile("\\$");
|
public static final Pattern TEMP_DELIMITER = Pattern.compile("\\$");
|
||||||
public static final Pattern DOT_SPLIT = Pattern.compile("\\.");
|
public static final Pattern DOT = Pattern.compile("\\.");
|
||||||
public static final Pattern GROUP_MATCH = Pattern.compile("group\\..*");
|
public static final Pattern GROUP_MATCH = Pattern.compile("group\\..*");
|
||||||
public static final Pattern NON_ALPHA_NUMERIC = Pattern.compile("[^A-Za-z0-9]");
|
public static final Pattern NON_ALPHA_NUMERIC = Pattern.compile("[^A-Za-z0-9]");
|
||||||
public static final Pattern NON_USERNAME = Pattern.compile("[^A-Za-z0-9_]");
|
public static final Pattern NON_USERNAME = Pattern.compile("[^A-Za-z0-9_]");
|
||||||
|
@ -17,7 +17,7 @@ import java.util.stream.Collectors;
|
|||||||
* For example a User or a Group
|
* For example a User or a Group
|
||||||
*/
|
*/
|
||||||
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
|
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
|
||||||
public abstract class PermissionObject {
|
public abstract class PermissionHolder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The UUID of the user / name of the group.
|
* The UUID of the user / name of the group.
|
||||||
@ -53,11 +53,11 @@ public abstract class PermissionObject {
|
|||||||
return b ? toQuery.containsKey(node) && toQuery.get(node) : toQuery.containsKey(node) && !toQuery.get(node);
|
return b ? toQuery.containsKey(node) && toQuery.get(node) : toQuery.containsKey(node) && !toQuery.get(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
node = Patterns.TEMP_SPLIT.split(node)[0];
|
node = Patterns.TEMP_DELIMITER.split(node)[0];
|
||||||
|
|
||||||
for (Map.Entry<String, Boolean> e : toQuery.entrySet()) {
|
for (Map.Entry<String, Boolean> e : toQuery.entrySet()) {
|
||||||
if (e.getKey().contains("$")) {
|
if (e.getKey().contains("$")) {
|
||||||
String[] parts = Patterns.TEMP_SPLIT.split(e.getKey());
|
String[] parts = Patterns.TEMP_DELIMITER.split(e.getKey());
|
||||||
if (parts[0].equalsIgnoreCase(node)) {
|
if (parts[0].equalsIgnoreCase(node)) {
|
||||||
return b ? e.getValue() : !e.getValue();
|
return b ? e.getValue() : !e.getValue();
|
||||||
}
|
}
|
||||||
@ -146,7 +146,7 @@ public abstract class PermissionObject {
|
|||||||
public boolean inheritsPermission(String node, boolean b) {
|
public boolean inheritsPermission(String node, boolean b) {
|
||||||
if (node.contains("/")) {
|
if (node.contains("/")) {
|
||||||
// Use other method
|
// Use other method
|
||||||
final String[] parts = Patterns.SERVER_SPLIT.split(node, 2);
|
final String[] parts = Patterns.SERVER_DELIMITER.split(node, 2);
|
||||||
return inheritsPermission(parts[1], b, parts[0]);
|
return inheritsPermission(parts[1], b, parts[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,7 +163,7 @@ public abstract class PermissionObject {
|
|||||||
public boolean inheritsPermission(String node, boolean b, String server) {
|
public boolean inheritsPermission(String node, boolean b, String server) {
|
||||||
if (server.contains("-")) {
|
if (server.contains("-")) {
|
||||||
// Use other method
|
// Use other method
|
||||||
final String[] parts = Patterns.WORLD_SPLIT.split(server, 2);
|
final String[] parts = Patterns.WORLD_DELIMITER.split(server, 2);
|
||||||
return inheritsPermission(node, b, parts[0], parts[1]);
|
return inheritsPermission(node, b, parts[0], parts[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,7 +306,7 @@ public abstract class PermissionObject {
|
|||||||
|
|
||||||
if (temporary) {
|
if (temporary) {
|
||||||
match = this.nodes.keySet().stream()
|
match = this.nodes.keySet().stream()
|
||||||
.filter(n -> n.contains("$")).filter(n -> Patterns.TEMP_SPLIT.split(n)[0].equalsIgnoreCase(fNode))
|
.filter(n -> n.contains("$")).filter(n -> Patterns.TEMP_DELIMITER.split(n)[0].equalsIgnoreCase(fNode))
|
||||||
.findFirst();
|
.findFirst();
|
||||||
} else {
|
} else {
|
||||||
if (this.nodes.containsKey(fNode)) {
|
if (this.nodes.containsKey(fNode)) {
|
||||||
@ -401,7 +401,7 @@ public abstract class PermissionObject {
|
|||||||
*/
|
*/
|
||||||
public Map<Map.Entry<String, Boolean>, Long> getTemporaryNodes() {
|
public Map<Map.Entry<String, Boolean>, Long> getTemporaryNodes() {
|
||||||
return this.nodes.entrySet().stream().filter(e -> e.getKey().contains("$")).map(e -> {
|
return this.nodes.entrySet().stream().filter(e -> e.getKey().contains("$")).map(e -> {
|
||||||
final String[] parts = Patterns.TEMP_SPLIT.split(e.getKey());
|
final String[] parts = Patterns.TEMP_DELIMITER.split(e.getKey());
|
||||||
final long expiry = Long.parseLong(parts[1]);
|
final long expiry = Long.parseLong(parts[1]);
|
||||||
return new AbstractMap.SimpleEntry<Map.Entry<String, Boolean>, Long>(new AbstractMap.SimpleEntry<>(parts[0], e.getValue()), expiry);
|
return new AbstractMap.SimpleEntry<Map.Entry<String, Boolean>, Long>(new AbstractMap.SimpleEntry<>(parts[0], e.getValue()), expiry);
|
||||||
|
|
||||||
@ -423,7 +423,7 @@ public abstract class PermissionObject {
|
|||||||
public void auditTemporaryPermissions() {
|
public void auditTemporaryPermissions() {
|
||||||
this.nodes.keySet().stream()
|
this.nodes.keySet().stream()
|
||||||
.filter(s -> s.contains("$"))
|
.filter(s -> s.contains("$"))
|
||||||
.filter(s -> DateUtil.shouldExpire(Long.parseLong(Patterns.TEMP_SPLIT.split(s)[1])))
|
.filter(s -> DateUtil.shouldExpire(Long.parseLong(Patterns.TEMP_DELIMITER.split(s)[1])))
|
||||||
.forEach(s -> this.nodes.remove(s));
|
.forEach(s -> this.nodes.remove(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -484,12 +484,12 @@ public abstract class PermissionObject {
|
|||||||
for (Map.Entry<String, Boolean> node : convertTemporaryPerms().entrySet()) {
|
for (Map.Entry<String, Boolean> node : convertTemporaryPerms().entrySet()) {
|
||||||
serverSpecific:
|
serverSpecific:
|
||||||
if (node.getKey().contains("/")) {
|
if (node.getKey().contains("/")) {
|
||||||
String[] parts = Patterns.SERVER_SPLIT.split(node.getKey(), 2);
|
String[] parts = Patterns.SERVER_DELIMITER.split(node.getKey(), 2);
|
||||||
// 0=server(+world) 1=node
|
// 0=server(+world) 1=node
|
||||||
|
|
||||||
// WORLD SPECIFIC
|
// WORLD SPECIFIC
|
||||||
if (parts[0].contains("-")) {
|
if (parts[0].contains("-")) {
|
||||||
String[] serverParts = Patterns.WORLD_SPLIT.split(parts[0], 2);
|
String[] serverParts = Patterns.WORLD_DELIMITER.split(parts[0], 2);
|
||||||
// 0=server 1=world
|
// 0=server 1=world
|
||||||
|
|
||||||
if ((!serverParts[0].equalsIgnoreCase("global") || !includeGlobal) && (!serverParts[0].equalsIgnoreCase(server))) {
|
if ((!serverParts[0].equalsIgnoreCase("global") || !includeGlobal) && (!serverParts[0].equalsIgnoreCase(server))) {
|
||||||
@ -540,7 +540,7 @@ public abstract class PermissionObject {
|
|||||||
// Could be here if the server was set to global.
|
// Could be here if the server was set to global.
|
||||||
String n = node.getKey();
|
String n = node.getKey();
|
||||||
if (n.contains("/")) {
|
if (n.contains("/")) {
|
||||||
n = Patterns.SERVER_SPLIT.split(n, 2)[1];
|
n = Patterns.SERVER_DELIMITER.split(n, 2)[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Patterns.GROUP_MATCH.matcher(n).matches()) {
|
if (Patterns.GROUP_MATCH.matcher(n).matches()) {
|
||||||
@ -556,14 +556,14 @@ public abstract class PermissionObject {
|
|||||||
// If a group is negated at a higher priority, the group should not then be applied at a lower priority
|
// If a group is negated at a higher priority, the group should not then be applied at a lower priority
|
||||||
serverWorldSpecificGroups.entrySet().stream().filter(node -> !node.getValue()).forEach(node -> {
|
serverWorldSpecificGroups.entrySet().stream().filter(node -> !node.getValue()).forEach(node -> {
|
||||||
groupNodes.remove(node.getKey());
|
groupNodes.remove(node.getKey());
|
||||||
groupNodes.remove(Patterns.SERVER_SPLIT.split(node.getKey(), 2)[1]);
|
groupNodes.remove(Patterns.SERVER_DELIMITER.split(node.getKey(), 2)[1]);
|
||||||
serverSpecificGroups.remove(node.getKey());
|
serverSpecificGroups.remove(node.getKey());
|
||||||
serverSpecificGroups.remove(Patterns.SERVER_SPLIT.split(node.getKey(), 2)[1]);
|
serverSpecificGroups.remove(Patterns.SERVER_DELIMITER.split(node.getKey(), 2)[1]);
|
||||||
serverSpecificGroups.remove(Patterns.WORLD_SPLIT.split(node.getKey(), 2)[0] + "/" + Patterns.SERVER_SPLIT.split(node.getKey(), 2)[1]);
|
serverSpecificGroups.remove(Patterns.WORLD_DELIMITER.split(node.getKey(), 2)[0] + "/" + Patterns.SERVER_DELIMITER.split(node.getKey(), 2)[1]);
|
||||||
});
|
});
|
||||||
serverSpecificGroups.entrySet().stream().filter(node -> !node.getValue()).forEach(node -> {
|
serverSpecificGroups.entrySet().stream().filter(node -> !node.getValue()).forEach(node -> {
|
||||||
groupNodes.remove(node.getKey());
|
groupNodes.remove(node.getKey());
|
||||||
groupNodes.remove(Patterns.SERVER_SPLIT.split(node.getKey(), 2)[1]);
|
groupNodes.remove(Patterns.SERVER_DELIMITER.split(node.getKey(), 2)[1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Apply lowest priority: groupNodes
|
// Apply lowest priority: groupNodes
|
||||||
@ -574,7 +574,7 @@ public abstract class PermissionObject {
|
|||||||
// Don't add negated groups
|
// Don't add negated groups
|
||||||
if (!groupNode.getValue()) continue;
|
if (!groupNode.getValue()) continue;
|
||||||
|
|
||||||
String groupName = Patterns.DOT_SPLIT.split(groupNode.getKey(), 2)[1];
|
String groupName = Patterns.DOT.split(groupNode.getKey(), 2)[1];
|
||||||
if (!excludedGroups.contains(groupName)) {
|
if (!excludedGroups.contains(groupName)) {
|
||||||
Group group = plugin.getGroupManager().getGroup(groupName);
|
Group group = plugin.getGroupManager().getGroup(groupName);
|
||||||
if (group != null) {
|
if (group != null) {
|
||||||
@ -589,7 +589,7 @@ public abstract class PermissionObject {
|
|||||||
// Apply next priorities: serverSpecificGroups and then serverWorldSpecificGroups
|
// Apply next priorities: serverSpecificGroups and then serverWorldSpecificGroups
|
||||||
for (Map<String, Boolean> m : Arrays.asList(serverSpecificGroups, serverWorldSpecificGroups)) {
|
for (Map<String, Boolean> m : Arrays.asList(serverSpecificGroups, serverWorldSpecificGroups)) {
|
||||||
for (Map.Entry<String, Boolean> groupNode : m.entrySet()) {
|
for (Map.Entry<String, Boolean> groupNode : m.entrySet()) {
|
||||||
final String rawNode = Patterns.SERVER_SPLIT.split(groupNode.getKey())[1];
|
final String rawNode = Patterns.SERVER_DELIMITER.split(groupNode.getKey())[1];
|
||||||
|
|
||||||
// Add the actual group perm node, so other plugins can hook
|
// Add the actual group perm node, so other plugins can hook
|
||||||
perms.put(rawNode, groupNode.getValue());
|
perms.put(rawNode, groupNode.getValue());
|
||||||
@ -597,7 +597,7 @@ public abstract class PermissionObject {
|
|||||||
// Don't add negated groups
|
// Don't add negated groups
|
||||||
if (!groupNode.getValue()) continue;
|
if (!groupNode.getValue()) continue;
|
||||||
|
|
||||||
String groupName = Patterns.DOT_SPLIT.split(rawNode, 2)[1];
|
String groupName = Patterns.DOT.split(rawNode, 2)[1];
|
||||||
if (!excludedGroups.contains(groupName)) {
|
if (!excludedGroups.contains(groupName)) {
|
||||||
Group group = plugin.getGroupManager().getGroup(groupName);
|
Group group = plugin.getGroupManager().getGroup(groupName);
|
||||||
if (group != null) {
|
if (group != null) {
|
||||||
@ -616,7 +616,7 @@ public abstract class PermissionObject {
|
|||||||
// Apply final priorities: serverSpecificNodes and then serverWorldSpecificNodes
|
// Apply final priorities: serverSpecificNodes and then serverWorldSpecificNodes
|
||||||
for (Map<String, Boolean> m : Arrays.asList(serverSpecificNodes, serverWorldSpecificNodes)) {
|
for (Map<String, Boolean> m : Arrays.asList(serverSpecificNodes, serverWorldSpecificNodes)) {
|
||||||
for (Map.Entry<String, Boolean> node : m.entrySet()) {
|
for (Map.Entry<String, Boolean> node : m.entrySet()) {
|
||||||
final String rawNode = Patterns.SERVER_SPLIT.split(node.getKey())[1];
|
final String rawNode = Patterns.SERVER_DELIMITER.split(node.getKey())[1];
|
||||||
perms.put(rawNode, node.getValue());
|
perms.put(rawNode, node.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -626,7 +626,7 @@ public abstract class PermissionObject {
|
|||||||
|
|
||||||
private static String stripTime(String s) {
|
private static String stripTime(String s) {
|
||||||
if (s.contains("$")) {
|
if (s.contains("$")) {
|
||||||
return Patterns.TEMP_SPLIT.split(s)[0];
|
return Patterns.TEMP_DELIMITER.split(s)[0];
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
21
pom.xml
21
pom.xml
@ -41,27 +41,6 @@
|
|||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<!-- HikariCP -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.zaxxer</groupId>
|
|
||||||
<artifactId>HikariCP</artifactId>
|
|
||||||
<version>2.4.7</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<!-- slf4j library -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>slf4j-simple</artifactId>
|
|
||||||
<version>1.7.9</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<!-- gson -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.google.code.gson</groupId>
|
|
||||||
<artifactId>gson</artifactId>
|
|
||||||
<version>2.7</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<!-- Lombok -->
|
<!-- Lombok -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
|
@ -75,5 +75,19 @@
|
|||||||
<version>1.5</version>
|
<version>1.5</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- HikariCP -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.zaxxer</groupId>
|
||||||
|
<artifactId>HikariCP</artifactId>
|
||||||
|
<version>2.4.7</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- slf4j library -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-simple</artifactId>
|
||||||
|
<version>1.7.9</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
@ -4,12 +4,12 @@ import com.google.inject.Inject;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import me.lucko.luckperms.api.LuckPermsApi;
|
import me.lucko.luckperms.api.LuckPermsApi;
|
||||||
import me.lucko.luckperms.api.implementation.ApiProvider;
|
import me.lucko.luckperms.api.implementation.ApiProvider;
|
||||||
|
import me.lucko.luckperms.constants.Message;
|
||||||
import me.lucko.luckperms.data.Datastore;
|
import me.lucko.luckperms.data.Datastore;
|
||||||
import me.lucko.luckperms.data.methods.FlatfileDatastore;
|
import me.lucko.luckperms.data.methods.FlatfileDatastore;
|
||||||
import me.lucko.luckperms.data.methods.MySQLDatastore;
|
import me.lucko.luckperms.data.methods.MySQLDatastore;
|
||||||
import me.lucko.luckperms.data.methods.SQLiteDatastore;
|
import me.lucko.luckperms.data.methods.SQLiteDatastore;
|
||||||
import me.lucko.luckperms.groups.GroupManager;
|
import me.lucko.luckperms.groups.GroupManager;
|
||||||
import me.lucko.luckperms.listeners.PlayerListener;
|
|
||||||
import me.lucko.luckperms.runnables.UpdateTask;
|
import me.lucko.luckperms.runnables.UpdateTask;
|
||||||
import me.lucko.luckperms.tracks.TrackManager;
|
import me.lucko.luckperms.tracks.TrackManager;
|
||||||
import me.lucko.luckperms.users.SpongeUserManager;
|
import me.lucko.luckperms.users.SpongeUserManager;
|
||||||
@ -37,7 +37,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Plugin(id = "luckperms", name = "LuckPerms", version = LPSpongePlugin.VERSION)
|
@Plugin(id = "luckperms", name = "LuckPerms", version = LPSpongePlugin.VERSION, authors = {"Luck"}, description = "A permissions plugin")
|
||||||
public class LPSpongePlugin implements LuckPermsPlugin {
|
public class LPSpongePlugin implements LuckPermsPlugin {
|
||||||
static final String VERSION = "1.5"; // TODO load this from pom
|
static final String VERSION = "1.5"; // TODO load this from pom
|
||||||
|
|
||||||
@ -59,14 +59,17 @@ public class LPSpongePlugin implements LuckPermsPlugin {
|
|||||||
private TrackManager trackManager;
|
private TrackManager trackManager;
|
||||||
private Datastore datastore;
|
private Datastore datastore;
|
||||||
private UuidCache uuidCache;
|
private UuidCache uuidCache;
|
||||||
|
private me.lucko.luckperms.api.Logger log;
|
||||||
|
|
||||||
@Listener
|
@Listener
|
||||||
public void onEnable(GamePreInitializationEvent event) {
|
public void onEnable(GamePreInitializationEvent event) {
|
||||||
|
log = LogUtil.wrap(logger);
|
||||||
|
|
||||||
getLog().info("Loading configuration...");
|
getLog().info("Loading configuration...");
|
||||||
configuration = new SpongeConfig(this);
|
configuration = new SpongeConfig(this);
|
||||||
|
|
||||||
// register events
|
// register events
|
||||||
Sponge.getEventManager().registerListeners(this, new PlayerListener(this));
|
Sponge.getEventManager().registerListeners(this, new SpongeListener(this));
|
||||||
|
|
||||||
// register commands
|
// register commands
|
||||||
getLog().info("Registering commands...");
|
getLog().info("Registering commands...");
|
||||||
@ -129,16 +132,12 @@ public class LPSpongePlugin implements LuckPermsPlugin {
|
|||||||
LuckPerms.unregisterProvider();
|
LuckPerms.unregisterProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||||
private File getStorageDir() {
|
private File getStorageDir() {
|
||||||
File base = configDir.toFile().getParentFile().getParentFile();
|
File base = configDir.toFile().getParentFile().getParentFile();
|
||||||
File luckperms = new File(base, "luckperms");
|
File luckPermsDir = new File(base, "luckperms");
|
||||||
luckperms.mkdirs();
|
luckPermsDir.mkdirs();
|
||||||
return luckperms;
|
return luckPermsDir;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public me.lucko.luckperms.api.Logger getLog() {
|
|
||||||
return LogUtil.wrap(getLogger());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -147,8 +146,8 @@ public class LPSpongePlugin implements LuckPermsPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPlayerStatus(UUID uuid) {
|
public Message getPlayerStatus(UUID uuid) {
|
||||||
return game.getServer().getPlayer(getUuidCache().getExternalUUID(uuid)).isPresent() ? "&aOnline" : "&cOffline";
|
return game.getServer().getPlayer(getUuidCache().getExternalUUID(uuid)).isPresent() ? Message.PLAYER_ONLINE : Message.PLAYER_OFFLINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package me.lucko.luckperms;
|
package me.lucko.luckperms;
|
||||||
|
|
||||||
import me.lucko.luckperms.commands.CommandManager;
|
import me.lucko.luckperms.commands.CommandManager;
|
||||||
import me.lucko.luckperms.commands.Sender;
|
import me.lucko.luckperms.commands.SenderFactory;
|
||||||
import me.lucko.luckperms.utils.Patterns;
|
import me.lucko.luckperms.utils.Patterns;
|
||||||
import org.spongepowered.api.command.CommandCallable;
|
import org.spongepowered.api.command.CommandCallable;
|
||||||
import org.spongepowered.api.command.CommandException;
|
import org.spongepowered.api.command.CommandException;
|
||||||
@ -10,65 +10,59 @@ import org.spongepowered.api.command.CommandSource;
|
|||||||
import org.spongepowered.api.text.Text;
|
import org.spongepowered.api.text.Text;
|
||||||
import org.spongepowered.api.text.serializer.TextSerializers;
|
import org.spongepowered.api.text.serializer.TextSerializers;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public class SpongeCommand extends CommandManager implements CommandCallable {
|
class SpongeCommand extends CommandManager implements CommandCallable {
|
||||||
public SpongeCommand(LuckPermsPlugin plugin) {
|
private static final Factory FACTORY = new Factory();
|
||||||
|
|
||||||
|
SpongeCommand(LuckPermsPlugin plugin) {
|
||||||
super(plugin);
|
super(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandResult process(CommandSource source, String s) throws CommandException {
|
public CommandResult process(CommandSource source, String s) throws CommandException {
|
||||||
onCommand(makeSender(source), "perms", Arrays.asList(Patterns.SPACE_SPLIT.split(s)));
|
onCommand(FACTORY.wrap(source), "perms", Arrays.asList(Patterns.SPACE.split(s)));
|
||||||
return CommandResult.success();
|
return CommandResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getSuggestions(CommandSource source, String s) throws CommandException {
|
public List<String> getSuggestions(CommandSource source, String s) throws CommandException {
|
||||||
return onTabComplete(makeSender(source), Arrays.asList(Patterns.SPACE_SPLIT.split(s)));
|
return onTabComplete(FACTORY.wrap(source), Arrays.asList(Patterns.SPACE.split(s)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean testPermission(CommandSource commandSource) {
|
public boolean testPermission(CommandSource source) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<? extends Text> getShortDescription(CommandSource commandSource) {
|
public Optional<? extends Text> getShortDescription(CommandSource source) {
|
||||||
return Optional.of(Text.of("LuckPerms main command."));
|
return Optional.of(Text.of("LuckPerms main command."));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<? extends Text> getHelp(CommandSource commandSource) {
|
public Optional<? extends Text> getHelp(CommandSource source) {
|
||||||
return Optional.of(Text.of("Type /perms for help."));
|
return Optional.of(Text.of("Type /perms for help."));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Text getUsage(CommandSource commandSource) {
|
public Text getUsage(CommandSource source) {
|
||||||
return Text.of("/perms");
|
return Text.of("/perms");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Sender makeSender(CommandSource source) {
|
private static class Factory extends SenderFactory<CommandSource> {
|
||||||
return new Sender() {
|
|
||||||
final WeakReference<CommandSource> cs = new WeakReference<>(source);
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@Override
|
@Override
|
||||||
public void sendMessage(String s) {
|
protected void sendMessage(CommandSource source, String s) {
|
||||||
final CommandSource c = cs.get();
|
source.sendMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(s));
|
||||||
if (c != null) {
|
|
||||||
c.sendMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(s));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasPermission(String node) {
|
protected boolean hasPermission(CommandSource source, String node) {
|
||||||
final CommandSource c = cs.get();
|
return source.hasPermission(node);
|
||||||
return c != null && c.hasPermission(node);
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package me.lucko.luckperms;
|
package me.lucko.luckperms;
|
||||||
|
|
||||||
import me.lucko.luckperms.utils.LPConfiguration;
|
import me.lucko.luckperms.utils.LPConfiguration;
|
||||||
|
import me.lucko.luckperms.utils.Patterns;
|
||||||
import ninja.leaping.configurate.ConfigurationNode;
|
import ninja.leaping.configurate.ConfigurationNode;
|
||||||
import ninja.leaping.configurate.commented.CommentedConfigurationNode;
|
import ninja.leaping.configurate.commented.CommentedConfigurationNode;
|
||||||
import ninja.leaping.configurate.hocon.HoconConfigurationLoader;
|
import ninja.leaping.configurate.hocon.HoconConfigurationLoader;
|
||||||
@ -47,7 +48,7 @@ class SpongeConfig extends LPConfiguration<LPSpongePlugin> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ConfigurationNode getNode(String path) {
|
private ConfigurationNode getNode(String path) {
|
||||||
String[] paths = path.split("\\.");
|
String[] paths = Patterns.DOT.split(path);
|
||||||
ConfigurationNode node = root;
|
ConfigurationNode node = root;
|
||||||
|
|
||||||
for (String s : paths) {
|
for (String s : paths) {
|
||||||
|
69
sponge/src/main/java/me/lucko/luckperms/SpongeListener.java
Normal file
69
sponge/src/main/java/me/lucko/luckperms/SpongeListener.java
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package me.lucko.luckperms;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.constants.Message;
|
||||||
|
import me.lucko.luckperms.users.User;
|
||||||
|
import me.lucko.luckperms.utils.AbstractListener;
|
||||||
|
import org.spongepowered.api.entity.Entity;
|
||||||
|
import org.spongepowered.api.entity.living.player.Player;
|
||||||
|
import org.spongepowered.api.event.Listener;
|
||||||
|
import org.spongepowered.api.event.entity.DisplaceEntityEvent;
|
||||||
|
import org.spongepowered.api.event.network.ClientConnectionEvent;
|
||||||
|
import org.spongepowered.api.profile.GameProfile;
|
||||||
|
import org.spongepowered.api.text.serializer.TextSerializers;
|
||||||
|
|
||||||
|
class SpongeListener extends AbstractListener {
|
||||||
|
private final LPSpongePlugin plugin;
|
||||||
|
|
||||||
|
SpongeListener(LPSpongePlugin plugin) {
|
||||||
|
super(plugin);
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Listener
|
||||||
|
public void onClientAuth(ClientConnectionEvent.Auth e) {
|
||||||
|
if (!plugin.getDatastore().isAcceptingLogins()) {
|
||||||
|
// Datastore is disabled, prevent players from joining the server
|
||||||
|
// Just don't load their data, they will be kicked at login
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final GameProfile p = e.getProfile();
|
||||||
|
onAsyncLogin(p.getUniqueId(), p.getName().get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
@Listener
|
||||||
|
public void onClientLogin(ClientConnectionEvent.Login e) {
|
||||||
|
final GameProfile player = e.getProfile();
|
||||||
|
final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(player.getUniqueId()));
|
||||||
|
|
||||||
|
if (user == null) {
|
||||||
|
e.setCancelled(true);
|
||||||
|
e.setMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(Message.LOADING_ERROR.toString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
user.refreshPermissions();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Listener
|
||||||
|
public void onClientJoin(ClientConnectionEvent.Join e) {
|
||||||
|
// Refresh permissions again
|
||||||
|
refreshPlayer(e.getTargetEntity().getUniqueId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Listener
|
||||||
|
public void onPlayerTeleport(DisplaceEntityEvent.Teleport e) {
|
||||||
|
final Entity entity = e.getTargetEntity();
|
||||||
|
if (!(entity instanceof Player)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshPlayer(entity.getUniqueId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Listener
|
||||||
|
public void onClientLeave(ClientConnectionEvent.Disconnect e) {
|
||||||
|
onLeave(e.getTargetEntity().getUniqueId());
|
||||||
|
}
|
||||||
|
}
|
@ -1,107 +0,0 @@
|
|||||||
package me.lucko.luckperms.listeners;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import me.lucko.luckperms.LPSpongePlugin;
|
|
||||||
import me.lucko.luckperms.commands.Util;
|
|
||||||
import me.lucko.luckperms.constants.Message;
|
|
||||||
import me.lucko.luckperms.users.User;
|
|
||||||
import me.lucko.luckperms.utils.UuidCache;
|
|
||||||
import org.spongepowered.api.entity.Entity;
|
|
||||||
import org.spongepowered.api.entity.living.player.Player;
|
|
||||||
import org.spongepowered.api.event.Listener;
|
|
||||||
import org.spongepowered.api.event.entity.DisplaceEntityEvent;
|
|
||||||
import org.spongepowered.api.event.network.ClientConnectionEvent;
|
|
||||||
import org.spongepowered.api.profile.GameProfile;
|
|
||||||
import org.spongepowered.api.text.serializer.TextSerializers;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class PlayerListener {
|
|
||||||
private static final String KICK_MESSAGE = Util.color(Message.PREFIX + "User data could not be loaded. Please contact an administrator.");
|
|
||||||
private final LPSpongePlugin plugin;
|
|
||||||
|
|
||||||
@Listener
|
|
||||||
public void onClientAuth(ClientConnectionEvent.Auth e) {
|
|
||||||
final long startTime = System.currentTimeMillis();
|
|
||||||
if (!plugin.getDatastore().isAcceptingLogins()) {
|
|
||||||
// Datastore is disabled, prevent players from joining the server
|
|
||||||
// Just don't load their data, they will be kickec at login
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final UuidCache cache = plugin.getUuidCache();
|
|
||||||
final GameProfile p = e.getProfile();
|
|
||||||
final String name = p.getName().get();
|
|
||||||
|
|
||||||
if (!cache.isOnlineMode()) {
|
|
||||||
UUID uuid = plugin.getDatastore().getUUID(name);
|
|
||||||
if (uuid != null) {
|
|
||||||
cache.addToCache(p.getUniqueId(), uuid);
|
|
||||||
} else {
|
|
||||||
// No previous data for this player
|
|
||||||
cache.addToCache(p.getUniqueId(), p.getUniqueId());
|
|
||||||
plugin.getDatastore().saveUUIDData(name, p.getUniqueId(), b -> {});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Online mode, no cache needed. This is just for name -> uuid lookup.
|
|
||||||
plugin.getDatastore().saveUUIDData(name, p.getUniqueId(), b -> {});
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin.getDatastore().loadOrCreateUser(cache.getUUID(p.getUniqueId()), name);
|
|
||||||
final long time = System.currentTimeMillis() - startTime;
|
|
||||||
if (time >= 1000) {
|
|
||||||
plugin.getLog().warn("Processing login for " + p.getName() + " took " + time + "ms.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Listener
|
|
||||||
public void onClientLogin(ClientConnectionEvent.Login e) {
|
|
||||||
final GameProfile player = e.getProfile();
|
|
||||||
final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(player.getUniqueId()));
|
|
||||||
|
|
||||||
if (user == null) {
|
|
||||||
e.setCancelled(true);
|
|
||||||
e.setMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(KICK_MESSAGE));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
user.refreshPermissions();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Listener
|
|
||||||
public void onClientJoin(ClientConnectionEvent.Join e) {
|
|
||||||
// Refresh permissions again
|
|
||||||
refreshPlayer(e.getTargetEntity());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Listener
|
|
||||||
public void onPlayerTeleport(DisplaceEntityEvent.Teleport e) {
|
|
||||||
final Entity entity = e.getTargetEntity();
|
|
||||||
if (!(entity instanceof Player)){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
refreshPlayer((Player) entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Listener
|
|
||||||
public void onClientLeave(ClientConnectionEvent.Disconnect e) {
|
|
||||||
final Player player = e.getTargetEntity();
|
|
||||||
final UuidCache cache = plugin.getUuidCache();
|
|
||||||
|
|
||||||
// Unload the user from memory when they disconnect;
|
|
||||||
cache.clearCache(player.getUniqueId());
|
|
||||||
|
|
||||||
final User user = plugin.getUserManager().getUser(cache.getUUID(player.getUniqueId()));
|
|
||||||
plugin.getUserManager().unloadUser(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refreshPlayer(Player p) {
|
|
||||||
final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(p.getUniqueId()));
|
|
||||||
if (user != null) {
|
|
||||||
user.refreshPermissions();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user