Sponge support

This commit is contained in:
Luck 2016-08-05 12:58:27 +02:00
parent 56e11b8b85
commit 03450c3339
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
37 changed files with 908 additions and 126 deletions

View File

@ -1,5 +1,5 @@
# LuckPerms [![Build Status](https://ci.lucko.me/job/LuckPerms/badge/icon)](https://ci.lucko.me/job/LuckPerms/) # LuckPerms [![Build Status](https://ci.lucko.me/job/LuckPerms/badge/icon)](https://ci.lucko.me/job/LuckPerms/)
A permissions implementation for Bukkit/BungeeCord. A permissions implementation for Bukkit/Spigot, BungeeCord and Sponge.
## Links ## Links
* **Development Builds** - <https://ci.lucko.me/job/LuckPerms> * **Development Builds** - <https://ci.lucko.me/job/LuckPerms>
@ -23,11 +23,12 @@ A permissions implementation for Bukkit/BungeeCord.
* **Well documented** - API methods have comprehensive Java docs, it's clear what each method does. * **Well documented** - API methods have comprehensive Java docs, it's clear what each method does.
* **Efficient/lightweight** - maybe? Who knows, it might be. * **Efficient/lightweight** - maybe? Who knows, it might be.
* **Open Sourced, Free...** - you shouldn't have to pay $10+ for a "powerful" permissions plugin. * **Open Sourced, Free...** - you shouldn't have to pay $10+ for a "powerful" permissions plugin.
* **BungeeCord compatible** - permissions, users and groups are synced across Bukkit/BungeeCord instances * **BungeeCord compatible** - permissions, users and groups are synced across all LuckPerms instances
* **Sponge compatible** - permissions, users and groups are synced across all LuckPerms instances (bukkit --> sponge, for example)
* **Support for MySQL, SQLite & Flatfile (JSON)** - other storage methods coming soon (maybe) * **Support for MySQL, SQLite & Flatfile (JSON)** - other storage methods coming soon (maybe)
## Setup ## Setup
All configuration options are in the **config.yml** file, which is generated automagically when the plugin first starts. All configuration options are in the **config.yml/luckperms.conf** file, which is generated automagically when the plugin first starts.
You can define the settings for per-server permissions, the storage method and credentials within this file. You can define the settings for per-server permissions, the storage method and credentials within this file.
@ -57,11 +58,20 @@ Temporary permissions are checked each time a user/group is loaded, and when the
The only way around this is to decrease the sync interval. The only way around this is to decrease the sync interval.
## API ## API
LuckPerms has an extensive API, allowing for easy integration with other projects. To use the Api, you need to obtain an instance of the `LuckPermsApi` interface. This can be done in two ways, (one way on BungeeCord). LuckPerms has an extensive API, allowing for easy integration with other projects. To use the Api, you need to obtain an instance of the `LuckPermsApi` interface. This can be done in a number of ways.
```java ```java
// On all platforms
final LuckPermsApi api = LuckPerms.getApi(); final LuckPermsApi api = LuckPerms.getApi();
// On Bukkit/Spigot
final LuckPermsApi api = Bukkit.getServicesManager().getRegistration(LuckPermsApi.class).getProvider(); final LuckPermsApi api = Bukkit.getServicesManager().getRegistration(LuckPermsApi.class).getProvider();
// On Sponge
Optional<LuckPermsApi> provider = Sponge.getServiceManager().provide(LuckPermsApi.class);
if (provider.isPresent()) {
final LuckPermsApi api = provider.get();
}
``` ```
If you want to use LuckPerms in your onEnable method, you need to add the following to your plugins `plugin.yml`. If you want to use LuckPerms in your onEnable method, you need to add the following to your plugins `plugin.yml`.
@ -83,7 +93,7 @@ You can add LuckPerms as a Maven dependency by adding the following to your proj
<dependency> <dependency>
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<artifactId>luckperms-api</artifactId> <artifactId>luckperms-api</artifactId>
<version>1.4</version> <version>1.5</version>
</dependency> </dependency>
</dependencies> </dependencies>
```` ````

View File

@ -5,11 +5,11 @@
<parent> <parent>
<artifactId>luckperms</artifactId> <artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<version>1.4</version> <version>1.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<version>1.4</version> <version>1.5</version>
<artifactId>luckperms-api</artifactId> <artifactId>luckperms-api</artifactId>
<build> <build>
<plugins> <plugins>

View File

@ -0,0 +1,9 @@
package me.lucko.luckperms.api;
public interface Logger {
void info(String s);
void warn(String s);
void severe(String s);
}

View File

@ -9,6 +9,7 @@ public interface LuckPermsApi {
String getVersion(); String getVersion();
Datastore getDatastore(); Datastore getDatastore();
Logger getLogger();
User getUser(UUID uuid); User getUser(UUID uuid);
User getUser(String name); User getUser(String name);

View File

@ -5,12 +5,12 @@
<parent> <parent>
<artifactId>luckperms</artifactId> <artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<version>1.4</version> <version>1.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>luckperms-bukkit</artifactId> <artifactId>luckperms-bukkit</artifactId>
<version>1.4</version> <version>1.5</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>LuckPerms</name> <name>LuckPerms</name>
@ -72,14 +72,14 @@
<dependency> <dependency>
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<artifactId>luckperms-common</artifactId> <artifactId>luckperms-common</artifactId>
<version>1.4</version> <version>1.5</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<!-- LuckPerms API --> <!-- LuckPerms API -->
<dependency> <dependency>
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<artifactId>luckperms-api</artifactId> <artifactId>luckperms-api</artifactId>
<version>1.4</version> <version>1.5</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -11,8 +11,8 @@ import java.lang.ref.WeakReference;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
class CommandManagerBukkit extends CommandManager implements CommandExecutor, TabExecutor { class BukkitCommand extends CommandManager implements CommandExecutor, TabExecutor {
CommandManagerBukkit(LuckPermsPlugin plugin) { BukkitCommand(LuckPermsPlugin plugin) {
super(plugin); super(plugin);
} }

View File

@ -1,6 +1,7 @@
package me.lucko.luckperms; package me.lucko.luckperms;
import lombok.Getter; import lombok.Getter;
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;
@ -15,6 +16,7 @@ import me.lucko.luckperms.tracks.TrackManager;
import me.lucko.luckperms.users.BukkitUserManager; import me.lucko.luckperms.users.BukkitUserManager;
import me.lucko.luckperms.users.UserManager; import me.lucko.luckperms.users.UserManager;
import me.lucko.luckperms.utils.LPConfiguration; import me.lucko.luckperms.utils.LPConfiguration;
import me.lucko.luckperms.utils.LogUtil;
import me.lucko.luckperms.utils.UuidCache; import me.lucko.luckperms.utils.UuidCache;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.PluginCommand; import org.bukkit.command.PluginCommand;
@ -40,7 +42,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
@Override @Override
public void onEnable() { public void onEnable() {
getLogger().info("Loading configuration..."); getLog().info("Loading configuration...");
configuration = new BukkitConfig(this); configuration = new BukkitConfig(this);
// register events // register events
@ -48,40 +50,40 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
pm.registerEvents(new PlayerListener(this), this); pm.registerEvents(new PlayerListener(this), this);
// register commands // register commands
getLogger().info("Registering commands..."); getLog().info("Registering commands...");
CommandManagerBukkit commandManager = new CommandManagerBukkit(this); BukkitCommand commandManager = new BukkitCommand(this);
PluginCommand main = getServer().getPluginCommand("luckperms"); PluginCommand main = getServer().getPluginCommand("luckperms");
main.setExecutor(commandManager); main.setExecutor(commandManager);
main.setTabCompleter(commandManager); main.setTabCompleter(commandManager);
main.setAliases(Arrays.asList("perms", "lp", "permissions", "p", "perm")); main.setAliases(Arrays.asList("perms", "lp", "permissions", "p", "perm"));
getLogger().info("Detecting storage method..."); getLog().info("Detecting storage method...");
final String storageMethod = configuration.getStorageMethod(); final String storageMethod = configuration.getStorageMethod();
if (storageMethod.equalsIgnoreCase("mysql")) { if (storageMethod.equalsIgnoreCase("mysql")) {
getLogger().info("Using MySQL as storage method."); getLog().info("Using MySQL as storage method.");
datastore = new MySQLDatastore(this, configuration.getDatabaseValues()); datastore = new MySQLDatastore(this, configuration.getDatabaseValues());
} else if (storageMethod.equalsIgnoreCase("sqlite")) { } else if (storageMethod.equalsIgnoreCase("sqlite")) {
getLogger().info("Using SQLite as storage method."); getLog().info("Using SQLite as storage method.");
datastore = new SQLiteDatastore(this, new File(getDataFolder(), "luckperms.sqlite")); datastore = new SQLiteDatastore(this, new File(getDataFolder(), "luckperms.sqlite"));
} else if (storageMethod.equalsIgnoreCase("flatfile")) { } else if (storageMethod.equalsIgnoreCase("flatfile")) {
getLogger().info("Using Flatfile (JSON) as storage method."); getLog().info("Using Flatfile (JSON) as storage method.");
datastore = new FlatfileDatastore(this, getDataFolder()); datastore = new FlatfileDatastore(this, getDataFolder());
} else { } else {
getLogger().severe("Storage method '" + storageMethod + "' was not recognised. Using SQLite as fallback."); getLog().severe("Storage method '" + storageMethod + "' was not recognised. Using SQLite as fallback.");
datastore = new SQLiteDatastore(this, new File(getDataFolder(), "luckperms.sqlite")); datastore = new SQLiteDatastore(this, new File(getDataFolder(), "luckperms.sqlite"));
} }
getLogger().info("Initialising datastore..."); getLog().info("Initialising datastore...");
datastore.init(); datastore.init();
getLogger().info("Loading internal permission managers..."); getLog().info("Loading internal permission managers...");
uuidCache = new UuidCache(getConfiguration().getOnlineMode()); uuidCache = new UuidCache(getConfiguration().getOnlineMode());
userManager = new BukkitUserManager(this); userManager = new BukkitUserManager(this);
groupManager = new GroupManager(this); groupManager = new GroupManager(this);
trackManager = new TrackManager(); trackManager = new TrackManager();
// Run update task to refresh any online users // Run update task to refresh any online users
getLogger().info("Scheduling Update Task to refresh any online users."); getLog().info("Scheduling Update Task to refresh any online users.");
try { try {
new UpdateTask(this).run(); new UpdateTask(this).run();
} catch (Exception e) { } catch (Exception e) {
@ -95,33 +97,33 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
} }
// Provide vault support // Provide vault support
getLogger().info("Attempting to hook into Vault..."); getLog().info("Attempting to hook into Vault...");
try { try {
if (getServer().getPluginManager().isPluginEnabled("Vault")) { if (getServer().getPluginManager().isPluginEnabled("Vault")) {
VaultHook.hook(this); VaultHook.hook(this);
getLogger().info("Registered Vault permission & chat hook."); getLog().info("Registered Vault permission & chat hook.");
} else { } else {
getLogger().info("Vault not found."); getLog().info("Vault not found.");
} }
} catch (Exception e) { } catch (Exception e) {
getLogger().severe("Error occurred whilst hooking into Vault."); getLog().severe("Error occurred whilst hooking into Vault.");
e.printStackTrace(); e.printStackTrace();
} }
getLogger().info("Registering API..."); getLog().info("Registering API...");
final ApiProvider provider = new ApiProvider(this); final ApiProvider provider = new ApiProvider(this);
LuckPerms.registerProvider(provider); LuckPerms.registerProvider(provider);
getServer().getServicesManager().register(LuckPermsApi.class, provider, this, ServicePriority.Normal); getServer().getServicesManager().register(LuckPermsApi.class, provider, this, ServicePriority.Normal);
getLogger().info("Successfully loaded."); getLog().info("Successfully loaded.");
} }
@Override @Override
public void onDisable() { public void onDisable() {
getLogger().info("Closing datastore..."); getLog().info("Closing datastore...");
datastore.shutdown(); datastore.shutdown();
getLogger().info("Unregistering API..."); getLog().info("Unregistering API...");
LuckPerms.unregisterProvider(); LuckPerms.unregisterProvider();
getServer().getServicesManager().unregisterAll(this); getServer().getServicesManager().unregisterAll(this);
} }
@ -136,6 +138,11 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
Bukkit.getScheduler().runTask(this, r); Bukkit.getScheduler().runTask(this, r);
} }
@Override
public Logger getLog() {
return LogUtil.wrap(getLogger());
}
@Override @Override
public String getVersion() { public String getVersion() {
return getDescription().getVersion(); return getDescription().getVersion();

View File

@ -46,14 +46,14 @@ public class PlayerListener implements Listener {
plugin.getDatastore().loadOrCreateUser(cache.getUUID(e.getUniqueId()), e.getName()); plugin.getDatastore().loadOrCreateUser(cache.getUUID(e.getUniqueId()), e.getName());
final long time = System.currentTimeMillis() - startTime; final long time = System.currentTimeMillis() - startTime;
if (time >= 1000) { if (time >= 1000) {
plugin.getLogger().warning("Processing login for " + e.getName() + " took " + time + "ms."); plugin.getLog().warn("Processing login for " + e.getName() + " took " + time + "ms.");
} }
} }
@EventHandler @EventHandler
public void onPlayerLogin(PlayerLoginEvent e) { public void onPlayerLogin(PlayerLoginEvent e) {
final Player player = e.getPlayer(); final Player player = e.getPlayer();
final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId())); final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(player.getUniqueId()));
if (user == null) { if (user == null) {
e.disallow(PlayerLoginEvent.Result.KICK_OTHER, KICK_MESSAGE); e.disallow(PlayerLoginEvent.Result.KICK_OTHER, KICK_MESSAGE);
@ -74,6 +74,11 @@ public class PlayerListener implements Listener {
refreshPlayer(e.getPlayer()); refreshPlayer(e.getPlayer());
} }
@EventHandler
public void onPlayerChangedWorld(PlayerChangedWorldEvent e) {
refreshPlayer(e.getPlayer());
}
@EventHandler @EventHandler
public void onPlayerQuit(PlayerQuitEvent e) { public void onPlayerQuit(PlayerQuitEvent e) {
final Player player = e.getPlayer(); final Player player = e.getPlayer();
@ -86,11 +91,6 @@ public class PlayerListener implements Listener {
plugin.getUserManager().unloadUser(user); plugin.getUserManager().unloadUser(user);
} }
@EventHandler
public void onPlayerChangedWorld(PlayerChangedWorldEvent e) {
refreshPlayer(e.getPlayer());
}
private void refreshPlayer(Player p) { private void refreshPlayer(Player p) {
final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(p.getUniqueId())); final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(p.getUniqueId()));
if (user != null) { if (user != null) {

View File

@ -34,7 +34,7 @@ public class BukkitUser extends User {
if (player == null) return; if (player == null) return;
if (attachment == null) { if (attachment == null) {
getPlugin().getLogger().warning("User " + getName() + " does not have a permissions attachment defined."); getPlugin().getLog().warn("User " + getName() + " does not have a permissions attachment defined.");
setAttachment(player.addAttachment(plugin)); setAttachment(player.addAttachment(plugin));
} }

View File

@ -16,7 +16,7 @@ include-global: true
# 1. You have Spigot servers connected to a BungeeCord proxy, with online-mode set to false, but 'bungeecord' set to true in the spigot.yml # 1. You have Spigot servers connected to a BungeeCord proxy, with online-mode set to false, but 'bungeecord' set to true in the spigot.yml
# AND 'ip-forward' set to true in the BungeeCord config.yml # AND 'ip-forward' set to true in the BungeeCord config.yml
# In this case, set online-mode in LuckPerms to true, dispite the server being in offline mode. # In this case, set online-mode in LuckPerms to true, despite the server being in offline mode.
# 2. You are only running one server instance using LuckPerms, (not a network) # 2. You are only running one server instance using LuckPerms, (not a network)
# In this case, set online-mode to true no matter what is set in server.properties. (we can just fallback to the servers uuid cache) # In this case, set online-mode to true no matter what is set in server.properties. (we can just fallback to the servers uuid cache)

View File

@ -5,12 +5,12 @@
<parent> <parent>
<artifactId>luckperms</artifactId> <artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<version>1.4</version> <version>1.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>luckperms-bungee</artifactId> <artifactId>luckperms-bungee</artifactId>
<version>1.4</version> <version>1.5</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>LuckPerms</name> <name>LuckPerms</name>
@ -65,14 +65,14 @@
<dependency> <dependency>
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<artifactId>luckperms-common</artifactId> <artifactId>luckperms-common</artifactId>
<version>1.4</version> <version>1.5</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<!-- LuckPerms API --> <!-- LuckPerms API -->
<dependency> <dependency>
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<artifactId>luckperms-api</artifactId> <artifactId>luckperms-api</artifactId>
<version>1.4</version> <version>1.5</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -10,10 +10,10 @@ import net.md_5.bungee.api.plugin.TabExecutor;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.Arrays; import java.util.Arrays;
class MainCommand extends Command implements TabExecutor { class BungeeCommand extends Command implements TabExecutor {
private final CommandManager manager; private final CommandManager manager;
public MainCommand(CommandManager manager) { public BungeeCommand(CommandManager manager) {
super("luckpermsbungee", null, "bperms", "lpb", "bpermissions", "bp", "bperm"); super("luckpermsbungee", null, "bperms", "lpb", "bpermissions", "bp", "bperm");
this.manager = manager; this.manager = manager;
} }

View File

@ -1,6 +1,7 @@
package me.lucko.luckperms; package me.lucko.luckperms;
import lombok.Getter; import lombok.Getter;
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.data.Datastore; import me.lucko.luckperms.data.Datastore;
@ -13,6 +14,7 @@ import me.lucko.luckperms.tracks.TrackManager;
import me.lucko.luckperms.users.BungeeUserManager; import me.lucko.luckperms.users.BungeeUserManager;
import me.lucko.luckperms.users.UserManager; import me.lucko.luckperms.users.UserManager;
import me.lucko.luckperms.utils.LPConfiguration; import me.lucko.luckperms.utils.LPConfiguration;
import me.lucko.luckperms.utils.LogUtil;
import me.lucko.luckperms.utils.UuidCache; import me.lucko.luckperms.utils.UuidCache;
import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.api.plugin.Plugin;
@ -33,43 +35,43 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
@Override @Override
public void onEnable() { public void onEnable() {
getLogger().info("Loading configuration..."); getLog().info("Loading configuration...");
configuration = new BungeeConfig(this); configuration = new BungeeConfig(this);
// register events // register events
getProxy().getPluginManager().registerListener(this, new PlayerListener(this)); getProxy().getPluginManager().registerListener(this, new PlayerListener(this));
// register commands // register commands
getLogger().info("Registering commands..."); getLog().info("Registering commands...");
getProxy().getPluginManager().registerCommand(this, new MainCommand(new CommandManager(this))); getProxy().getPluginManager().registerCommand(this, new BungeeCommand(new CommandManager(this)));
// disable the default Bungee /perms command so it gets handled by the Bukkit plugin // disable the default Bungee /perms command so it gets handled by the Bukkit plugin
getProxy().getDisabledCommands().add("perms"); getProxy().getDisabledCommands().add("perms");
getLogger().info("Detecting storage method..."); getLog().info("Detecting storage method...");
final String storageMethod = configuration.getStorageMethod(); final String storageMethod = configuration.getStorageMethod();
if (storageMethod.equalsIgnoreCase("mysql")) { if (storageMethod.equalsIgnoreCase("mysql")) {
getLogger().info("Using MySQL as storage method."); getLog().info("Using MySQL as storage method.");
datastore = new MySQLDatastore(this, configuration.getDatabaseValues()); datastore = new MySQLDatastore(this, configuration.getDatabaseValues());
} else if (storageMethod.equalsIgnoreCase("flatfile")) { } else if (storageMethod.equalsIgnoreCase("flatfile")) {
getLogger().info("Using Flatfile (JSON) as storage method."); getLog().info("Using Flatfile (JSON) as storage method.");
datastore = new FlatfileDatastore(this, getDataFolder()); datastore = new FlatfileDatastore(this, getDataFolder());
} else { } else {
getLogger().severe("Storage method '" + storageMethod + "' was not recognised. Using Flatfile as fallback."); getLog().severe("Storage method '" + storageMethod + "' was not recognised. Using Flatfile as fallback.");
datastore = new FlatfileDatastore(this, getDataFolder()); datastore = new FlatfileDatastore(this, getDataFolder());
} }
getLogger().info("Initialising datastore..."); getLog().info("Initialising datastore...");
datastore.init(); datastore.init();
getLogger().info("Loading internal permission managers..."); getLog().info("Loading internal permission managers...");
uuidCache = new UuidCache(getConfiguration().getOnlineMode()); uuidCache = new UuidCache(getConfiguration().getOnlineMode());
userManager = new BungeeUserManager(this); userManager = new BungeeUserManager(this);
groupManager = new GroupManager(this); groupManager = new GroupManager(this);
trackManager = new TrackManager(); trackManager = new TrackManager();
// Run update task to refresh any online users // Run update task to refresh any online users
getLogger().info("Scheduling Update Task to refresh any online users."); getLog().info("Scheduling Update Task to refresh any online users.");
try { try {
new UpdateTask(this).run(); new UpdateTask(this).run();
} catch (Exception e) { } catch (Exception e) {
@ -81,21 +83,26 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
getProxy().getScheduler().schedule(this, new UpdateTask(this), mins, mins, TimeUnit.MINUTES); getProxy().getScheduler().schedule(this, new UpdateTask(this), mins, mins, TimeUnit.MINUTES);
} }
getLogger().info("Registering API..."); getLog().info("Registering API...");
LuckPerms.registerProvider(new ApiProvider(this)); LuckPerms.registerProvider(new ApiProvider(this));
getLogger().info("Successfully loaded."); getLog().info("Successfully loaded.");
} }
@Override @Override
public void onDisable() { public void onDisable() {
getLogger().info("Closing datastore..."); getLog().info("Closing datastore...");
datastore.shutdown(); datastore.shutdown();
getLogger().info("Unregistering API..."); getLog().info("Unregistering API...");
LuckPerms.unregisterProvider(); LuckPerms.unregisterProvider();
} }
@Override
public Logger getLog() {
return LogUtil.wrap(getLogger());
}
@Override @Override
public String getVersion() { public String getVersion() {
return getDescription().getVersion(); return getDescription().getVersion();

View File

@ -57,7 +57,7 @@ public class PlayerListener implements Listener {
plugin.getDatastore().loadOrCreateUser(cache.getUUID(c.getUniqueId()), c.getName()); plugin.getDatastore().loadOrCreateUser(cache.getUUID(c.getUniqueId()), c.getName());
final long time = System.currentTimeMillis() - startTime; final long time = System.currentTimeMillis() - startTime;
if (time >= 1000) { if (time >= 1000) {
plugin.getLogger().warning("Processing login for " + c.getName() + " took " + time + "ms."); plugin.getLog().warn("Processing login for " + c.getName() + " took " + time + "ms.");
} }
e.completeIntent(plugin); e.completeIntent(plugin);
}); });

View File

@ -9,7 +9,6 @@ import java.util.Map;
import java.util.UUID; import java.util.UUID;
public class BungeeUser extends User { public class BungeeUser extends User {
private final LPBungeePlugin plugin; private final LPBungeePlugin plugin;
BungeeUser(UUID uuid, LPBungeePlugin plugin) { BungeeUser(UUID uuid, LPBungeePlugin plugin) {

View File

@ -16,7 +16,7 @@ include-global: false
# 1. You have Spigot servers connected to a BungeeCord proxy, with online-mode set to false, but 'bungeecord' set to true in the spigot.yml # 1. You have Spigot servers connected to a BungeeCord proxy, with online-mode set to false, but 'bungeecord' set to true in the spigot.yml
# AND 'ip-forward' set to true in the BungeeCord config.yml # AND 'ip-forward' set to true in the BungeeCord config.yml
# In this case, set online-mode in LuckPerms to true, dispite the server being in offline mode. # In this case, set online-mode in LuckPerms to true, despite the server being in offline mode.
# 2. You are only running one server instance using LuckPerms, (not a network) # 2. You are only running one server instance using LuckPerms, (not a network)
# In this case, set online-mode to true no matter what is set in server.properties. (we can just fallback to the servers uuid cache) # In this case, set online-mode to true no matter what is set in server.properties. (we can just fallback to the servers uuid cache)

View File

@ -5,11 +5,11 @@
<parent> <parent>
<artifactId>luckperms</artifactId> <artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<version>1.4</version> <version>1.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<version>1.4</version> <version>1.5</version>
<artifactId>luckperms-common</artifactId> <artifactId>luckperms-common</artifactId>
<build> <build>
<plugins> <plugins>
@ -30,7 +30,7 @@
<dependency> <dependency>
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<artifactId>luckperms-api</artifactId> <artifactId>luckperms-api</artifactId>
<version>1.4</version> <version>1.5</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -1,5 +1,6 @@
package me.lucko.luckperms; package me.lucko.luckperms;
import me.lucko.luckperms.api.Logger;
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;
@ -9,7 +10,6 @@ import me.lucko.luckperms.utils.UuidCache;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.logging.Logger;
public interface LuckPermsPlugin { public interface LuckPermsPlugin {
@ -47,7 +47,7 @@ public interface LuckPermsPlugin {
* Retrieves the {@link Logger} for the plugin * Retrieves the {@link Logger} for the plugin
* @return the plugin's {@link Logger} * @return the plugin's {@link Logger}
*/ */
Logger getLogger(); Logger getLog();
/** /**
* Retrieves the {@link UuidCache} for the plugin * Retrieves the {@link UuidCache} for the plugin

View File

@ -33,6 +33,11 @@ public class ApiProvider implements LuckPermsApi {
return new DatastoreLink(plugin.getDatastore()); return new DatastoreLink(plugin.getDatastore());
} }
@Override
public Logger getLogger() {
return plugin.getLog();
}
@Override @Override
public User getUser(@NonNull UUID uuid) { public User getUser(@NonNull UUID uuid) {
final me.lucko.luckperms.users.User user = plugin.getUserManager().getUser(uuid); final me.lucko.luckperms.users.User user = plugin.getUserManager().getUser(uuid);

View File

@ -23,7 +23,6 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.logging.Level;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class CommandManager { public class CommandManager {
@ -162,7 +161,7 @@ public class CommandManager {
} }
private void registerMainCommand(MainCommand command) { private void registerMainCommand(MainCommand command) {
plugin.getLogger().log(Level.INFO, "[CommandManager] Registered main command '" + command.getName() + "'"); plugin.getLog().info("[CommandManager] Registered main command '" + command.getName() + "'");
mainCommands.add(command); mainCommands.add(command);
} }

View File

@ -1,12 +1,14 @@
package me.lucko.luckperms.data.methods; package me.lucko.luckperms.data.methods;
import com.zaxxer.hikari.HikariDataSource; import com.zaxxer.hikari.HikariDataSource;
import lombok.Cleanup;
import me.lucko.luckperms.LuckPermsPlugin; import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.data.MySQLConfiguration; import me.lucko.luckperms.data.MySQLConfiguration;
import java.sql.Connection; import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.logging.Level;
public class MySQLDatastore extends SQLDatastore { public class MySQLDatastore extends SQLDatastore {
@ -41,13 +43,53 @@ public class MySQLDatastore extends SQLDatastore {
hikari.addDataSourceProperty("password", password); hikari.addDataSourceProperty("password", password);
if (!setupTables(CREATETABLE_UUID, CREATETABLE_USERS, CREATETABLE_GROUPS, CREATETABLE_TRACKS)) { if (!setupTables(CREATETABLE_UUID, CREATETABLE_USERS, CREATETABLE_GROUPS, CREATETABLE_TRACKS)) {
plugin.getLogger().log(Level.SEVERE, "Error occurred whilst initialising the database. All connections are disallowed."); plugin.getLog().severe("Error occurred whilst initialising the database. All connections are disallowed.");
shutdown(); shutdown();
} else { } else {
setAcceptingLogins(true); setAcceptingLogins(true);
} }
} }
@Override
boolean runQuery(QueryPS queryPS) {
boolean success = false;
try {
@Cleanup Connection connection = getConnection();
if (connection == null || connection.isClosed()) {
throw new IllegalStateException("SQL connection is null");
}
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement(queryPS.getQuery());
queryPS.onRun(preparedStatement);
preparedStatement.execute();
success = true;
} catch (SQLException e) {
e.printStackTrace();
}
return success;
}
@Override
boolean runQuery(QueryRS queryRS) {
boolean success = false;
try {
@Cleanup Connection connection = getConnection();
if (connection == null || connection.isClosed()) {
throw new IllegalStateException("SQL connection is null");
}
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement(queryRS.getQuery());
queryRS.onRun(preparedStatement);
preparedStatement.execute();
@Cleanup ResultSet resultSet = preparedStatement.executeQuery();
success = queryRS.onResult(resultSet);
} catch (SQLException e) {
e.printStackTrace();
}
return success;
}
@Override @Override
public void shutdown() { public void shutdown() {
if (hikari != null) { if (hikari != null) {

View File

@ -3,7 +3,6 @@ package me.lucko.luckperms.data.methods;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Cleanup;
import lombok.Getter; import lombok.Getter;
import me.lucko.luckperms.LuckPermsPlugin; import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.data.Datastore; import me.lucko.luckperms.data.Datastore;
@ -58,43 +57,8 @@ abstract class SQLDatastore extends Datastore {
abstract Connection getConnection() throws SQLException; abstract Connection getConnection() throws SQLException;
private boolean runQuery(QueryPS queryPS) { abstract boolean runQuery(QueryPS queryPS);
boolean success = false; abstract boolean runQuery(QueryRS queryRS);
try {
@Cleanup Connection connection = getConnection();
if (connection == null) {
throw new IllegalStateException("SQL connection is null");
}
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement(queryPS.getQuery());
queryPS.onRun(preparedStatement);
preparedStatement.execute();
success = true;
} catch (SQLException e) {
e.printStackTrace();
}
return success;
}
private boolean runQuery(QueryRS queryRS) {
boolean success = false;
try {
@Cleanup Connection connection = getConnection();
if (connection == null || connection.isClosed()) {
throw new IllegalStateException("SQL connection is null");
}
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement(queryRS.getQuery());
queryRS.onRun(preparedStatement);
preparedStatement.execute();
@Cleanup ResultSet resultSet = preparedStatement.executeQuery();
success = queryRS.onResult(resultSet);
} catch (SQLException e) {
e.printStackTrace();
}
return success;
}
boolean setupTables(String... tableQueries) { boolean setupTables(String... tableQueries) {
boolean success = true; boolean success = true;
@ -467,14 +431,14 @@ abstract class SQLDatastore extends Datastore {
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
private abstract class QueryPS { abstract class QueryPS {
private final String query; private final String query;
abstract void onRun(PreparedStatement preparedStatement) throws SQLException; abstract void onRun(PreparedStatement preparedStatement) throws SQLException;
} }
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
private abstract class QueryRS { abstract class QueryRS {
private final String query; private final String query;
abstract void onRun(PreparedStatement preparedStatement) throws SQLException; abstract void onRun(PreparedStatement preparedStatement) throws SQLException;
abstract boolean onResult(ResultSet resultSet) throws SQLException; abstract boolean onResult(ResultSet resultSet) throws SQLException;

View File

@ -1,12 +1,10 @@
package me.lucko.luckperms.data.methods; package me.lucko.luckperms.data.methods;
import lombok.Cleanup;
import me.lucko.luckperms.LuckPermsPlugin; import me.lucko.luckperms.LuckPermsPlugin;
import java.io.File; import java.io.File;
import java.sql.Connection; import java.sql.*;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.logging.Level;
public class SQLiteDatastore extends SQLDatastore { public class SQLiteDatastore extends SQLDatastore {
@ -26,13 +24,53 @@ public class SQLiteDatastore extends SQLDatastore {
@Override @Override
public void init() { public void init() {
if (!setupTables(CREATETABLE_UUID, CREATETABLE_USERS, CREATETABLE_GROUPS, CREATETABLE_TRACKS)) { if (!setupTables(CREATETABLE_UUID, CREATETABLE_USERS, CREATETABLE_GROUPS, CREATETABLE_TRACKS)) {
plugin.getLogger().log(Level.SEVERE, "Error occurred whilst initialising the database. All connections are disallowed."); plugin.getLog().severe("Error occurred whilst initialising the database. All connections are disallowed.");
shutdown(); shutdown();
} else { } else {
setAcceptingLogins(true); setAcceptingLogins(true);
} }
} }
@Override
boolean runQuery(QueryPS queryPS) {
boolean success = false;
try {
Connection connection = getConnection();
if (connection == null || connection.isClosed()) {
throw new IllegalStateException("SQL connection is null");
}
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement(queryPS.getQuery());
queryPS.onRun(preparedStatement);
preparedStatement.execute();
success = true;
} catch (SQLException e) {
e.printStackTrace();
}
return success;
}
@Override
boolean runQuery(QueryRS queryRS) {
boolean success = false;
try {
Connection connection = getConnection();
if (connection == null || connection.isClosed()) {
throw new IllegalStateException("SQL connection is null");
}
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement(queryRS.getQuery());
queryRS.onRun(preparedStatement);
preparedStatement.execute();
@Cleanup ResultSet resultSet = preparedStatement.executeQuery();
success = queryRS.onResult(resultSet);
} catch (SQLException e) {
e.printStackTrace();
}
return success;
}
@Override @Override
public void shutdown() { public void shutdown() {
try { try {

View File

@ -9,7 +9,7 @@ public class UpdateTask implements Runnable {
@Override @Override
public void run() { public void run() {
plugin.getLogger().info("Running update task."); plugin.getLog().info("Running update task.");
// Reload all of the groups // Reload all of the groups
plugin.getDatastore().loadAllGroups(); plugin.getDatastore().loadAllGroups();

View File

@ -22,14 +22,14 @@ public abstract class LPConfiguration<T extends LuckPermsPlugin> {
init(); init();
if (Patterns.NON_ALPHA_NUMERIC.matcher(getServer()).find()) { if (Patterns.NON_ALPHA_NUMERIC.matcher(getServer()).find()) {
plugin.getLogger().severe("Server name defined in config.yml contains invalid characters. Server names can " + plugin.getLog().severe("Server name defined in config.yml contains invalid characters. Server names can " +
"only contain alphanumeric characters.\nDefined server name '" + getServer() + "' will be replaced with '" + "only contain alphanumeric characters.\nDefined server name '" + getServer() + "' will be replaced with '" +
defaultServerName + "' (the default)"); defaultServerName + "' (the default)");
set("server", defaultServerName); set("server", defaultServerName);
} }
if (Patterns.NON_ALPHA_NUMERIC.matcher(getDefaultGroupName()).find()) { if (Patterns.NON_ALPHA_NUMERIC.matcher(getDefaultGroupName()).find()) {
plugin.getLogger().severe("Default group defined in config.yml contains invalid characters. Group names can " + plugin.getLog().severe("Default group defined in config.yml contains invalid characters. Group names can " +
"only contain alphanumeric characters.\nDefined default group name '" + getDefaultGroupName() + "only contain alphanumeric characters.\nDefined default group name '" + getDefaultGroupName() +
"' will be replaced with 'default' (the default)"); "' will be replaced with 'default' (the default)");
set("default-group", "default"); set("default-group", "default");

View File

@ -0,0 +1,49 @@
package me.lucko.luckperms.utils;
import lombok.experimental.UtilityClass;
import me.lucko.luckperms.api.Logger;
@UtilityClass
public class LogUtil {
public static Logger wrap(org.slf4j.Logger l) {
return new Logger() {
private final org.slf4j.Logger logger = l;
@Override
public void info(String s) {
logger.info(s);
}
@Override
public void warn(String s) {
logger.warn(s);
}
@Override
public void severe(String s) {
logger.error(s);
}
};
}
public static Logger wrap(java.util.logging.Logger l) {
return new Logger() {
private final java.util.logging.Logger logger = l;
@Override
public void info(String s) {
logger.info(s);
}
@Override
public void warn(String s) {
logger.warning(s);
}
@Override
public void severe(String s) {
logger.severe(s);
}
};
}
}

View File

@ -6,6 +6,7 @@ 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 SERVER_SPLIT = Pattern.compile("\\/"); public static final Pattern SERVER_SPLIT = Pattern.compile("\\/");
public static final Pattern WORLD_SPLIT = Pattern.compile("\\-"); public static final Pattern WORLD_SPLIT = Pattern.compile("\\-");
public static final Pattern TEMP_SPLIT = Pattern.compile("\\$"); public static final Pattern TEMP_SPLIT = Pattern.compile("\\$");

View File

@ -580,7 +580,7 @@ public abstract class PermissionObject {
if (group != null) { if (group != null) {
perms.putAll(group.getLocalPermissions(server, excludedGroups)); perms.putAll(group.getLocalPermissions(server, excludedGroups));
} else { } else {
plugin.getLogger().warning("Error whilst refreshing the permissions of '" + objectName + "'." + plugin.getLog().warn("Error whilst refreshing the permissions of '" + objectName + "'." +
"\n The group '" + groupName + "' is not loaded."); "\n The group '" + groupName + "' is not loaded.");
} }
} }
@ -603,7 +603,7 @@ public abstract class PermissionObject {
if (group != null) { if (group != null) {
perms.putAll(group.getLocalPermissions(server, excludedGroups)); perms.putAll(group.getLocalPermissions(server, excludedGroups));
} else { } else {
plugin.getLogger().warning("Error whilst refreshing the permissions of '" + objectName + "'." + plugin.getLog().warn("Error whilst refreshing the permissions of '" + objectName + "'." +
"\n The group '" + groupName + "' is not loaded."); "\n The group '" + groupName + "' is not loaded.");
} }
} }

11
pom.xml
View File

@ -7,12 +7,13 @@
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<artifactId>luckperms</artifactId> <artifactId>luckperms</artifactId>
<version>1.4</version> <version>1.5</version>
<modules> <modules>
<module>bukkit</module>
<module>common</module> <module>common</module>
<module>bungee</module>
<module>api</module> <module>api</module>
<module>bukkit</module>
<module>bungee</module>
<module>sponge</module>
</modules> </modules>
<packaging>pom</packaging> <packaging>pom</packaging>
@ -33,6 +34,10 @@
<id>luck-repo</id> <id>luck-repo</id>
<url>https://repo.lucko.me/</url> <url>https://repo.lucko.me/</url>
</repository> </repository>
<repository>
<id>sponge-repo</id>
<url>https://repo.spongepowered.org/maven</url>
</repository>
</repositories> </repositories>
<dependencies> <dependencies>

79
sponge/pom.xml Normal file
View File

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>1.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>luckperms-sponge</artifactId>
<version>1.5</version>
<packaging>jar</packaging>
<name>LuckPerms</name>
<build>
<defaultGoal>clean package</defaultGoal>
<finalName>LuckPermsSponge</finalName>
<sourceDirectory>${basedir}/src/main/java</sourceDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<!-- Sponge API -->
<dependency>
<groupId>org.spongepowered</groupId>
<artifactId>spongeapi</artifactId>
<version>4.1.0</version>
<scope>provided</scope>
</dependency>
<!-- LuckPerms Common -->
<dependency>
<groupId>me.lucko.luckperms</groupId>
<artifactId>luckperms-common</artifactId>
<version>1.5</version>
<scope>compile</scope>
</dependency>
<!-- LuckPerms API -->
<dependency>
<groupId>me.lucko.luckperms</groupId>
<artifactId>luckperms-api</artifactId>
<version>1.5</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,178 @@
package me.lucko.luckperms;
import com.google.inject.Inject;
import lombok.Getter;
import me.lucko.luckperms.api.LuckPermsApi;
import me.lucko.luckperms.api.implementation.ApiProvider;
import me.lucko.luckperms.data.Datastore;
import me.lucko.luckperms.data.methods.FlatfileDatastore;
import me.lucko.luckperms.data.methods.MySQLDatastore;
import me.lucko.luckperms.data.methods.SQLiteDatastore;
import me.lucko.luckperms.groups.GroupManager;
import me.lucko.luckperms.listeners.PlayerListener;
import me.lucko.luckperms.runnables.UpdateTask;
import me.lucko.luckperms.tracks.TrackManager;
import me.lucko.luckperms.users.SpongeUserManager;
import me.lucko.luckperms.users.UserManager;
import me.lucko.luckperms.utils.LPConfiguration;
import me.lucko.luckperms.utils.LogUtil;
import me.lucko.luckperms.utils.UuidCache;
import org.slf4j.Logger;
import org.spongepowered.api.Game;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.command.CommandManager;
import org.spongepowered.api.config.ConfigDir;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.game.state.GamePreInitializationEvent;
import org.spongepowered.api.event.game.state.GameStoppingServerEvent;
import org.spongepowered.api.plugin.Plugin;
import org.spongepowered.api.scheduler.Scheduler;
import java.io.File;
import java.nio.file.Path;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Getter
@Plugin(id = "luckperms", name = "LuckPerms", version = LPSpongePlugin.VERSION)
public class LPSpongePlugin implements LuckPermsPlugin {
static final String VERSION = "1.5"; // TODO load this from pom
@Inject
private Logger logger;
@Inject
private Game game;
@Inject
@ConfigDir(sharedRoot = false)
private Path configDir;
private Scheduler scheduler = Sponge.getScheduler();
private LPConfiguration configuration;
private UserManager userManager;
private GroupManager groupManager;
private TrackManager trackManager;
private Datastore datastore;
private UuidCache uuidCache;
@Listener
public void onEnable(GamePreInitializationEvent event) {
getLog().info("Loading configuration...");
configuration = new SpongeConfig(this);
// register events
Sponge.getEventManager().registerListeners(this, new PlayerListener(this));
// register commands
getLog().info("Registering commands...");
CommandManager cmdService = Sponge.getCommandManager();
cmdService.register(this, new SpongeCommand(this), "luckperms", "perms", "lp", "permissions", "p", "perm");
getLog().info("Detecting storage method...");
final String storageMethod = configuration.getStorageMethod();
if (storageMethod.equalsIgnoreCase("mysql")) {
getLog().info("Using MySQL as storage method.");
datastore = new MySQLDatastore(this, configuration.getDatabaseValues());
} else if (storageMethod.equalsIgnoreCase("sqlite")) {
getLog().info("Using SQLite as storage method.");
datastore = new SQLiteDatastore(this, new File(getStorageDir(), "luckperms.sqlite"));
} else if (storageMethod.equalsIgnoreCase("flatfile")) {
getLog().info("Using Flatfile (JSON) as storage method.");
datastore = new FlatfileDatastore(this, getStorageDir());
} else {
getLog().severe("Storage method '" + storageMethod + "' was not recognised. Using SQLite as fallback.");
datastore = new SQLiteDatastore(this, new File(getStorageDir(), "luckperms.sqlite"));
}
getLog().info("Initialising datastore...");
datastore.init();
getLog().info("Loading internal permission managers...");
uuidCache = new UuidCache(getConfiguration().getOnlineMode());
userManager = new SpongeUserManager(this);
groupManager = new GroupManager(this);
trackManager = new TrackManager();
// Run update task to refresh any online users
getLog().info("Scheduling Update Task to refresh any online users.");
try {
new UpdateTask(this).run();
} catch (Exception e) {
e.printStackTrace();
}
int mins = getConfiguration().getSyncTime();
if (mins > 0) {
scheduler.createTaskBuilder().async().interval(mins, TimeUnit.MINUTES).execute(new UpdateTask(this))
.submit(LPSpongePlugin.this);
}
getLog().info("Registering API...");
final ApiProvider provider = new ApiProvider(this);
LuckPerms.registerProvider(provider);
Sponge.getServiceManager().setProvider(this, LuckPermsApi.class, provider);
getLog().info("Successfully loaded.");
}
@Listener
public void onDisable(GameStoppingServerEvent event) {
getLog().info("Closing datastore...");
datastore.shutdown();
getLog().info("Unregistering API...");
LuckPerms.unregisterProvider();
}
private File getStorageDir() {
File base = configDir.toFile().getParentFile().getParentFile();
File luckperms = new File(base, "luckperms");
luckperms.mkdirs();
return luckperms;
}
@Override
public me.lucko.luckperms.api.Logger getLog() {
return LogUtil.wrap(getLogger());
}
@Override
public String getVersion() {
return VERSION;
}
@Override
public String getPlayerStatus(UUID uuid) {
return game.getServer().getPlayer(getUuidCache().getExternalUUID(uuid)).isPresent() ? "&aOnline" : "&cOffline";
}
@Override
public int getPlayerCount() {
return game.getServer().getOnlinePlayers().size();
}
@Override
public List<String> getPlayerList() {
return game.getServer().getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList());
}
@Override
public void runUpdateTask() {
scheduler.createTaskBuilder().async().execute(new UpdateTask(this)).submit(LPSpongePlugin.this);
}
@Override
public void doAsync(Runnable r) {
scheduler.createTaskBuilder().async().execute(r).submit(LPSpongePlugin.this);
}
@Override
public void doSync(Runnable r) {
scheduler.createTaskBuilder().execute(r).submit(LPSpongePlugin.this);
}
}

View File

@ -0,0 +1,74 @@
package me.lucko.luckperms;
import me.lucko.luckperms.commands.CommandManager;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.utils.Patterns;
import org.spongepowered.api.command.CommandCallable;
import org.spongepowered.api.command.CommandException;
import org.spongepowered.api.command.CommandResult;
import org.spongepowered.api.command.CommandSource;
import org.spongepowered.api.text.Text;
import org.spongepowered.api.text.serializer.TextSerializers;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class SpongeCommand extends CommandManager implements CommandCallable {
public SpongeCommand(LuckPermsPlugin plugin) {
super(plugin);
}
@Override
public CommandResult process(CommandSource source, String s) throws CommandException {
onCommand(makeSender(source), "perms", Arrays.asList(Patterns.SPACE_SPLIT.split(s)));
return CommandResult.success();
}
@Override
public List<String> getSuggestions(CommandSource source, String s) throws CommandException {
return onTabComplete(makeSender(source), Arrays.asList(Patterns.SPACE_SPLIT.split(s)));
}
@Override
public boolean testPermission(CommandSource commandSource) {
return true;
}
@Override
public Optional<? extends Text> getShortDescription(CommandSource commandSource) {
return Optional.of(Text.of("LuckPerms main command."));
}
@Override
public Optional<? extends Text> getHelp(CommandSource commandSource) {
return Optional.of(Text.of("Type /perms for help."));
}
@Override
public Text getUsage(CommandSource commandSource) {
return Text.of("/perms");
}
private static Sender makeSender(CommandSource source) {
return new Sender() {
final WeakReference<CommandSource> cs = new WeakReference<>(source);
@SuppressWarnings("deprecation")
@Override
public void sendMessage(String s) {
final CommandSource c = cs.get();
if (c != null) {
c.sendMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(s));
}
}
@Override
public boolean hasPermission(String node) {
final CommandSource c = cs.get();
return c != null && c.hasPermission(node);
}
};
}
}

View File

@ -0,0 +1,79 @@
package me.lucko.luckperms;
import me.lucko.luckperms.utils.LPConfiguration;
import ninja.leaping.configurate.ConfigurationNode;
import ninja.leaping.configurate.commented.CommentedConfigurationNode;
import ninja.leaping.configurate.hocon.HoconConfigurationLoader;
import ninja.leaping.configurate.loader.ConfigurationLoader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
class SpongeConfig extends LPConfiguration<LPSpongePlugin> {
private ConfigurationNode root;
SpongeConfig(LPSpongePlugin plugin) {
super(plugin, "global", true, "sqlite");
}
@SuppressWarnings("ResultOfMethodCallIgnored")
private Path makeFile(Path file) throws IOException {
File cfg = file.toFile();
cfg.getParentFile().mkdirs();
if (!cfg.exists()) {
try (InputStream is = getPlugin().getClass().getClassLoader().getResourceAsStream("luckperms.conf")) {
Files.copy(is, cfg.toPath());
}
}
return cfg.toPath();
}
@Override
protected void init() {
try {
ConfigurationLoader<CommentedConfigurationNode> loader = HoconConfigurationLoader.builder()
.setPath(makeFile(getPlugin().getConfigDir().resolve("luckperms.conf")))
.build();
root = loader.load();
} catch (IOException e) {
e.printStackTrace();
}
}
private ConfigurationNode getNode(String path) {
String[] paths = path.split("\\.");
ConfigurationNode node = root;
for (String s : paths) {
node = node.getNode(s);
}
return node;
}
@Override
protected void set(String path, Object value) {
getNode(path).setValue(value);
}
@Override
protected String getString(String path, String def) {
return getNode(path).getString(def);
}
@Override
protected int getInt(String path, int def) {
return getNode(path).getInt(def);
}
@Override
protected boolean getBoolean(String path, boolean def) {
return getNode(path).getBoolean(def);
}
}

View File

@ -0,0 +1,107 @@
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();
}
}
}

View File

@ -0,0 +1,41 @@
package me.lucko.luckperms.users;
import me.lucko.luckperms.LPSpongePlugin;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.util.Tristate;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
class SpongeUser extends User {
private final LPSpongePlugin plugin;
SpongeUser(UUID uuid, LPSpongePlugin plugin) {
super(uuid, plugin);
this.plugin = plugin;
}
SpongeUser(UUID uuid, String username, LPSpongePlugin plugin) {
super(uuid, username, plugin);
this.plugin = plugin;
}
@Override
public void refreshPermissions() {
Optional<Player> p = plugin.getGame().getServer().getPlayer(plugin.getUuidCache().getExternalUUID(getUuid()));
if (!p.isPresent()) return;
final Player player = p.get();
// Clear existing permissions
player.getSubjectData().clearParents();
player.getSubjectData().clearPermissions();
// Re-add all defined permissions for the user
final String world = player.getWorld().getName();
Map<String, Boolean> local = getLocalPermissions(getPlugin().getConfiguration().getServer(), world, null);
local.entrySet().forEach(e -> player.getSubjectData().setPermission(new HashSet<>(), e.getKey(), Tristate.fromBoolean(e.getValue())));
}
}

View File

@ -0,0 +1,52 @@
package me.lucko.luckperms.users;
import me.lucko.luckperms.LPSpongePlugin;
import org.spongepowered.api.entity.living.player.Player;
import java.util.Optional;
import java.util.UUID;
public class SpongeUserManager extends UserManager {
private final LPSpongePlugin plugin;
public SpongeUserManager(LPSpongePlugin plugin) {
super(plugin);
this.plugin = plugin;
}
@Override
public void unloadUser(User user) {
if (user != null) {
Optional<Player> p = plugin.getGame().getServer().getPlayer(plugin.getUuidCache().getExternalUUID(user.getUuid()));
if (p.isPresent()) {
p.get().getSubjectData().clearParents();
p.get().getSubjectData().clearPermissions();
}
getUsers().remove(user.getUuid());
}
}
@Override
public void cleanupUser(User user) {
if (plugin.getGame().getServer().getPlayer(plugin.getUuidCache().getExternalUUID(user.getUuid())).isPresent()) {
unloadUser(user);
}
}
@Override
public User makeUser(UUID uuid) {
return new SpongeUser(uuid, plugin);
}
@Override
public User makeUser(UUID uuid, String username) {
return new SpongeUser(uuid, username, plugin);
}
@Override
public void updateAllUsers() {
plugin.getGame().getServer().getOnlinePlayers().stream()
.map(p -> plugin.getUuidCache().getUUID(p.getUniqueId()))
.forEach(u -> plugin.getDatastore().loadUser(u));
}
}

View File

@ -0,0 +1,36 @@
# LuckPerms Configuration
# The name of the server, used for server specific permissions. Set to 'global' to disable.
server="global"
# The default group assigned to all users on their first join.
default-group="default"
# If users on this server should have their global permissions/groups applied.
include-global=true
# If this server is in offline or online mode.
# This setting allows a player to have the same UUID across a network of offline mode/mixed servers.
# You should generally reflect the setting in server.properties here. Except when...
# 1. You have Spigot servers connected to a BungeeCord proxy, with online-mode set to false, but 'bungeecord' set to
# true in the spigot.yml AND 'ip-forward' set to true in the BungeeCord config.yml
# In this case, set online-mode in LuckPerms to true, despite the server being in offline mode.
# 2. You are only running one server instance using LuckPerms, (not a network) In this case, set online-mode to true no
# matter what is set in server.properties. (we can just fallback to the servers uuid cache)
online-mode=true
# Which storage method the plugin should use.
# Currently supported: mysql, sqlite, flatfile
# Fill out connection info below if you're using MySQL
storage-method="sqlite"
sql: {
address="localhost:3306"
database="minecraft"
username="root"
password=""
sync-minutes=3
}