mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-12-17 22:57:49 +01:00
Add support for Velocity
This commit is contained in:
parent
bd41286076
commit
55220e9d10
@ -37,7 +37,8 @@ public enum PlatformType {
|
|||||||
BUKKIT("Bukkit"),
|
BUKKIT("Bukkit"),
|
||||||
BUNGEE("Bungee"),
|
BUNGEE("Bungee"),
|
||||||
SPONGE("Sponge"),
|
SPONGE("Sponge"),
|
||||||
NUKKIT("Nukkit");
|
NUKKIT("Nukkit"),
|
||||||
|
VELOCITY("Velocity");
|
||||||
|
|
||||||
private final String friendlyName;
|
private final String friendlyName;
|
||||||
|
|
||||||
|
@ -42,9 +42,9 @@ public class BukkitMessagingFactory extends MessagingFactory<LPBukkitPlugin> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected InternalMessagingService getServiceFor(String messagingType) {
|
protected InternalMessagingService getServiceFor(String messagingType) {
|
||||||
if (messagingType.equals("bungee")) {
|
if (messagingType.equals("pluginmsg") || messagingType.equals("bungee") || messagingType.equals("velocity")) {
|
||||||
try {
|
try {
|
||||||
return new LuckPermsMessagingService(getPlugin(), new BungeeMessengerProvider());
|
return new LuckPermsMessagingService(getPlugin(), new PluginMessageMessengerProvider());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -63,20 +63,20 @@ public class BukkitMessagingFactory extends MessagingFactory<LPBukkitPlugin> {
|
|||||||
return super.getServiceFor(messagingType);
|
return super.getServiceFor(messagingType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BungeeMessengerProvider implements MessengerProvider {
|
private class PluginMessageMessengerProvider implements MessengerProvider {
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Bungee";
|
return "PluginMessage";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Messenger obtain(@Nonnull IncomingMessageConsumer incomingMessageConsumer) {
|
public Messenger obtain(@Nonnull IncomingMessageConsumer incomingMessageConsumer) {
|
||||||
BungeeMessenger bungeeMessaging = new BungeeMessenger(getPlugin(), incomingMessageConsumer);
|
PluginMessageMessenger messenger = new PluginMessageMessenger(getPlugin(), incomingMessageConsumer);
|
||||||
bungeeMessaging.init();
|
messenger.init();
|
||||||
return bungeeMessaging;
|
return messenger;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,9 +91,9 @@ public class BukkitMessagingFactory extends MessagingFactory<LPBukkitPlugin> {
|
|||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Messenger obtain(@Nonnull IncomingMessageConsumer incomingMessageConsumer) {
|
public Messenger obtain(@Nonnull IncomingMessageConsumer incomingMessageConsumer) {
|
||||||
LilyPadMessenger lilyPadMessaging = new LilyPadMessenger(getPlugin(), incomingMessageConsumer);
|
LilyPadMessenger messenger = new LilyPadMessenger(getPlugin(), incomingMessageConsumer);
|
||||||
lilyPadMessaging.init();
|
messenger.init();
|
||||||
return lilyPadMessaging;
|
return messenger;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,13 +46,13 @@ import javax.annotation.Nonnull;
|
|||||||
/**
|
/**
|
||||||
* An implementation of {@link Messenger} using the plugin messaging channels.
|
* An implementation of {@link Messenger} using the plugin messaging channels.
|
||||||
*/
|
*/
|
||||||
public class BungeeMessenger implements Messenger, PluginMessageListener {
|
public class PluginMessageMessenger implements Messenger, PluginMessageListener {
|
||||||
private static final String CHANNEL = "luckperms:update";
|
private static final String CHANNEL = "luckperms:update";
|
||||||
|
|
||||||
private final LPBukkitPlugin plugin;
|
private final LPBukkitPlugin plugin;
|
||||||
private final IncomingMessageConsumer consumer;
|
private final IncomingMessageConsumer consumer;
|
||||||
|
|
||||||
public BungeeMessenger(LPBukkitPlugin plugin, IncomingMessageConsumer consumer) {
|
public PluginMessageMessenger(LPBukkitPlugin plugin, IncomingMessageConsumer consumer) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.consumer = consumer;
|
this.consumer = consumer;
|
||||||
}
|
}
|
||||||
@ -73,7 +73,7 @@ public class BungeeMessenger implements Messenger, PluginMessageListener {
|
|||||||
new BukkitRunnable() {
|
new BukkitRunnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Collection<? extends Player> players = BungeeMessenger.this.plugin.getBootstrap().getServer().getOnlinePlayers();
|
Collection<? extends Player> players = PluginMessageMessenger.this.plugin.getBootstrap().getServer().getOnlinePlayers();
|
||||||
Player p = Iterables.getFirst(players, null);
|
Player p = Iterables.getFirst(players, null);
|
||||||
if (p == null) {
|
if (p == null) {
|
||||||
return;
|
return;
|
||||||
@ -84,7 +84,7 @@ public class BungeeMessenger implements Messenger, PluginMessageListener {
|
|||||||
|
|
||||||
byte[] data = out.toByteArray();
|
byte[] data = out.toByteArray();
|
||||||
|
|
||||||
p.sendPluginMessage(BungeeMessenger.this.plugin.getBootstrap(), CHANNEL, data);
|
p.sendPluginMessage(PluginMessageMessenger.this.plugin.getBootstrap(), CHANNEL, data);
|
||||||
cancel();
|
cancel();
|
||||||
}
|
}
|
||||||
}.runTaskTimer(this.plugin.getBootstrap(), 1L, 100L);
|
}.runTaskTimer(this.plugin.getBootstrap(), 1L, 100L);
|
@ -205,9 +205,9 @@ watch-files: true
|
|||||||
# => sql Uses the SQL database to form a queue system for communication. Will only work when
|
# => sql Uses the SQL database to form a queue system for communication. Will only work when
|
||||||
# 'storage-method' is set to MySQL or MariaDB. This is chosen by default if the
|
# 'storage-method' is set to MySQL or MariaDB. This is chosen by default if the
|
||||||
# option is set to 'none' and SQL storage is in use. Set to 'notsql' to disable this.
|
# option is set to 'none' and SQL storage is in use. Set to 'notsql' to disable this.
|
||||||
# => bungee Uses the plugin messaging channels to communicate with the proxy.
|
# => pluginmsg Uses the plugin messaging channels to communicate with the proxy.
|
||||||
# LuckPerms must be installed on your proxy & all connected servers backend servers.
|
# LuckPerms must be installed on your proxy & all connected servers backend servers.
|
||||||
# Won't work if you have more than one BungeeCord proxy.
|
# Won't work if you have more than one proxy.
|
||||||
# => lilypad Uses LilyPad pub-sub to push changes. You need to have the LilyPad-Connect plugin
|
# => lilypad Uses LilyPad pub-sub to push changes. You need to have the LilyPad-Connect plugin
|
||||||
# installed.
|
# installed.
|
||||||
# => redis Uses Redis pub-sub to push changes. Your server connection info must be configured
|
# => redis Uses Redis pub-sub to push changes. Your server connection info must be configured
|
||||||
|
@ -42,9 +42,9 @@ public class BungeeMessagingFactory extends MessagingFactory<LPBungeePlugin> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected InternalMessagingService getServiceFor(String messagingType) {
|
protected InternalMessagingService getServiceFor(String messagingType) {
|
||||||
if (messagingType.equals("bungee")) {
|
if (messagingType.equals("pluginmsg") || messagingType.equals("bungee")) {
|
||||||
try {
|
try {
|
||||||
return new LuckPermsMessagingService(getPlugin(), new BungeeMessengerProvider());
|
return new LuckPermsMessagingService(getPlugin(), new PluginMessageMessengerProvider());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -63,20 +63,20 @@ public class BungeeMessagingFactory extends MessagingFactory<LPBungeePlugin> {
|
|||||||
return super.getServiceFor(messagingType);
|
return super.getServiceFor(messagingType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BungeeMessengerProvider implements MessengerProvider {
|
private class PluginMessageMessengerProvider implements MessengerProvider {
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Bungee";
|
return "PluginMessage";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Messenger obtain(@Nonnull IncomingMessageConsumer incomingMessageConsumer) {
|
public Messenger obtain(@Nonnull IncomingMessageConsumer incomingMessageConsumer) {
|
||||||
BungeeMessenger bungeeMessaging = new BungeeMessenger(getPlugin(), incomingMessageConsumer);
|
PluginMessageMessenger messenger = new PluginMessageMessenger(getPlugin(), incomingMessageConsumer);
|
||||||
bungeeMessaging.init();
|
messenger.init();
|
||||||
return bungeeMessaging;
|
return messenger;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,9 +91,9 @@ public class BungeeMessagingFactory extends MessagingFactory<LPBungeePlugin> {
|
|||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Messenger obtain(@Nonnull IncomingMessageConsumer incomingMessageConsumer) {
|
public Messenger obtain(@Nonnull IncomingMessageConsumer incomingMessageConsumer) {
|
||||||
RedisBungeeMessenger redisBungeeMessaging = new RedisBungeeMessenger(getPlugin(), incomingMessageConsumer);
|
RedisBungeeMessenger messenger = new RedisBungeeMessenger(getPlugin(), incomingMessageConsumer);
|
||||||
redisBungeeMessaging.init();
|
messenger.init();
|
||||||
return redisBungeeMessaging;
|
return messenger;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,13 +45,13 @@ import javax.annotation.Nonnull;
|
|||||||
/**
|
/**
|
||||||
* An implementation of {@link Messenger} using the plugin messaging channels.
|
* An implementation of {@link Messenger} using the plugin messaging channels.
|
||||||
*/
|
*/
|
||||||
public class BungeeMessenger implements Messenger, Listener {
|
public class PluginMessageMessenger implements Messenger, Listener {
|
||||||
private static final String CHANNEL = "luckperms:update";
|
private static final String CHANNEL = "luckperms:update";
|
||||||
|
|
||||||
private final LPBungeePlugin plugin;
|
private final LPBungeePlugin plugin;
|
||||||
private final IncomingMessageConsumer consumer;
|
private final IncomingMessageConsumer consumer;
|
||||||
|
|
||||||
public BungeeMessenger(LPBungeePlugin plugin, IncomingMessageConsumer consumer) {
|
public PluginMessageMessenger(LPBungeePlugin plugin, IncomingMessageConsumer consumer) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.consumer = consumer;
|
this.consumer = consumer;
|
||||||
}
|
}
|
||||||
@ -74,7 +74,7 @@ public class BungeeMessenger implements Messenger, Listener {
|
|||||||
byte[] data = out.toByteArray();
|
byte[] data = out.toByteArray();
|
||||||
|
|
||||||
for (ServerInfo server : this.plugin.getBootstrap().getProxy().getServers().values()) {
|
for (ServerInfo server : this.plugin.getBootstrap().getProxy().getServers().values()) {
|
||||||
server.sendData(CHANNEL, data, true);
|
server.sendData(CHANNEL, data, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ public class BungeeMessenger implements Messenger, Listener {
|
|||||||
// Forward to other servers
|
// Forward to other servers
|
||||||
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||||
for (ServerInfo server : this.plugin.getBootstrap().getProxy().getServers().values()) {
|
for (ServerInfo server : this.plugin.getBootstrap().getProxy().getServers().values()) {
|
||||||
server.sendData(CHANNEL, data, true);
|
server.sendData(CHANNEL, data, false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
@ -203,7 +203,7 @@ watch-files: true
|
|||||||
# when 'storage-method' is set to MySQL or MariaDB. This is chosen by default if
|
# when 'storage-method' is set to MySQL or MariaDB. This is chosen by default if
|
||||||
# the option is set to 'none' and SQL storage is in use. Set to 'notsql' to
|
# the option is set to 'none' and SQL storage is in use. Set to 'notsql' to
|
||||||
# disable this.
|
# disable this.
|
||||||
# => bungee Uses the plugin messaging channels to communicate with the proxy.
|
# => pluginmsg Uses the plugin messaging channels to communicate with the proxy.
|
||||||
# LuckPerms must be installed on your proxy & all connected servers backend
|
# LuckPerms must be installed on your proxy & all connected servers backend
|
||||||
# servers. Won't work if you have more than one BungeeCord proxy.
|
# servers. Won't work if you have more than one BungeeCord proxy.
|
||||||
# => redis Uses Redis pub-sub to push changes. Your server connection info must be
|
# => redis Uses Redis pub-sub to push changes. Your server connection info must be
|
||||||
|
@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of LuckPerms, licensed under the MIT License.
|
||||||
|
*
|
||||||
|
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package me.lucko.luckperms.common.config.adapter;
|
||||||
|
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
|
|
||||||
|
import ninja.leaping.configurate.ConfigurationNode;
|
||||||
|
import ninja.leaping.configurate.loader.AbstractConfigurationLoader;
|
||||||
|
import ninja.leaping.configurate.loader.ConfigurationLoader;
|
||||||
|
import ninja.leaping.configurate.yaml.YAMLConfigurationLoader;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public abstract class ConfigurateConfigAdapter extends AbstractConfigurationAdapter implements ConfigurationAdapter {
|
||||||
|
|
||||||
|
private final Path path;
|
||||||
|
private ConfigurationNode root;
|
||||||
|
|
||||||
|
public ConfigurateConfigAdapter(LuckPermsPlugin plugin, Path path) {
|
||||||
|
super(plugin);
|
||||||
|
this.path = path;
|
||||||
|
reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract ConfigurationLoader<? extends ConfigurationNode> createLoader(Path path);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reload() {
|
||||||
|
ConfigurationLoader<? extends ConfigurationNode> loader = createLoader(this.path);
|
||||||
|
try {
|
||||||
|
this.root = loader.load();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ConfigurationNode resolvePath(String path) {
|
||||||
|
if (this.root == null) {
|
||||||
|
throw new RuntimeException("Config is not loaded.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.root.getNode(Splitter.on('.').splitToList(path).toArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getString(String path, String def) {
|
||||||
|
return resolvePath(path).getString(def);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getInt(String path, int def) {
|
||||||
|
return resolvePath(path).getInt(def);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getBoolean(String path, boolean def) {
|
||||||
|
return resolvePath(path).getBoolean(def);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getList(String path, List<String> def) {
|
||||||
|
ConfigurationNode node = resolvePath(path);
|
||||||
|
if (node.isVirtual()) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node.getList(Object::toString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getKeys(String path, List<String> def) {
|
||||||
|
ConfigurationNode node = resolvePath(path);
|
||||||
|
if (node.isVirtual()) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node.getChildrenMap().keySet().stream().map(Object::toString).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getMap(String path, Map<String, String> def) {
|
||||||
|
ConfigurationNode node = resolvePath(path);
|
||||||
|
if (node.isVirtual()) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> m = (Map<String, Object>) node.getValue(Collections.emptyMap());
|
||||||
|
return m.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, v -> v.getValue().toString()));
|
||||||
|
}
|
||||||
|
}
|
@ -210,6 +210,13 @@ public enum Dependency {
|
|||||||
"Dxr1o3EPbpOOmwraqu+cors8O/nKwJnhS5EiPkTb3fc=",
|
"Dxr1o3EPbpOOmwraqu+cors8O/nKwJnhS5EiPkTb3fc=",
|
||||||
Relocation.of("configurate", "ninja{}leaping{}configurate")
|
Relocation.of("configurate", "ninja{}leaping{}configurate")
|
||||||
),
|
),
|
||||||
|
SNAKEYAML(
|
||||||
|
"org.yaml",
|
||||||
|
"snakeyaml",
|
||||||
|
"1.21",
|
||||||
|
"5DywaD9wgEuDPfqlrAMv8Uugx1jUoenq62ZAUV34P68=",
|
||||||
|
Relocation.of("yaml", "org{}yaml{}snakeyaml")
|
||||||
|
),
|
||||||
CONFIGURATE_HOCON(
|
CONFIGURATE_HOCON(
|
||||||
"me{}lucko{}configurate",
|
"me{}lucko{}configurate",
|
||||||
"configurate-hocon",
|
"configurate-hocon",
|
||||||
|
@ -153,7 +153,7 @@ public class DependencyManager {
|
|||||||
try {
|
try {
|
||||||
// apply remap rules
|
// apply remap rules
|
||||||
List<Relocation> relocations = new ArrayList<>(source.dependency.getRelocations());
|
List<Relocation> relocations = new ArrayList<>(source.dependency.getRelocations());
|
||||||
relocations.addAll(this.registry.getLegacyRelocations(source.dependency));
|
this.registry.applyRelocationSettings(source.dependency, relocations);
|
||||||
|
|
||||||
if (relocations.isEmpty()) {
|
if (relocations.isEmpty()) {
|
||||||
remappedJars.add(source);
|
remappedJars.add(source);
|
||||||
|
@ -29,6 +29,7 @@ import com.google.common.collect.ImmutableList;
|
|||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.api.platform.PlatformType;
|
||||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||||
import me.lucko.luckperms.common.dependencies.relocation.Relocation;
|
import me.lucko.luckperms.common.dependencies.relocation.Relocation;
|
||||||
import me.lucko.luckperms.common.dependencies.relocation.RelocationHandler;
|
import me.lucko.luckperms.common.dependencies.relocation.RelocationHandler;
|
||||||
@ -86,19 +87,24 @@ public class DependencyRegistry {
|
|||||||
return dependencies;
|
return dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
// support for LuckPerms legacy (bukkit 1.7.10)
|
public void applyRelocationSettings(Dependency dependency, List<Relocation> relocations) {
|
||||||
public List<Relocation> getLegacyRelocations(Dependency dependency) {
|
PlatformType type = this.plugin.getBootstrap().getType();
|
||||||
if (RelocationHandler.DEPENDENCIES.contains(dependency)) {
|
|
||||||
return ImmutableList.of();
|
// support for LuckPerms legacy (bukkit 1.7.10)
|
||||||
|
if (!RelocationHandler.DEPENDENCIES.contains(dependency) && JsonElement.class.getName().startsWith("me.lucko")) {
|
||||||
|
relocations.add(Relocation.of("guava", "com{}google{}common"));
|
||||||
|
relocations.add(Relocation.of("gson", "com{}google{}gson"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (JsonElement.class.getName().startsWith("me.lucko")) {
|
// don't relocate text when running on Velocity
|
||||||
return ImmutableList.of(
|
if (dependency == Dependency.TEXT && type == PlatformType.VELOCITY) {
|
||||||
Relocation.of("guava", "com{}google{}common"),
|
relocations.remove(Relocation.of("text", "net{}kyori{}text"));
|
||||||
Relocation.of("gson", "com{}google{}gson")
|
}
|
||||||
);
|
|
||||||
|
// relocate yaml within configurate when running velocity
|
||||||
|
if (dependency == Dependency.CONFIGURATE_YAML && type == PlatformType.VELOCITY) {
|
||||||
|
relocations.add(Relocation.of("yaml", "org{}yaml{}snakeyaml"));
|
||||||
}
|
}
|
||||||
return ImmutableList.of();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean classExists(String className) {
|
private static boolean classExists(String className) {
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.common.dependencies.classloader;
|
package me.lucko.luckperms.common.dependencies.classloader;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
||||||
@ -33,8 +34,6 @@ import java.nio.file.Path;
|
|||||||
*/
|
*/
|
||||||
public interface PluginClassLoader {
|
public interface PluginClassLoader {
|
||||||
|
|
||||||
void loadJar(URL url);
|
|
||||||
|
|
||||||
void loadJar(Path file);
|
void loadJar(Path file);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -55,20 +55,11 @@ public class ReflectionClassLoader implements PluginClassLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void loadJar(URL url) {
|
|
||||||
try {
|
|
||||||
ADD_URL_METHOD.invoke(this.classLoader, url);
|
|
||||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadJar(Path file) {
|
public void loadJar(Path file) {
|
||||||
try {
|
try {
|
||||||
loadJar(file.toUri().toURL());
|
ADD_URL_METHOD.invoke(this.classLoader, file.toUri().toURL());
|
||||||
} catch (MalformedURLException e) {
|
} catch (IllegalAccessException | InvocationTargetException | MalformedURLException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ package me.lucko.luckperms.common.dependencies.relocation;
|
|||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public final class Relocation {
|
public final class Relocation {
|
||||||
private static final String RELOCATION_PREFIX = "me.lucko.luckperms.lib.";
|
private static final String RELOCATION_PREFIX = "me.lucko.luckperms.lib.";
|
||||||
@ -55,4 +56,17 @@ public final class Relocation {
|
|||||||
return this.relocatedPattern;
|
return this.relocatedPattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Relocation that = (Relocation) o;
|
||||||
|
return Objects.equals(this.pattern, that.pattern) &&
|
||||||
|
Objects.equals(this.relocatedPattern, that.relocatedPattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(this.pattern, this.relocatedPattern);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
rootProject.name = 'luckperms'
|
rootProject.name = 'luckperms'
|
||||||
include 'api', 'common', 'bukkit', 'bukkit-legacy', 'bungee', 'sponge', 'sponge:sponge-service', 'sponge:sponge-service-api6', 'sponge:sponge-service-api7', 'nukkit'
|
include (
|
||||||
|
'api',
|
||||||
|
'common',
|
||||||
|
'bukkit',
|
||||||
|
'bukkit-legacy',
|
||||||
|
'bungee',
|
||||||
|
'sponge', 'sponge:sponge-service', 'sponge:sponge-service-api6', 'sponge:sponge-service-api7',
|
||||||
|
'nukkit',
|
||||||
|
'velocity'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -202,10 +202,6 @@ public class LPSpongeBootstrap implements LuckPermsBootstrap {
|
|||||||
return this.spongeScheduler;
|
return this.spongeScheduler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Path getConfigPath() {
|
|
||||||
return this.configDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PluginContainer getPluginContainer() {
|
public PluginContainer getPluginContainer() {
|
||||||
return this.pluginContainer;
|
return this.pluginContainer;
|
||||||
}
|
}
|
||||||
|
@ -222,10 +222,10 @@ public class LPSpongePlugin extends AbstractLuckPermsPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Path resolveConfig() {
|
private Path resolveConfig() {
|
||||||
Path path = this.bootstrap.getConfigPath().resolve("luckperms.conf");
|
Path path = this.bootstrap.getConfigDirectory().resolve("luckperms.conf");
|
||||||
if (!Files.exists(path)) {
|
if (!Files.exists(path)) {
|
||||||
try {
|
try {
|
||||||
MoreFiles.createDirectoriesIfNotExists(this.bootstrap.getConfigPath());
|
MoreFiles.createDirectoriesIfNotExists(this.bootstrap.getConfigDirectory());
|
||||||
try (InputStream is = getClass().getClassLoader().getResourceAsStream("luckperms.conf")) {
|
try (InputStream is = getClass().getClassLoader().getResourceAsStream("luckperms.conf")) {
|
||||||
Files.copy(is, path);
|
Files.copy(is, path);
|
||||||
}
|
}
|
||||||
|
@ -25,98 +25,23 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.sponge;
|
package me.lucko.luckperms.sponge;
|
||||||
|
|
||||||
import com.google.common.base.Splitter;
|
import me.lucko.luckperms.common.config.adapter.ConfigurateConfigAdapter;
|
||||||
|
|
||||||
import me.lucko.luckperms.common.config.adapter.AbstractConfigurationAdapter;
|
|
||||||
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
||||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
|
|
||||||
import ninja.leaping.configurate.ConfigurationNode;
|
import ninja.leaping.configurate.ConfigurationNode;
|
||||||
import ninja.leaping.configurate.commented.CommentedConfigurationNode;
|
|
||||||
import ninja.leaping.configurate.hocon.HoconConfigurationLoader;
|
import ninja.leaping.configurate.hocon.HoconConfigurationLoader;
|
||||||
import ninja.leaping.configurate.loader.ConfigurationLoader;
|
import ninja.leaping.configurate.loader.ConfigurationLoader;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class SpongeConfigAdapter extends AbstractConfigurationAdapter implements ConfigurationAdapter {
|
|
||||||
|
|
||||||
private final Path path;
|
|
||||||
private ConfigurationNode root;
|
|
||||||
|
|
||||||
|
public class SpongeConfigAdapter extends ConfigurateConfigAdapter implements ConfigurationAdapter {
|
||||||
public SpongeConfigAdapter(LuckPermsPlugin plugin, Path path) {
|
public SpongeConfigAdapter(LuckPermsPlugin plugin, Path path) {
|
||||||
super(plugin);
|
super(plugin, path);
|
||||||
this.path = path;
|
|
||||||
reload();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reload() {
|
protected ConfigurationLoader<? extends ConfigurationNode> createLoader(Path path) {
|
||||||
ConfigurationLoader<CommentedConfigurationNode> loader = HoconConfigurationLoader.builder().setPath(this.path).build();
|
return HoconConfigurationLoader.builder().setPath(path).build();
|
||||||
|
|
||||||
try {
|
|
||||||
this.root = loader.load();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private ConfigurationNode resolvePath(String path) {
|
|
||||||
if (this.root == null) {
|
|
||||||
throw new RuntimeException("Config is not loaded.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.root.getNode(Splitter.on('.').splitToList(path).toArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getString(String path, String def) {
|
|
||||||
return resolvePath(path).getString(def);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getInt(String path, int def) {
|
|
||||||
return resolvePath(path).getInt(def);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean getBoolean(String path, boolean def) {
|
|
||||||
return resolvePath(path).getBoolean(def);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> getList(String path, List<String> def) {
|
|
||||||
ConfigurationNode node = resolvePath(path);
|
|
||||||
if (node.isVirtual()) {
|
|
||||||
return def;
|
|
||||||
}
|
|
||||||
|
|
||||||
return node.getList(Object::toString);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> getKeys(String path, List<String> def) {
|
|
||||||
ConfigurationNode node = resolvePath(path);
|
|
||||||
if (node.isVirtual()) {
|
|
||||||
return def;
|
|
||||||
}
|
|
||||||
|
|
||||||
return node.getChildrenMap().keySet().stream().map(Object::toString).collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public Map<String, String> getMap(String path, Map<String, String> def) {
|
|
||||||
ConfigurationNode node = resolvePath(path);
|
|
||||||
if (node.isVirtual()) {
|
|
||||||
return def;
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, Object> m = (Map<String, Object>) node.getValue(Collections.emptyMap());
|
|
||||||
return m.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, v -> v.getValue().toString()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ import javax.annotation.Nonnull;
|
|||||||
/**
|
/**
|
||||||
* An implementation of {@link Messenger} using the plugin messaging channels.
|
* An implementation of {@link Messenger} using the plugin messaging channels.
|
||||||
*/
|
*/
|
||||||
public class BungeeMessenger implements Messenger, RawDataListener {
|
public class PluginMessageMessenger implements Messenger, RawDataListener {
|
||||||
private static final String CHANNEL = "luckperms:update";
|
private static final String CHANNEL = "luckperms:update";
|
||||||
|
|
||||||
private final LPSpongePlugin plugin;
|
private final LPSpongePlugin plugin;
|
||||||
@ -55,7 +55,7 @@ public class BungeeMessenger implements Messenger, RawDataListener {
|
|||||||
|
|
||||||
private ChannelBinding.RawDataChannel channel = null;
|
private ChannelBinding.RawDataChannel channel = null;
|
||||||
|
|
||||||
public BungeeMessenger(LPSpongePlugin plugin, IncomingMessageConsumer consumer) {
|
public PluginMessageMessenger(LPSpongePlugin plugin, IncomingMessageConsumer consumer) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.consumer = consumer;
|
this.consumer = consumer;
|
||||||
}
|
}
|
@ -42,9 +42,9 @@ public class SpongeMessagingFactory extends MessagingFactory<LPSpongePlugin> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected InternalMessagingService getServiceFor(String messagingType) {
|
protected InternalMessagingService getServiceFor(String messagingType) {
|
||||||
if (messagingType.equals("bungee")) {
|
if (messagingType.equals("pluginmsg") || messagingType.equals("bungee") || messagingType.equals("velocity")) {
|
||||||
try {
|
try {
|
||||||
return new LuckPermsMessagingService(getPlugin(), new BungeeMessengerProvider());
|
return new LuckPermsMessagingService(getPlugin(), new PluginMessageMessengerProvider());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -53,20 +53,20 @@ public class SpongeMessagingFactory extends MessagingFactory<LPSpongePlugin> {
|
|||||||
return super.getServiceFor(messagingType);
|
return super.getServiceFor(messagingType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BungeeMessengerProvider implements MessengerProvider {
|
private class PluginMessageMessengerProvider implements MessengerProvider {
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Bungee";
|
return "PluginMessage";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Messenger obtain(@Nonnull IncomingMessageConsumer incomingMessageConsumer) {
|
public Messenger obtain(@Nonnull IncomingMessageConsumer incomingMessageConsumer) {
|
||||||
BungeeMessenger bungeeMessaging = new BungeeMessenger(getPlugin(), incomingMessageConsumer);
|
PluginMessageMessenger messenger = new PluginMessageMessenger(getPlugin(), incomingMessageConsumer);
|
||||||
bungeeMessaging.init();
|
messenger.init();
|
||||||
return bungeeMessaging;
|
return messenger;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,9 +210,9 @@ watch-files = true
|
|||||||
# => sql Uses the SQL database to form a queue system for communication. Will only work when
|
# => sql Uses the SQL database to form a queue system for communication. Will only work when
|
||||||
# 'storage-method' is set to MySQL or MariaDB. This is chosen by default if the
|
# 'storage-method' is set to MySQL or MariaDB. This is chosen by default if the
|
||||||
# option is set to 'none' and SQL storage is in use. Set to 'notsql' to disable this.
|
# option is set to 'none' and SQL storage is in use. Set to 'notsql' to disable this.
|
||||||
# => bungee Uses the plugin messaging channels to communicate with the proxy.
|
# => pluginmsg Uses the plugin messaging channels to communicate with the proxy.
|
||||||
# LuckPerms must be installed on your proxy & all connected servers backend servers.
|
# LuckPerms must be installed on your proxy & all connected servers backend servers.
|
||||||
# Won't work if you have more than one BungeeCord proxy.
|
# Won't work if you have more than one proxy.
|
||||||
# => redis Uses Redis pub-sub to push changes. Your server connection info must be configured
|
# => redis Uses Redis pub-sub to push changes. Your server connection info must be configured
|
||||||
# below.
|
# below.
|
||||||
# => none Disables the service.
|
# => none Disables the service.
|
||||||
|
54
velocity/build.gradle
Normal file
54
velocity/build.gradle
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
url "https://plugins.gradle.org/m2/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath "com.github.jengelman.gradle.plugins:shadow:2.0.4"
|
||||||
|
classpath "gradle.plugin.ninja.miserable:blossom:1.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: "com.github.johnrengelman.shadow"
|
||||||
|
apply plugin: "ninja.miserable.blossom"
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile project(':common')
|
||||||
|
|
||||||
|
compileOnly 'com.velocitypowered:velocity-api:1.0-SNAPSHOT'
|
||||||
|
}
|
||||||
|
|
||||||
|
blossom {
|
||||||
|
replaceTokenIn('src/main/java/me/lucko/luckperms/velocity/LPVelocityBootstrap.java')
|
||||||
|
replaceToken '@version@', project.ext.fullVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
shadowJar {
|
||||||
|
archiveName = "LuckPerms-Velocity-${project.ext.fullVersion}.jar"
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
include(dependency('me.lucko.luckperms:.*'))
|
||||||
|
}
|
||||||
|
|
||||||
|
// relocate 'net.kyori.text', 'me.lucko.luckperms.lib.text' (included in velocity!)
|
||||||
|
relocate 'net.kyori.event', 'me.lucko.luckperms.lib.eventbus'
|
||||||
|
relocate 'com.github.benmanes.caffeine', 'me.lucko.luckperms.lib.caffeine'
|
||||||
|
relocate 'okio', 'me.lucko.luckperms.lib.okio'
|
||||||
|
relocate 'okhttp3', 'me.lucko.luckperms.lib.okhttp3'
|
||||||
|
relocate 'me.lucko.commodore', 'me.lucko.luckperms.lib.commodore'
|
||||||
|
relocate 'org.mariadb.jdbc', 'me.lucko.luckperms.lib.mariadb'
|
||||||
|
relocate 'com.mysql', 'me.lucko.luckperms.lib.mysql'
|
||||||
|
relocate 'org.postgresql', 'me.lucko.luckperms.lib.postgresql'
|
||||||
|
relocate 'com.zaxxer.hikari', 'me.lucko.luckperms.lib.hikari'
|
||||||
|
relocate 'com.mongodb', 'me.lucko.luckperms.lib.mongodb'
|
||||||
|
relocate 'org.bson', 'me.lucko.luckperms.lib.bson'
|
||||||
|
relocate 'redis.clients.jedis', 'me.lucko.luckperms.lib.jedis'
|
||||||
|
relocate 'org.apache.commons.pool2', 'me.lucko.luckperms.lib.commonspool2'
|
||||||
|
relocate 'ninja.leaping.configurate', 'me.lucko.luckperms.lib.configurate'
|
||||||
|
relocate 'org.yaml.snakeyaml', 'me.lucko.luckperms.lib.yaml'
|
||||||
|
}
|
||||||
|
|
||||||
|
artifacts {
|
||||||
|
archives shadowJar
|
||||||
|
}
|
@ -0,0 +1,241 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of LuckPerms, licensed under the MIT License.
|
||||||
|
*
|
||||||
|
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package me.lucko.luckperms.velocity;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.velocitypowered.api.event.PostOrder;
|
||||||
|
import com.velocitypowered.api.event.Subscribe;
|
||||||
|
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
||||||
|
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
|
||||||
|
import com.velocitypowered.api.plugin.Plugin;
|
||||||
|
import com.velocitypowered.api.plugin.annotation.DataDirectory;
|
||||||
|
import com.velocitypowered.api.proxy.Player;
|
||||||
|
import com.velocitypowered.api.proxy.ProxyServer;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.api.platform.PlatformType;
|
||||||
|
import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader;
|
||||||
|
import me.lucko.luckperms.common.plugin.bootstrap.LuckPermsBootstrap;
|
||||||
|
import me.lucko.luckperms.common.plugin.logging.PluginLogger;
|
||||||
|
import me.lucko.luckperms.common.plugin.logging.Slf4jPluginLogger;
|
||||||
|
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bootstrap plugin for LuckPerms running on Velocity.
|
||||||
|
*/
|
||||||
|
@Plugin(
|
||||||
|
id = "luckperms",
|
||||||
|
name = "LuckPerms",
|
||||||
|
version = "@version@",
|
||||||
|
authors = "Luck",
|
||||||
|
description = "A permissions plugin",
|
||||||
|
url = "https://github.com/lucko/LuckPerms"
|
||||||
|
)
|
||||||
|
public class LPVelocityBootstrap implements LuckPermsBootstrap {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The plugin logger
|
||||||
|
*/
|
||||||
|
private final PluginLogger logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A scheduler adapter for the platform
|
||||||
|
*/
|
||||||
|
private final SchedulerAdapter schedulerAdapter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The plugin classloader
|
||||||
|
*/
|
||||||
|
private final PluginClassLoader classLoader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The plugin instance
|
||||||
|
*/
|
||||||
|
private final LPVelocityPlugin plugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The time when the plugin was enabled
|
||||||
|
*/
|
||||||
|
private long startTime;
|
||||||
|
|
||||||
|
// load/enable latches
|
||||||
|
private final CountDownLatch loadLatch = new CountDownLatch(1);
|
||||||
|
private final CountDownLatch enableLatch = new CountDownLatch(1);
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ProxyServer proxy;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
@DataDirectory
|
||||||
|
private Path configDirectory;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public LPVelocityBootstrap(Logger logger) {
|
||||||
|
this.logger = new Slf4jPluginLogger(logger);
|
||||||
|
this.schedulerAdapter = new VelocitySchedulerAdapter(this);
|
||||||
|
this.classLoader = new VelocityClassLoader(this);
|
||||||
|
this.plugin = new LPVelocityPlugin(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// provide adapters
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PluginLogger getPluginLogger() {
|
||||||
|
return this.logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SchedulerAdapter getScheduler() {
|
||||||
|
return this.schedulerAdapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PluginClassLoader getPluginClassLoader() {
|
||||||
|
return this.classLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lifecycle
|
||||||
|
|
||||||
|
@Subscribe(order = PostOrder.FIRST)
|
||||||
|
public void onEnable(ProxyInitializeEvent e) {
|
||||||
|
this.startTime = System.currentTimeMillis();
|
||||||
|
try {
|
||||||
|
this.plugin.load();
|
||||||
|
} finally {
|
||||||
|
this.loadLatch.countDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.plugin.enable();
|
||||||
|
} finally {
|
||||||
|
this.enableLatch.countDown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe(order = PostOrder.LAST)
|
||||||
|
public void onDisable(ProxyShutdownEvent e) {
|
||||||
|
this.plugin.disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CountDownLatch getEnableLatch() {
|
||||||
|
return this.enableLatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CountDownLatch getLoadLatch() {
|
||||||
|
return this.loadLatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
// getters for the injected sponge instances
|
||||||
|
|
||||||
|
public ProxyServer getProxy() {
|
||||||
|
return this.proxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
// provide information about the plugin
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getVersion() {
|
||||||
|
return "@version@";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getStartupTime() {
|
||||||
|
return this.startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// provide information about the platform
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PlatformType getType() {
|
||||||
|
return PlatformType.VELOCITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getServerBrand() {
|
||||||
|
return "Velocity";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getServerVersion() {
|
||||||
|
return ProxyServer.class.getPackage().getImplementationVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Path getDataDirectory() {
|
||||||
|
return this.configDirectory.toAbsolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getResourceStream(String path) {
|
||||||
|
return getClass().getClassLoader().getResourceAsStream(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Player> getPlayer(UUID uuid) {
|
||||||
|
return this.proxy.getPlayer(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<UUID> lookupUuid(String username) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<String> lookupUsername(UUID uuid) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPlayerCount() {
|
||||||
|
return this.proxy.getPlayerCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<String> getPlayerList() {
|
||||||
|
return this.proxy.getAllPlayers().stream().map(Player::getUsername);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<UUID> getOnlinePlayers() {
|
||||||
|
return this.proxy.getAllPlayers().stream().map(Player::getUniqueId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPlayerOnline(UUID uuid) {
|
||||||
|
Player player = this.proxy.getPlayer(uuid).orElse(null);
|
||||||
|
return player != null && player.isActive();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,236 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of LuckPerms, licensed under the MIT License.
|
||||||
|
*
|
||||||
|
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package me.lucko.luckperms.velocity;
|
||||||
|
|
||||||
|
import com.velocitypowered.api.proxy.Player;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.api.Contexts;
|
||||||
|
import me.lucko.luckperms.api.LuckPermsApi;
|
||||||
|
import me.lucko.luckperms.common.api.LuckPermsApiProvider;
|
||||||
|
import me.lucko.luckperms.common.calculators.CalculatorFactory;
|
||||||
|
import me.lucko.luckperms.common.command.CommandManager;
|
||||||
|
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
||||||
|
import me.lucko.luckperms.common.contexts.ContextManager;
|
||||||
|
import me.lucko.luckperms.common.dependencies.Dependency;
|
||||||
|
import me.lucko.luckperms.common.event.AbstractEventBus;
|
||||||
|
import me.lucko.luckperms.common.managers.group.StandardGroupManager;
|
||||||
|
import me.lucko.luckperms.common.managers.track.StandardTrackManager;
|
||||||
|
import me.lucko.luckperms.common.managers.user.StandardUserManager;
|
||||||
|
import me.lucko.luckperms.common.messaging.MessagingFactory;
|
||||||
|
import me.lucko.luckperms.common.model.User;
|
||||||
|
import me.lucko.luckperms.common.plugin.AbstractLuckPermsPlugin;
|
||||||
|
import me.lucko.luckperms.common.plugin.util.AbstractConnectionListener;
|
||||||
|
import me.lucko.luckperms.common.sender.Sender;
|
||||||
|
import me.lucko.luckperms.common.tasks.CacheHousekeepingTask;
|
||||||
|
import me.lucko.luckperms.common.tasks.ExpireTemporaryTask;
|
||||||
|
import me.lucko.luckperms.common.utils.MoreFiles;
|
||||||
|
import me.lucko.luckperms.velocity.calculators.VelocityCalculatorFactory;
|
||||||
|
import me.lucko.luckperms.velocity.contexts.BackendServerCalculator;
|
||||||
|
import me.lucko.luckperms.velocity.contexts.VelocityContextManager;
|
||||||
|
import me.lucko.luckperms.velocity.listeners.MonitoringPermissionCheckListener;
|
||||||
|
import me.lucko.luckperms.velocity.listeners.VelocityConnectionListener;
|
||||||
|
import me.lucko.luckperms.velocity.messaging.VelocityMessagingFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LuckPerms implementation for the Velocity API.
|
||||||
|
*/
|
||||||
|
public class LPVelocityPlugin extends AbstractLuckPermsPlugin {
|
||||||
|
private final LPVelocityBootstrap bootstrap;
|
||||||
|
|
||||||
|
private VelocitySenderFactory senderFactory;
|
||||||
|
private VelocityConnectionListener connectionListener;
|
||||||
|
private CommandManager commandManager;
|
||||||
|
private StandardUserManager userManager;
|
||||||
|
private StandardGroupManager groupManager;
|
||||||
|
private StandardTrackManager trackManager;
|
||||||
|
private ContextManager<Player> contextManager;
|
||||||
|
|
||||||
|
public LPVelocityPlugin(LPVelocityBootstrap bootstrap) {
|
||||||
|
this.bootstrap = bootstrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LPVelocityBootstrap getBootstrap() {
|
||||||
|
return this.bootstrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setupSenderFactory() {
|
||||||
|
this.senderFactory = new VelocitySenderFactory(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Set<Dependency> getGlobalDependencies() {
|
||||||
|
return EnumSet.of(Dependency.CAFFEINE, Dependency.OKIO, Dependency.OKHTTP, Dependency.EVENT,
|
||||||
|
Dependency.CONFIGURATE_CORE, Dependency.CONFIGURATE_YAML, Dependency.SNAKEYAML);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ConfigurationAdapter provideConfigurationAdapter() {
|
||||||
|
return new VelocityConfigAdapter(this, resolveConfig());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void registerPlatformListeners() {
|
||||||
|
this.connectionListener = new VelocityConnectionListener(this);
|
||||||
|
this.bootstrap.getProxy().getEventManager().register(this.bootstrap, this.connectionListener);
|
||||||
|
this.bootstrap.getProxy().getEventManager().register(this.bootstrap, new MonitoringPermissionCheckListener(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MessagingFactory<?> provideMessagingFactory() {
|
||||||
|
return new VelocityMessagingFactory(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void registerCommands() {
|
||||||
|
this.commandManager = new CommandManager(this);
|
||||||
|
this.bootstrap.getProxy().getCommandManager().register(new VelocityCommandExecutor(this, this.commandManager), "luckpermsvelocity", "lpv", "vperm", "vperms", "vpermission", "vpermissions");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setupManagers() {
|
||||||
|
this.userManager = new StandardUserManager(this);
|
||||||
|
this.groupManager = new StandardGroupManager(this);
|
||||||
|
this.trackManager = new StandardTrackManager(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected CalculatorFactory provideCalculatorFactory() {
|
||||||
|
return new VelocityCalculatorFactory(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setupContextManager() {
|
||||||
|
this.contextManager = new VelocityContextManager(this);
|
||||||
|
this.contextManager.registerCalculator(new BackendServerCalculator(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setupPlatformHooks() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AbstractEventBus provideEventBus(LuckPermsApiProvider apiProvider) {
|
||||||
|
return new VelocityEventBus(this, apiProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void registerApiOnPlatform(LuckPermsApi api) {
|
||||||
|
// Velocity doesn't have a services manager
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void registerHousekeepingTasks() {
|
||||||
|
this.bootstrap.getScheduler().asyncRepeating(new ExpireTemporaryTask(this), 3, TimeUnit.SECONDS);
|
||||||
|
this.bootstrap.getScheduler().asyncRepeating(new CacheHousekeepingTask(this), 2, TimeUnit.MINUTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void performFinalSetup() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Path resolveConfig() {
|
||||||
|
Path path = this.bootstrap.getConfigDirectory().resolve("config.yml");
|
||||||
|
if (!Files.exists(path)) {
|
||||||
|
try {
|
||||||
|
MoreFiles.createDirectoriesIfNotExists(this.bootstrap.getConfigDirectory());
|
||||||
|
try (InputStream is = getClass().getClassLoader().getResourceAsStream("config.yml")) {
|
||||||
|
Files.copy(is, path);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Contexts> getContextForUser(User user) {
|
||||||
|
return this.bootstrap.getPlayer(user.getUuid()).map(player -> this.contextManager.getApplicableContexts(player));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<Sender> getOnlineSenders() {
|
||||||
|
return Stream.concat(
|
||||||
|
Stream.of(getConsoleSender()),
|
||||||
|
this.bootstrap.getProxy().getAllPlayers().stream().map(p -> this.senderFactory.wrap(p))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Sender getConsoleSender() {
|
||||||
|
return this.senderFactory.wrap(this.bootstrap.getProxy().getConsoleCommandSource());
|
||||||
|
}
|
||||||
|
|
||||||
|
public VelocitySenderFactory getSenderFactory() {
|
||||||
|
return this.senderFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbstractConnectionListener getConnectionListener() {
|
||||||
|
return this.connectionListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommandManager getCommandManager() {
|
||||||
|
return this.commandManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StandardUserManager getUserManager() {
|
||||||
|
return this.userManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StandardGroupManager getGroupManager() {
|
||||||
|
return this.groupManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StandardTrackManager getTrackManager() {
|
||||||
|
return this.trackManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContextManager<Player> getContextManager() {
|
||||||
|
return this.contextManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package me.lucko.luckperms.velocity;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public class VelocityClassLoader implements PluginClassLoader {
|
||||||
|
private final LPVelocityBootstrap bootstrap;
|
||||||
|
|
||||||
|
public VelocityClassLoader(LPVelocityBootstrap bootstrap) {
|
||||||
|
this.bootstrap = bootstrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadJar(Path file) {
|
||||||
|
this.bootstrap.getProxy().getPluginManager().addToClasspath(bootstrap, file);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of LuckPerms, licensed under the MIT License.
|
||||||
|
*
|
||||||
|
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package me.lucko.luckperms.velocity;
|
||||||
|
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
|
import com.velocitypowered.api.command.Command;
|
||||||
|
import com.velocitypowered.api.command.CommandSource;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.command.CommandManager;
|
||||||
|
import me.lucko.luckperms.common.sender.Sender;
|
||||||
|
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class VelocityCommandExecutor implements Command {
|
||||||
|
private static final Splitter TAB_COMPLETE_ARGUMENT_SPLITTER = Splitter.on(CommandManager.COMMAND_SEPARATOR_PATTERN);
|
||||||
|
private static final Splitter ARGUMENT_SPLITTER = Splitter.on(CommandManager.COMMAND_SEPARATOR_PATTERN).omitEmptyStrings();
|
||||||
|
private static final Joiner ARGUMENT_JOINER = Joiner.on(' ');
|
||||||
|
|
||||||
|
private final LPVelocityPlugin plugin;
|
||||||
|
private final CommandManager manager;
|
||||||
|
|
||||||
|
public VelocityCommandExecutor(LPVelocityPlugin plugin, CommandManager manager) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.manager = manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(@NonNull CommandSource source, String[] args) {
|
||||||
|
Sender lpSender = this.plugin.getSenderFactory().wrap(source);
|
||||||
|
List<String> arguments = CommandManager.stripQuotes(ARGUMENT_SPLITTER.splitToList(ARGUMENT_JOINER.join(args)));
|
||||||
|
|
||||||
|
this.manager.onCommand(lpSender, "lpv", arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> suggest(@NonNull CommandSource source, String[] args) {
|
||||||
|
Sender lpSender = this.plugin.getSenderFactory().wrap(source);
|
||||||
|
List<String> arguments = CommandManager.stripQuotes(TAB_COMPLETE_ARGUMENT_SPLITTER.splitToList(ARGUMENT_JOINER.join(args)));
|
||||||
|
|
||||||
|
return this.manager.onTabComplete(lpSender, arguments);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of LuckPerms, licensed under the MIT License.
|
||||||
|
*
|
||||||
|
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package me.lucko.luckperms.velocity;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.config.adapter.ConfigurateConfigAdapter;
|
||||||
|
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
||||||
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
|
|
||||||
|
import ninja.leaping.configurate.ConfigurationNode;
|
||||||
|
import ninja.leaping.configurate.loader.ConfigurationLoader;
|
||||||
|
import ninja.leaping.configurate.yaml.YAMLConfigurationLoader;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public class VelocityConfigAdapter extends ConfigurateConfigAdapter implements ConfigurationAdapter {
|
||||||
|
public VelocityConfigAdapter(LuckPermsPlugin plugin, Path path) {
|
||||||
|
super(plugin, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ConfigurationLoader<? extends ConfigurationNode> createLoader(Path path) {
|
||||||
|
return YAMLConfigurationLoader.builder().setPath(path).build();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of LuckPerms, licensed under the MIT License.
|
||||||
|
*
|
||||||
|
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package me.lucko.luckperms.velocity;
|
||||||
|
|
||||||
|
import com.velocitypowered.api.plugin.PluginContainer;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.api.LuckPermsApiProvider;
|
||||||
|
import me.lucko.luckperms.common.event.AbstractEventBus;
|
||||||
|
|
||||||
|
public class VelocityEventBus extends AbstractEventBus<PluginContainer> {
|
||||||
|
private final LPVelocityPlugin plugin;
|
||||||
|
|
||||||
|
public VelocityEventBus(LPVelocityPlugin plugin, LuckPermsApiProvider apiProvider) {
|
||||||
|
super(plugin, apiProvider);
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PluginContainer checkPlugin(Object plugin) throws IllegalArgumentException {
|
||||||
|
if (plugin instanceof PluginContainer) {
|
||||||
|
return (PluginContainer) plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginContainer pluginContainer = this.plugin.getBootstrap().getProxy().getPluginManager().fromInstance(plugin).orElse(null);
|
||||||
|
if (pluginContainer != null) {
|
||||||
|
return pluginContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalArgumentException("Object " + plugin + " (" + plugin.getClass().getName() + ") is not a plugin.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of LuckPerms, licensed under the MIT License.
|
||||||
|
*
|
||||||
|
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package me.lucko.luckperms.velocity;
|
||||||
|
|
||||||
|
import com.velocitypowered.api.scheduler.ScheduledTask;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
|
||||||
|
import me.lucko.luckperms.common.plugin.scheduler.SchedulerTask;
|
||||||
|
import me.lucko.luckperms.common.utils.Iterators;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class VelocitySchedulerAdapter implements SchedulerAdapter {
|
||||||
|
private final LPVelocityBootstrap bootstrap;
|
||||||
|
|
||||||
|
private final Executor executor;
|
||||||
|
private final Set<ScheduledTask> tasks = Collections.newSetFromMap(new WeakHashMap<>());
|
||||||
|
|
||||||
|
public VelocitySchedulerAdapter(LPVelocityBootstrap bootstrap) {
|
||||||
|
this.bootstrap = bootstrap;
|
||||||
|
this.executor = r -> bootstrap.getProxy().getScheduler().buildTask(bootstrap, r).schedule();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Executor async() {
|
||||||
|
return this.executor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Executor sync() {
|
||||||
|
return this.executor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SchedulerTask asyncLater(Runnable task, long delay, TimeUnit unit) {
|
||||||
|
ScheduledTask t = this.bootstrap.getProxy().getScheduler().buildTask(this.bootstrap, task)
|
||||||
|
.delay((int) delay, unit)
|
||||||
|
.schedule();
|
||||||
|
|
||||||
|
this.tasks.add(t);
|
||||||
|
return t::cancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SchedulerTask asyncRepeating(Runnable task, long interval, TimeUnit unit) {
|
||||||
|
ScheduledTask t = this.bootstrap.getProxy().getScheduler().buildTask(this.bootstrap, task)
|
||||||
|
.delay((int) interval, unit)
|
||||||
|
.repeat((int) interval, unit)
|
||||||
|
.schedule();
|
||||||
|
|
||||||
|
this.tasks.add(t);
|
||||||
|
return t::cancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shutdown() {
|
||||||
|
Iterators.iterate(this.tasks, ScheduledTask::cancel);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of LuckPerms, licensed under the MIT License.
|
||||||
|
*
|
||||||
|
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package me.lucko.luckperms.velocity;
|
||||||
|
|
||||||
|
import com.velocitypowered.api.command.CommandSource;
|
||||||
|
import com.velocitypowered.api.proxy.Player;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.api.Tristate;
|
||||||
|
import me.lucko.luckperms.common.command.CommandManager;
|
||||||
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
|
import me.lucko.luckperms.common.sender.SenderFactory;
|
||||||
|
import me.lucko.luckperms.common.utils.TextUtils;
|
||||||
|
|
||||||
|
import net.kyori.text.Component;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class VelocitySenderFactory extends SenderFactory<CommandSource> {
|
||||||
|
public VelocitySenderFactory(LuckPermsPlugin plugin) {
|
||||||
|
super(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getName(CommandSource source) {
|
||||||
|
if (source instanceof Player) {
|
||||||
|
return ((Player) source).getUsername();
|
||||||
|
}
|
||||||
|
return CommandManager.CONSOLE_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected UUID getUuid(CommandSource source) {
|
||||||
|
if (source instanceof Player) {
|
||||||
|
return ((Player) source).getUniqueId();
|
||||||
|
}
|
||||||
|
return CommandManager.CONSOLE_UUID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void sendMessage(CommandSource source, String s) {
|
||||||
|
sendMessage(source, TextUtils.fromLegacy(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void sendMessage(CommandSource source, Component message) {
|
||||||
|
source.sendMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Tristate getPermissionValue(CommandSource source, String node) {
|
||||||
|
return Tristate.fromBoolean(hasPermission(source, node));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean hasPermission(CommandSource source, String node) {
|
||||||
|
return source.hasPermission(node);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of LuckPerms, licensed under the MIT License.
|
||||||
|
*
|
||||||
|
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package me.lucko.luckperms.velocity.calculators;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.api.Contexts;
|
||||||
|
import me.lucko.luckperms.velocity.LPVelocityPlugin;
|
||||||
|
import me.lucko.luckperms.common.calculators.CalculatorFactory;
|
||||||
|
import me.lucko.luckperms.common.calculators.PermissionCalculator;
|
||||||
|
import me.lucko.luckperms.common.calculators.PermissionCalculatorMetadata;
|
||||||
|
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||||
|
import me.lucko.luckperms.common.processors.MapProcessor;
|
||||||
|
import me.lucko.luckperms.common.processors.PermissionProcessor;
|
||||||
|
import me.lucko.luckperms.common.processors.RegexProcessor;
|
||||||
|
import me.lucko.luckperms.common.processors.WildcardProcessor;
|
||||||
|
|
||||||
|
public class VelocityCalculatorFactory implements CalculatorFactory {
|
||||||
|
private final LPVelocityPlugin plugin;
|
||||||
|
|
||||||
|
public VelocityCalculatorFactory(LPVelocityPlugin plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PermissionCalculator build(Contexts contexts, PermissionCalculatorMetadata metadata) {
|
||||||
|
ImmutableList.Builder<PermissionProcessor> processors = ImmutableList.builder();
|
||||||
|
|
||||||
|
processors.add(new MapProcessor());
|
||||||
|
|
||||||
|
if (this.plugin.getConfiguration().get(ConfigKeys.APPLYING_REGEX)) {
|
||||||
|
processors.add(new RegexProcessor());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.plugin.getConfiguration().get(ConfigKeys.APPLYING_WILDCARDS)) {
|
||||||
|
processors.add(new WildcardProcessor());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PermissionCalculator(this.plugin, metadata, processors.build());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of LuckPerms, licensed under the MIT License.
|
||||||
|
*
|
||||||
|
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package me.lucko.luckperms.velocity.contexts;
|
||||||
|
|
||||||
|
import com.velocitypowered.api.proxy.Player;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.api.Contexts;
|
||||||
|
import me.lucko.luckperms.api.context.ContextCalculator;
|
||||||
|
import me.lucko.luckperms.api.context.MutableContextSet;
|
||||||
|
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||||
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
public class BackendServerCalculator implements ContextCalculator<Player> {
|
||||||
|
|
||||||
|
private static String getServer(Player player) {
|
||||||
|
return player.getCurrentServer().isPresent() ? player.getCurrentServer().get().getServerInfo().getName().toLowerCase() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final LuckPermsPlugin plugin;
|
||||||
|
|
||||||
|
public BackendServerCalculator(LuckPermsPlugin plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public MutableContextSet giveApplicableContext(@Nonnull Player subject, @Nonnull MutableContextSet accumulator) {
|
||||||
|
String server = getServer(subject);
|
||||||
|
while (server != null && !accumulator.has(Contexts.WORLD_KEY, server)) {
|
||||||
|
accumulator.add(Contexts.WORLD_KEY, server);
|
||||||
|
server = this.plugin.getConfiguration().get(ConfigKeys.WORLD_REWRITES).getOrDefault(server, server).toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
return accumulator;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of LuckPerms, licensed under the MIT License.
|
||||||
|
*
|
||||||
|
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package me.lucko.luckperms.velocity.contexts;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||||
|
import com.velocitypowered.api.proxy.Player;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.api.Contexts;
|
||||||
|
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||||
|
import me.lucko.luckperms.common.contexts.ContextManager;
|
||||||
|
import me.lucko.luckperms.common.contexts.ContextsCache;
|
||||||
|
import me.lucko.luckperms.common.contexts.ContextsSupplier;
|
||||||
|
import me.lucko.luckperms.velocity.LPVelocityPlugin;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class VelocityContextManager extends ContextManager<Player> {
|
||||||
|
|
||||||
|
private final LoadingCache<Player, ContextsCache<Player>> subjectCaches = Caffeine.newBuilder()
|
||||||
|
.expireAfterAccess(1, TimeUnit.MINUTES)
|
||||||
|
.build(key -> new ContextsCache<>(key, this));
|
||||||
|
|
||||||
|
public VelocityContextManager(LPVelocityPlugin plugin) {
|
||||||
|
super(plugin, Player.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContextsSupplier getCacheFor(Player subject) {
|
||||||
|
if (subject == null) {
|
||||||
|
throw new NullPointerException("subject");
|
||||||
|
}
|
||||||
|
|
||||||
|
return subjectCaches.get(subject);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidateCache(Player subject) {
|
||||||
|
if (subject == null) {
|
||||||
|
throw new NullPointerException("subject");
|
||||||
|
}
|
||||||
|
|
||||||
|
ContextsCache<Player> cache = this.subjectCaches.getIfPresent(subject);
|
||||||
|
if (cache != null) {
|
||||||
|
cache.invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Contexts formContexts(Player subject, ImmutableContextSet contextSet) {
|
||||||
|
return formContexts(contextSet);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of LuckPerms, licensed under the MIT License.
|
||||||
|
*
|
||||||
|
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package me.lucko.luckperms.velocity.listeners;
|
||||||
|
|
||||||
|
import com.velocitypowered.api.event.PostOrder;
|
||||||
|
import com.velocitypowered.api.event.Subscribe;
|
||||||
|
import com.velocitypowered.api.event.permission.PermissionsSetupEvent;
|
||||||
|
import com.velocitypowered.api.permission.PermissionFunction;
|
||||||
|
import com.velocitypowered.api.permission.PermissionProvider;
|
||||||
|
import com.velocitypowered.api.permission.PermissionSubject;
|
||||||
|
import com.velocitypowered.api.proxy.Player;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.api.Tristate;
|
||||||
|
import me.lucko.luckperms.api.context.ContextSet;
|
||||||
|
import me.lucko.luckperms.common.verbose.CheckOrigin;
|
||||||
|
import me.lucko.luckperms.velocity.LPVelocityPlugin;
|
||||||
|
import me.lucko.luckperms.velocity.service.CompatibilityUtil;
|
||||||
|
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
|
||||||
|
public class MonitoringPermissionCheckListener {
|
||||||
|
private final LPVelocityPlugin plugin;
|
||||||
|
|
||||||
|
public MonitoringPermissionCheckListener(LPVelocityPlugin plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe(order = PostOrder.LAST)
|
||||||
|
public void onOtherPermissionSetup(PermissionsSetupEvent e) {
|
||||||
|
// players are handled separately
|
||||||
|
if (e.getSubject() instanceof Player) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.setProvider(new MonitoredPermissionProvider(e.getProvider()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class MonitoredPermissionProvider implements PermissionProvider {
|
||||||
|
private final PermissionProvider delegate;
|
||||||
|
|
||||||
|
MonitoredPermissionProvider(PermissionProvider delegate) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull PermissionFunction createFunction(@NonNull PermissionSubject subject) {
|
||||||
|
PermissionFunction function = this.delegate.createFunction(subject);
|
||||||
|
return new MonitoredPermissionFunction(subject, function);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class MonitoredPermissionFunction implements PermissionFunction {
|
||||||
|
private final String name;
|
||||||
|
private final PermissionFunction delegate;
|
||||||
|
|
||||||
|
MonitoredPermissionFunction(PermissionSubject subject, PermissionFunction delegate) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
this.name = determineName(subject);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public com.velocitypowered.api.permission.@NonNull Tristate getPermissionSetting(@NonNull String permission) {
|
||||||
|
com.velocitypowered.api.permission.Tristate setting = this.delegate.getPermissionSetting(permission);
|
||||||
|
|
||||||
|
// report result
|
||||||
|
Tristate result = CompatibilityUtil.convertTristate(setting);
|
||||||
|
String name = "internal/" + this.name;
|
||||||
|
|
||||||
|
MonitoringPermissionCheckListener.this.plugin.getVerboseHandler().offerCheckData(CheckOrigin.PLATFORM_LOOKUP_CHECK, name, ContextSet.empty(), permission, result);
|
||||||
|
MonitoringPermissionCheckListener.this.plugin.getPermissionRegistry().offer(permission);
|
||||||
|
|
||||||
|
return setting;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String determineName(PermissionSubject subject) {
|
||||||
|
if (subject == this.plugin.getBootstrap().getProxy().getConsoleCommandSource()) {
|
||||||
|
return "console";
|
||||||
|
}
|
||||||
|
return subject.getClass().getSimpleName();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of LuckPerms, licensed under the MIT License.
|
||||||
|
*
|
||||||
|
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package me.lucko.luckperms.velocity.listeners;
|
||||||
|
|
||||||
|
import com.velocitypowered.api.event.PostOrder;
|
||||||
|
import com.velocitypowered.api.event.ResultedEvent;
|
||||||
|
import com.velocitypowered.api.event.Subscribe;
|
||||||
|
import com.velocitypowered.api.event.connection.DisconnectEvent;
|
||||||
|
import com.velocitypowered.api.event.connection.LoginEvent;
|
||||||
|
import com.velocitypowered.api.event.permission.PermissionsSetupEvent;
|
||||||
|
import com.velocitypowered.api.proxy.Player;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.velocity.LPVelocityPlugin;
|
||||||
|
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||||
|
import me.lucko.luckperms.common.locale.message.Message;
|
||||||
|
import me.lucko.luckperms.common.model.User;
|
||||||
|
import me.lucko.luckperms.common.plugin.util.AbstractConnectionListener;
|
||||||
|
import me.lucko.luckperms.velocity.service.PlayerPermissionProvider;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class VelocityConnectionListener extends AbstractConnectionListener {
|
||||||
|
private final LPVelocityPlugin plugin;
|
||||||
|
|
||||||
|
private final Set<UUID> deniedLogin = Collections.synchronizedSet(new HashSet<>());
|
||||||
|
|
||||||
|
public VelocityConnectionListener(LPVelocityPlugin plugin) {
|
||||||
|
super(plugin);
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onPlayerPermissionsSetup(PermissionsSetupEvent e) {
|
||||||
|
/* Called when the player first attempts a connection with the server.
|
||||||
|
The PermissionsSetupEvent is called for players just before the Login event
|
||||||
|
|
||||||
|
We delay the login here, as we want to cache UUID data before the player is connected to a backend bukkit server.
|
||||||
|
This means that a player will have the same UUID across the network, even if parts of the network are running in
|
||||||
|
Offline mode. */
|
||||||
|
|
||||||
|
if (!(e.getSubject() instanceof Player)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Player p = (Player) e.getSubject();
|
||||||
|
|
||||||
|
if (this.plugin.getConfiguration().get(ConfigKeys.DEBUG_LOGINS)) {
|
||||||
|
this.plugin.getLogger().info("Processing pre-login for " + p.getUniqueId() + " - " + p.getUsername());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Actually process the login for the connection.
|
||||||
|
We do this here to delay the login until the data is ready.
|
||||||
|
If the login gets cancelled later on, then this will be cleaned up.
|
||||||
|
|
||||||
|
This includes:
|
||||||
|
- loading uuid data
|
||||||
|
- loading permissions
|
||||||
|
- creating a user instance in the UserManager for this connection.
|
||||||
|
- setting up cached data. */
|
||||||
|
try {
|
||||||
|
User user = loadUser(p.getUniqueId(), p.getUsername());
|
||||||
|
this.plugin.getEventFactory().handleUserLoginProcess(p.getUniqueId(), p.getUsername(), user);
|
||||||
|
recordConnection(p.getUniqueId());
|
||||||
|
|
||||||
|
// set permission provider
|
||||||
|
e.setProvider(new PlayerPermissionProvider(p, user, this.plugin.getContextManager().getCacheFor(p)));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
this.plugin.getLogger().severe("Exception occurred whilst loading data for " + p.getUniqueId() + " - " + p.getUsername());
|
||||||
|
ex.printStackTrace();
|
||||||
|
|
||||||
|
// there was some error loading
|
||||||
|
if (this.plugin.getConfiguration().get(ConfigKeys.CANCEL_FAILED_LOGINS)) {
|
||||||
|
// cancel the login attempt
|
||||||
|
this.deniedLogin.add(p.getUniqueId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe(order = PostOrder.FIRST)
|
||||||
|
public void onPlayerLogin(LoginEvent e) {
|
||||||
|
if (this.deniedLogin.remove(e.getPlayer().getUniqueId())) {
|
||||||
|
e.setResult(ResultedEvent.ComponentResult.denied(Message.LOADING_DATABASE_ERROR.asComponent(this.plugin.getLocaleManager())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onPlayerPostLogin(LoginEvent e) {
|
||||||
|
final Player player = e.getPlayer();
|
||||||
|
final User user = this.plugin.getUserManager().getIfLoaded(e.getPlayer().getUniqueId());
|
||||||
|
|
||||||
|
if (this.plugin.getConfiguration().get(ConfigKeys.DEBUG_LOGINS)) {
|
||||||
|
this.plugin.getLogger().info("Processing post-login for " + player.getUniqueId() + " - " + player.getUsername());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!e.getResult().isAllowed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user == null) {
|
||||||
|
if (!getUniqueConnections().contains(player.getUniqueId())) {
|
||||||
|
this.plugin.getLogger().warn("User " + player.getUniqueId() + " - " + player.getUsername() +
|
||||||
|
" doesn't have data pre-loaded, they have never need processed during pre-login in this session.");
|
||||||
|
} else {
|
||||||
|
this.plugin.getLogger().warn("User " + player.getUniqueId() + " - " + player.getUsername() +
|
||||||
|
" doesn't currently have data pre-loaded, but they have been processed before in this session.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.plugin.getConfiguration().get(ConfigKeys.CANCEL_FAILED_LOGINS)) {
|
||||||
|
// disconnect the user
|
||||||
|
e.setResult(ResultedEvent.ComponentResult.denied(Message.LOADING_STATE_ERROR.asComponent(this.plugin.getLocaleManager())));
|
||||||
|
} else {
|
||||||
|
// just send a message
|
||||||
|
this.plugin.getBootstrap().getScheduler().asyncLater(() -> {
|
||||||
|
if (!player.isActive()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
player.sendMessage(Message.LOADING_STATE_ERROR.asComponent(this.plugin.getLocaleManager()));
|
||||||
|
}, 1, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait until the last priority to unload, so plugins can still perform permission checks on this event
|
||||||
|
@Subscribe(order = PostOrder.LAST)
|
||||||
|
public void onPlayerQuit(DisconnectEvent e) {
|
||||||
|
Player player = e.getPlayer();
|
||||||
|
|
||||||
|
// Register with the housekeeper, so the User's instance will stick
|
||||||
|
// around for a bit after they disconnect
|
||||||
|
this.plugin.getUserManager().getHouseKeeper().registerUsage(player.getUniqueId());
|
||||||
|
|
||||||
|
// force a clear of transient nodes
|
||||||
|
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||||
|
User user = this.plugin.getUserManager().getIfLoaded(player.getUniqueId());
|
||||||
|
if (user != null) {
|
||||||
|
user.clearTransientNodes();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of LuckPerms, licensed under the MIT License.
|
||||||
|
*
|
||||||
|
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package me.lucko.luckperms.velocity.messaging;
|
||||||
|
|
||||||
|
import com.google.common.io.ByteArrayDataInput;
|
||||||
|
import com.google.common.io.ByteArrayDataOutput;
|
||||||
|
import com.google.common.io.ByteStreams;
|
||||||
|
import com.velocitypowered.api.proxy.Player;
|
||||||
|
import com.velocitypowered.api.proxy.messages.ChannelIdentifier;
|
||||||
|
import com.velocitypowered.api.proxy.messages.ChannelMessageSource;
|
||||||
|
import com.velocitypowered.api.proxy.messages.ChannelRegistrar;
|
||||||
|
import com.velocitypowered.api.proxy.messages.ChannelSide;
|
||||||
|
import com.velocitypowered.api.proxy.messages.MessageHandler;
|
||||||
|
import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.api.messenger.IncomingMessageConsumer;
|
||||||
|
import me.lucko.luckperms.api.messenger.Messenger;
|
||||||
|
import me.lucko.luckperms.api.messenger.message.OutgoingMessage;
|
||||||
|
import me.lucko.luckperms.velocity.LPVelocityPlugin;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An implementation of {@link Messenger} using the plugin messaging channels.
|
||||||
|
*/
|
||||||
|
public class PluginMessageMessenger implements Messenger, MessageHandler {
|
||||||
|
private static final ChannelIdentifier CHANNEL = MinecraftChannelIdentifier.create("luckperms", "update");
|
||||||
|
|
||||||
|
private final LPVelocityPlugin plugin;
|
||||||
|
private final IncomingMessageConsumer consumer;
|
||||||
|
|
||||||
|
public PluginMessageMessenger(LPVelocityPlugin plugin, IncomingMessageConsumer consumer) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.consumer = consumer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
ChannelRegistrar channelRegistrar = this.plugin.getBootstrap().getProxy().getChannelRegistrar();
|
||||||
|
channelRegistrar.register(this, CHANNEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
// TODO: no way to unregister an individual MessageHandler?
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dispatchMessage(byte[] data) {
|
||||||
|
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||||
|
this.plugin.getBootstrap().getProxy().getAllPlayers().stream()
|
||||||
|
.map(Player::getCurrentServer)
|
||||||
|
.filter(Optional::isPresent)
|
||||||
|
.map(Optional::get)
|
||||||
|
.distinct()
|
||||||
|
.forEach(server -> server.sendPluginMessage(CHANNEL, data));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendOutgoingMessage(@Nonnull OutgoingMessage outgoingMessage) {
|
||||||
|
ByteArrayDataOutput out = ByteStreams.newDataOutput();
|
||||||
|
out.writeUTF(outgoingMessage.asEncodedString());
|
||||||
|
|
||||||
|
byte[] data = out.toByteArray();
|
||||||
|
dispatchMessage(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ForwardStatus handle(ChannelMessageSource source, ChannelSide side, ChannelIdentifier channel, byte[] data) {
|
||||||
|
if (side == ChannelSide.FROM_CLIENT) {
|
||||||
|
return ForwardStatus.HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteArrayDataInput in = ByteStreams.newDataInput(data);
|
||||||
|
String msg = in.readUTF();
|
||||||
|
|
||||||
|
if (this.consumer.consumeIncomingMessageAsString(msg)) {
|
||||||
|
// Forward to other servers
|
||||||
|
this.plugin.getBootstrap().getScheduler().executeAsync(() -> dispatchMessage(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ForwardStatus.HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of LuckPerms, licensed under the MIT License.
|
||||||
|
*
|
||||||
|
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package me.lucko.luckperms.velocity.messaging;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.api.messenger.IncomingMessageConsumer;
|
||||||
|
import me.lucko.luckperms.api.messenger.Messenger;
|
||||||
|
import me.lucko.luckperms.api.messenger.MessengerProvider;
|
||||||
|
import me.lucko.luckperms.velocity.LPVelocityPlugin;
|
||||||
|
import me.lucko.luckperms.common.messaging.InternalMessagingService;
|
||||||
|
import me.lucko.luckperms.common.messaging.LuckPermsMessagingService;
|
||||||
|
import me.lucko.luckperms.common.messaging.MessagingFactory;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
public class VelocityMessagingFactory extends MessagingFactory<LPVelocityPlugin> {
|
||||||
|
public VelocityMessagingFactory(LPVelocityPlugin plugin) {
|
||||||
|
super(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected InternalMessagingService getServiceFor(String messagingType) {
|
||||||
|
if (messagingType.equals("pluginmsg") || messagingType.equals("velocity")) {
|
||||||
|
try {
|
||||||
|
return new LuckPermsMessagingService(getPlugin(), new PluginMessageMessengerProvider());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.getServiceFor(messagingType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PluginMessageMessengerProvider implements MessengerProvider {
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "PluginMessage";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public Messenger obtain(@Nonnull IncomingMessageConsumer incomingMessageConsumer) {
|
||||||
|
PluginMessageMessenger messenger = new PluginMessageMessenger(getPlugin(), incomingMessageConsumer);
|
||||||
|
messenger.init();
|
||||||
|
return messenger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of LuckPerms, licensed under the MIT License.
|
||||||
|
*
|
||||||
|
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package me.lucko.luckperms.velocity.service;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.api.Tristate;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for converting between Velocity and LuckPerms tristate classes
|
||||||
|
*/
|
||||||
|
public final class CompatibilityUtil {
|
||||||
|
|
||||||
|
public static com.velocitypowered.api.permission.Tristate convertTristate(Tristate tristate) {
|
||||||
|
Objects.requireNonNull(tristate, "tristate");
|
||||||
|
switch (tristate) {
|
||||||
|
case TRUE:
|
||||||
|
return com.velocitypowered.api.permission.Tristate.TRUE;
|
||||||
|
case FALSE:
|
||||||
|
return com.velocitypowered.api.permission.Tristate.FALSE;
|
||||||
|
default:
|
||||||
|
return com.velocitypowered.api.permission.Tristate.UNDEFINED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Tristate convertTristate(com.velocitypowered.api.permission.Tristate tristate) {
|
||||||
|
Objects.requireNonNull(tristate, "tristate");
|
||||||
|
switch (tristate) {
|
||||||
|
case TRUE:
|
||||||
|
return Tristate.TRUE;
|
||||||
|
case FALSE:
|
||||||
|
return Tristate.FALSE;
|
||||||
|
default:
|
||||||
|
return Tristate.UNDEFINED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CompatibilityUtil() {}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package me.lucko.luckperms.velocity.service;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import com.velocitypowered.api.permission.PermissionFunction;
|
||||||
|
import com.velocitypowered.api.permission.PermissionProvider;
|
||||||
|
import com.velocitypowered.api.permission.PermissionSubject;
|
||||||
|
import com.velocitypowered.api.permission.Tristate;
|
||||||
|
import com.velocitypowered.api.proxy.Player;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.contexts.ContextsSupplier;
|
||||||
|
import me.lucko.luckperms.common.model.User;
|
||||||
|
import me.lucko.luckperms.common.verbose.CheckOrigin;
|
||||||
|
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
|
||||||
|
public class PlayerPermissionProvider implements PermissionProvider, PermissionFunction {
|
||||||
|
private final Player player;
|
||||||
|
private final User user;
|
||||||
|
private final ContextsSupplier contextsSupplier;
|
||||||
|
|
||||||
|
public PlayerPermissionProvider(Player player, User user, ContextsSupplier contextsSupplier) {
|
||||||
|
this.player = player;
|
||||||
|
this.user = user;
|
||||||
|
this.contextsSupplier = contextsSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull PermissionFunction createFunction(@NonNull PermissionSubject subject) {
|
||||||
|
Preconditions.checkState(subject == this.player, "createFunction called with different argument");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull Tristate getPermissionSetting(@NonNull String permission) {
|
||||||
|
return CompatibilityUtil.convertTristate(this.user.getCachedData().getPermissionData(this.contextsSupplier.getContexts()).getPermissionValue(permission, CheckOrigin.PLATFORM_PERMISSION_CHECK));
|
||||||
|
}
|
||||||
|
}
|
531
velocity/src/main/resources/config.yml
Normal file
531
velocity/src/main/resources/config.yml
Normal file
@ -0,0 +1,531 @@
|
|||||||
|
####################################################################################################
|
||||||
|
# +----------------------------------------------------------------------------------------------+ #
|
||||||
|
# | __ __ ___ __ __ | #
|
||||||
|
# | | | | / ` |__/ |__) |__ |__) |\/| /__` | #
|
||||||
|
# | |___ \__/ \__, | \ | |___ | \ | | .__/ | #
|
||||||
|
# | | #
|
||||||
|
# | | #
|
||||||
|
# | SOURCE CODE: https://github.com/lucko/LuckPerms | #
|
||||||
|
# | WIKI: https://github.com/lucko/LuckPerms/wiki | #
|
||||||
|
# | BUG REPORTS: https://github.com/lucko/LuckPerms/issues | #
|
||||||
|
# | | #
|
||||||
|
# | Each option in this file is documented and explained here: | #
|
||||||
|
# | ==> https://github.com/lucko/LuckPerms/wiki/Configuration | #
|
||||||
|
# | | #
|
||||||
|
# | New options are not added to this file automatically. Default values are used if an | #
|
||||||
|
# | option cannot be found. The latest config versions can be obtained at the link above. | #
|
||||||
|
# +----------------------------------------------------------------------------------------------+ #
|
||||||
|
####################################################################################################
|
||||||
|
|
||||||
|
# +----------------------------------------------------------------------------------------------+ #
|
||||||
|
# | | #
|
||||||
|
# | ESSENTIAL SETTINGS | #
|
||||||
|
# | | #
|
||||||
|
# | Important settings that control how LuckPerms functions. | #
|
||||||
|
# | | #
|
||||||
|
# +----------------------------------------------------------------------------------------------+ #
|
||||||
|
|
||||||
|
# The name of the server, used for server specific permissions.
|
||||||
|
#
|
||||||
|
# - When set to "global" this setting is effectively ignored.
|
||||||
|
# - In all other cases, the value here is added to all players in a "server" context.
|
||||||
|
# - See: https://github.com/lucko/LuckPerms/wiki/Context
|
||||||
|
server: proxy
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# +----------------------------------------------------------------------------------------------+ #
|
||||||
|
# | | #
|
||||||
|
# | STORAGE SETTINGS | #
|
||||||
|
# | | #
|
||||||
|
# | Controls which storage method LuckPerms will use to store data. | #
|
||||||
|
# | | #
|
||||||
|
# +----------------------------------------------------------------------------------------------+ #
|
||||||
|
|
||||||
|
# How the plugin should store data
|
||||||
|
#
|
||||||
|
# - The various options are explained in more detail on the wiki:
|
||||||
|
# https://github.com/lucko/LuckPerms/wiki/Choosing-a-Storage-type
|
||||||
|
#
|
||||||
|
# - Possible options:
|
||||||
|
#
|
||||||
|
# | Remote databases - require connection information to be configured below
|
||||||
|
# |=> MySQL
|
||||||
|
# |=> MariaDB (preferred over MySQL)
|
||||||
|
# |=> PostgreSQL
|
||||||
|
# |=> MongoDB
|
||||||
|
#
|
||||||
|
# | Flatfile/local database - don't require any extra configuration
|
||||||
|
# |=> H2 (preferred over SQLite)
|
||||||
|
# |=> SQLite
|
||||||
|
#
|
||||||
|
# | Readable & editable text files - don't require any extra configuration
|
||||||
|
# |=> YAML (.yml files)
|
||||||
|
# |=> JSON (.json files)
|
||||||
|
# |=> HOCON (.conf files)
|
||||||
|
# |=> TOML (.toml files)
|
||||||
|
# |
|
||||||
|
# | By default, user, group and track data is separated into different files. Data can be combined
|
||||||
|
# | and all stored in the same file by switching to a combined storage variant.
|
||||||
|
# | Just add '-combined' to the end of the storage-method, e.g. 'yaml-combined'
|
||||||
|
#
|
||||||
|
# - A H2 database is the default option.
|
||||||
|
# - If you want to edit data manually in "traditional" storage files, we suggest using YAML.
|
||||||
|
storage-method: h2
|
||||||
|
|
||||||
|
# The following block defines the settings for remote database storage methods.
|
||||||
|
#
|
||||||
|
# - You don't need to touch any of the settings here if you're using a local storage method!
|
||||||
|
# - The connection detail options are shared between all remote storage types.
|
||||||
|
data:
|
||||||
|
|
||||||
|
# Define the address and port for the database.
|
||||||
|
# - The standard DB engine port is used by default
|
||||||
|
# (MySQL: 3306, PostgreSQL: 5432, MongoDB: 27017)
|
||||||
|
# - Specify as "host:port" if differs
|
||||||
|
address: localhost
|
||||||
|
|
||||||
|
# The name of the database to store LuckPerms data in.
|
||||||
|
# - This must be created already. Don't worry about this setting if you're using MongoDB.
|
||||||
|
database: minecraft
|
||||||
|
|
||||||
|
# Credentials for the database.
|
||||||
|
username: root
|
||||||
|
password: ''
|
||||||
|
|
||||||
|
# These settings apply to the MySQL connection pool.
|
||||||
|
# - The default values will be suitable for the majority of users.
|
||||||
|
# - Do not change these settings unless you know what you're doing!
|
||||||
|
pool-settings:
|
||||||
|
|
||||||
|
# Sets the maximum size of the MySQL connection pool.
|
||||||
|
# - Basically this value will determine the maximum number of actual
|
||||||
|
# connections to the database backend.
|
||||||
|
# - More information about determining the size of connection pools can be found here:
|
||||||
|
# https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing
|
||||||
|
maximum-pool-size: 10
|
||||||
|
|
||||||
|
# Sets the minimum number of idle connections that the pool will try to maintain.
|
||||||
|
# - For maximum performance and responsiveness to spike demands, it is recommended to not set
|
||||||
|
# this value and instead allow the pool to act as a fixed size connection pool.
|
||||||
|
# (set this value to the same as 'maximum-pool-size')
|
||||||
|
minimum-idle: 10
|
||||||
|
|
||||||
|
# This setting controls the maximum lifetime of a connection in the pool in milliseconds.
|
||||||
|
# - The value should be at least 30 seconds less than any database or infrastructure imposed
|
||||||
|
# connection time limit.
|
||||||
|
maximum-lifetime: 1800000 # 30 minutes
|
||||||
|
|
||||||
|
# This setting controls the maximum number of milliseconds that the plugin will wait for a
|
||||||
|
# connection from the pool, before timing out.
|
||||||
|
connection-timeout: 5000 # 5 seconds
|
||||||
|
|
||||||
|
# This setting allows you to define extra properties for connections.
|
||||||
|
properties:
|
||||||
|
useUnicode: true
|
||||||
|
characterEncoding: utf8
|
||||||
|
|
||||||
|
# The prefix for all LuckPerms SQL tables.
|
||||||
|
# - Change this is you want to use different tables for different servers.
|
||||||
|
table_prefix: 'luckperms_'
|
||||||
|
|
||||||
|
# The prefix to use for all LuckPerms collections. Change this if you want to use different
|
||||||
|
# collections for different servers. The default is no prefix.
|
||||||
|
mongodb_collection_prefix: ''
|
||||||
|
|
||||||
|
# MongoDB ClientConnectionURI for use with replica sets and custom connection options
|
||||||
|
# - See https://docs.mongodb.com/manual/reference/connection-string/
|
||||||
|
mongodb_connection_URI: ''
|
||||||
|
|
||||||
|
# Define settings for a "split" storage setup.
|
||||||
|
#
|
||||||
|
# - This allows you to define a storage method for each type of data.
|
||||||
|
# - The connection options above still have to be correct for each type here.
|
||||||
|
split-storage:
|
||||||
|
# Don't touch this if you don't want to use split storage!
|
||||||
|
enabled: false
|
||||||
|
methods:
|
||||||
|
# These options don't need to be modified if split storage isn't enabled.
|
||||||
|
user: h2
|
||||||
|
group: h2
|
||||||
|
track: h2
|
||||||
|
uuid: h2
|
||||||
|
log: h2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# +----------------------------------------------------------------------------------------------+ #
|
||||||
|
# | | #
|
||||||
|
# | UPDATE PROPAGATION & MESSAGING SERVICE | #
|
||||||
|
# | | #
|
||||||
|
# | Controls the ways in which LuckPerms will sync data & notify other servers of changes. | #
|
||||||
|
# | These options are documented on greater detail on the wiki under "Instant Updates". | #
|
||||||
|
# | | #
|
||||||
|
# +----------------------------------------------------------------------------------------------+ #
|
||||||
|
|
||||||
|
# This option controls how frequently LuckPerms will perform a sync task.
|
||||||
|
#
|
||||||
|
# - A sync task will refresh all data from the storage, and ensure that the most up-to-date data is
|
||||||
|
# being used by the plugin.
|
||||||
|
# - This is disabled by default, as most users will not need it. However, if you're using a remote
|
||||||
|
# storage type without a messaging service setup, you may wish to set this to something like 3.
|
||||||
|
# - Set to -1 to disable the task completely.
|
||||||
|
sync-minutes: -1
|
||||||
|
|
||||||
|
# If the file watcher should be enabled.
|
||||||
|
#
|
||||||
|
# - When using a file-based storage type, LuckPerms can monitor the data files for changes, and
|
||||||
|
# automatically update when changes are detected.
|
||||||
|
# - If you don't want this feature to be active, set this option to false.
|
||||||
|
watch-files: true
|
||||||
|
|
||||||
|
# Define which messaging service should be used by the plugin.
|
||||||
|
#
|
||||||
|
# - If enabled and configured, LuckPerms will use the messaging service to inform other connected
|
||||||
|
# servers of changes.
|
||||||
|
# - Use the command "/lp networksync" to manually push changes.
|
||||||
|
# - Data is NOT stored using this service. It is only used as a messaging platform.
|
||||||
|
#
|
||||||
|
# - If you decide to enable this feature, you should set "sync-minutes" to -1, as there is no need
|
||||||
|
# for LuckPerms to poll the database for changes.
|
||||||
|
#
|
||||||
|
# - Possible options:
|
||||||
|
# => sql Uses the SQL database to form a queue system for communication. Will only work
|
||||||
|
# when 'storage-method' is set to MySQL or MariaDB. This is chosen by default if
|
||||||
|
# the option is set to 'none' and SQL storage is in use. Set to 'notsql' to
|
||||||
|
# disable this.
|
||||||
|
# => pluginmsg Uses the plugin messaging channels to communicate with the proxy.
|
||||||
|
# LuckPerms must be installed on your proxy & all connected servers backend
|
||||||
|
# servers. Won't work if you have more than one Velocity proxy.
|
||||||
|
# => redis Uses Redis pub-sub to push changes. Your server connection info must be
|
||||||
|
# configured below.
|
||||||
|
# => none Disables the service.
|
||||||
|
messaging-service: none
|
||||||
|
|
||||||
|
# If LuckPerms should automatically push updates after a change has been made with a command.
|
||||||
|
auto-push-updates: true
|
||||||
|
|
||||||
|
# If LuckPerms should push logging entries to connected servers via the messaging service.
|
||||||
|
push-log-entries: true
|
||||||
|
|
||||||
|
# If LuckPerms should broadcast received logging entries to players on this platform.
|
||||||
|
#
|
||||||
|
# - If you have LuckPerms installed on your backend servers as well as a Velocity proxy, you
|
||||||
|
# should set this option to false on either your backends or your proxies, to avoid players being
|
||||||
|
# messaged twice about log entries.
|
||||||
|
broadcast-received-log-entries: false
|
||||||
|
|
||||||
|
# Settings for Redis.
|
||||||
|
# Port 6379 is used by default; set address to "host:port" if differs
|
||||||
|
redis:
|
||||||
|
enabled: false
|
||||||
|
address: localhost
|
||||||
|
password: ''
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# +----------------------------------------------------------------------------------------------+ #
|
||||||
|
# | | #
|
||||||
|
# | CUSTOMIZATION SETTINGS | #
|
||||||
|
# | | #
|
||||||
|
# | Settings that allow admins to customize the way LuckPerms operates. | #
|
||||||
|
# | | #
|
||||||
|
# +----------------------------------------------------------------------------------------------+ #
|
||||||
|
|
||||||
|
# If LuckPerms should ensure all players have permission data when they connect to the server.
|
||||||
|
#
|
||||||
|
# - When set to true, LuckPerms will cancel login attempts if it is unable to load permissions data
|
||||||
|
# for a user, of if the storage provider is unavailable.
|
||||||
|
# - When set to false, LuckPerms will allow a player to connect regardless of whether their
|
||||||
|
# permissions data could be loaded.
|
||||||
|
# - This option does not exist on other platforms, and effectively defaults to true - however,
|
||||||
|
# the option is provided on Velocity, as it is less likely to be so dependant on permissions.
|
||||||
|
cancel-failed-logins: false
|
||||||
|
|
||||||
|
# Controls how temporary permissions/parents/meta should be accumulated.
|
||||||
|
#
|
||||||
|
# - The default behaviour is "deny".
|
||||||
|
# - This behaviour can also be specified when the command is executed. See the command usage
|
||||||
|
# documentation for more info.
|
||||||
|
#
|
||||||
|
# - Possible options:
|
||||||
|
# => accumulate durations will be added to the existing expiry time
|
||||||
|
# => replace durations will be replaced if the new duration is later than the current
|
||||||
|
# expiration
|
||||||
|
# => deny the command will just fail if you try to add another node with the same expiry
|
||||||
|
temporary-add-behaviour: deny
|
||||||
|
|
||||||
|
# Controls how LuckPerms will determine a users "primary" group.
|
||||||
|
#
|
||||||
|
# - The meaning and influence of "primary groups" are explained in detail on the wiki.
|
||||||
|
# - The preferred approach is to let LuckPerms automatically determine a users primary group
|
||||||
|
# based on the relative weight of their parent groups.
|
||||||
|
#
|
||||||
|
# - Possible options:
|
||||||
|
# => stored use the value stored against the users record in the file/database
|
||||||
|
# => parents-by-weight just use the users most highly weighted parent
|
||||||
|
# => all-parents-by-weight same as above, but calculates based upon all parents inherited from
|
||||||
|
# both directly and indirectly
|
||||||
|
primary-group-calculation: parents-by-weight
|
||||||
|
|
||||||
|
# If the plugin should check for "extra" permissions with users run LP commands.
|
||||||
|
#
|
||||||
|
# - These extra permissions allow finer control over what users can do with each command, and who
|
||||||
|
# they have access to edit.
|
||||||
|
# - The nature of the checks are documented on the wiki under "Argument based command permissions".
|
||||||
|
# - Argument based permissions are *not* static, unlike the 'base' permissions, and will depend upon
|
||||||
|
# the arguments given within the command.
|
||||||
|
argument-based-command-permissions: false
|
||||||
|
|
||||||
|
# If the plugin should send log notifications to users whenever permissions are modified.
|
||||||
|
#
|
||||||
|
# - Notifications are only sent to those with the appropriate permission to receive them
|
||||||
|
# - They can also be temporarily enabled/disabled on a per-user basis using
|
||||||
|
# '/lp log notify <on|off>'
|
||||||
|
log-notify: true
|
||||||
|
|
||||||
|
# Defines the options for prefix and suffix stacking.
|
||||||
|
#
|
||||||
|
# - The feature allows you to display multiple prefixes or suffixes alongside a players username in
|
||||||
|
# chat.
|
||||||
|
# - It is explained and documented in more detail on the wiki under "Prefix & Suffix Stacking".
|
||||||
|
#
|
||||||
|
# - The options are divided into separate sections for prefixes and suffixes.
|
||||||
|
# - The value of 'start-spacer' is included at the start of the resultant prefix/suffix.
|
||||||
|
# - The value of 'end-spacer' is included at the end of the resultant prefix/suffix.
|
||||||
|
# - The value of 'middle-spacer' is included between each element in the resultant prefix/suffix.
|
||||||
|
#
|
||||||
|
# - Possible format options:
|
||||||
|
# => highest Selects the value with the highest weight, from all values
|
||||||
|
# held by or inherited by the player.
|
||||||
|
#
|
||||||
|
# => lowest Same as above, except takes the one with the lowest weight.
|
||||||
|
#
|
||||||
|
# => highest_own Selects the value with the highest weight, but will not
|
||||||
|
# accept any inherited values.
|
||||||
|
#
|
||||||
|
# => lowest_own Same as above, except takes the value with the lowest weight.
|
||||||
|
#
|
||||||
|
# => highest_inherited Selects the value with the highest weight, but will only
|
||||||
|
# accept inherited values.
|
||||||
|
#
|
||||||
|
# => lowest_inherited Same as above, except takes the value with the lowest weight.
|
||||||
|
#
|
||||||
|
# => highest_on_track_<track> Selects the value with the highest weight, but only if the
|
||||||
|
# value was inherited from a group on the given track.
|
||||||
|
#
|
||||||
|
# => lowest_on_track_<track> Same as above, except takes the value with the lowest weight.
|
||||||
|
#
|
||||||
|
# => highest_not_on_track_<track> Selects the value with the highest weight, but only if the
|
||||||
|
# value was inherited from a group not on the given track.
|
||||||
|
#
|
||||||
|
# => lowest_not_on_track_<track> Same as above, except takes the value with the lowest weight.
|
||||||
|
meta-formatting:
|
||||||
|
prefix:
|
||||||
|
format:
|
||||||
|
- "highest"
|
||||||
|
start-spacer: ""
|
||||||
|
middle-spacer: " "
|
||||||
|
end-spacer: ""
|
||||||
|
suffix:
|
||||||
|
format:
|
||||||
|
- "highest"
|
||||||
|
start-spacer: ""
|
||||||
|
middle-spacer: " "
|
||||||
|
end-spacer: ""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# +----------------------------------------------------------------------------------------------+ #
|
||||||
|
# | | #
|
||||||
|
# | PERMISSION CALCULATION AND INHERITANCE | #
|
||||||
|
# | | #
|
||||||
|
# | Modify the way permission checks, meta lookups and inheritance resolutions are handled. | #
|
||||||
|
# | | #
|
||||||
|
# +----------------------------------------------------------------------------------------------+ #
|
||||||
|
|
||||||
|
# The algorithm LuckPerms should use when traversing the "inheritance tree".
|
||||||
|
#
|
||||||
|
# - Possible options:
|
||||||
|
# => breadth-first See: https://en.wikipedia.org/wiki/Breadth-first_search
|
||||||
|
# => depth-first-pre-order See: https://en.wikipedia.org/wiki/Depth-first_search
|
||||||
|
# => depth-first-post-order See: https://en.wikipedia.org/wiki/Depth-first_search
|
||||||
|
inheritance-traversal-algorithm: depth-first-pre-order
|
||||||
|
|
||||||
|
# +----------------------------------------------------------------------------------------------+ #
|
||||||
|
# | Permission resolution settings | #
|
||||||
|
# +----------------------------------------------------------------------------------------------+ #
|
||||||
|
|
||||||
|
# If users on this server should have their global permissions applied.
|
||||||
|
# When set to false, only server specific permissions will apply for users on this server
|
||||||
|
include-global: true
|
||||||
|
|
||||||
|
# If users on this server should have their global world permissions applied.
|
||||||
|
# When set to false, only world specific permissions will apply for users on this server
|
||||||
|
include-global-world: true
|
||||||
|
|
||||||
|
# If users on this server should have global (non-server specific) groups applied
|
||||||
|
apply-global-groups: true
|
||||||
|
|
||||||
|
# If users on this server should have global (non-world specific) groups applied
|
||||||
|
apply-global-world-groups: true
|
||||||
|
|
||||||
|
# +----------------------------------------------------------------------------------------------+ #
|
||||||
|
# | Inheritance settings | #
|
||||||
|
# +----------------------------------------------------------------------------------------------+ #
|
||||||
|
|
||||||
|
# If the plugin should apply wildcard permissions.
|
||||||
|
#
|
||||||
|
# - If set to true, LuckPerms will detect wildcard permissions, and resolve & apply all registered
|
||||||
|
# permissions matching the wildcard.
|
||||||
|
apply-wildcards: true
|
||||||
|
|
||||||
|
# If the plugin should parse regex permissions.
|
||||||
|
#
|
||||||
|
# - If set to true, LuckPerms will detect regex permissions, marked with "r=" at the start of the
|
||||||
|
# node, and resolve & apply all registered permissions matching the regex.
|
||||||
|
apply-regex: true
|
||||||
|
|
||||||
|
# If the plugin should complete and apply shorthand permissions.
|
||||||
|
#
|
||||||
|
# - If set to true, LuckPerms will detect and expand shorthand node patterns.
|
||||||
|
apply-shorthand: true
|
||||||
|
|
||||||
|
# +----------------------------------------------------------------------------------------------+ #
|
||||||
|
# | Extra settings | #
|
||||||
|
# +----------------------------------------------------------------------------------------------+ #
|
||||||
|
|
||||||
|
# Allows you to set "aliases" for the worlds sent forward for context calculation.
|
||||||
|
#
|
||||||
|
# - These aliases are provided in addition to the real world name. Applied recursively.
|
||||||
|
# - Remove the comment characters for the default aliases to apply.
|
||||||
|
world-rewrite:
|
||||||
|
# world_nether: world
|
||||||
|
# world_the_end: world
|
||||||
|
|
||||||
|
# Define special group weights for this server.
|
||||||
|
#
|
||||||
|
# - Group weights can also be applied directly to group data, using the setweight command.
|
||||||
|
# - This section allows weights to be set on a per-server basis.
|
||||||
|
group-weight:
|
||||||
|
# admin: 10
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# +----------------------------------------------------------------------------------------------+ #
|
||||||
|
# | | #
|
||||||
|
# | FINE TUNING OPTIONS | #
|
||||||
|
# | | #
|
||||||
|
# | A number of more niche settings for tweaking and changing behaviour. The section also | #
|
||||||
|
# | contains toggles for some more specialised features. It is only necessary to make changes to | #
|
||||||
|
# | these options if you want to fine-tune LuckPerms behaviour. | #
|
||||||
|
# | | #
|
||||||
|
# +----------------------------------------------------------------------------------------------+ #
|
||||||
|
|
||||||
|
# +----------------------------------------------------------------------------------------------+ #
|
||||||
|
# | Miscellaneous (and rarely used) settings | #
|
||||||
|
# +----------------------------------------------------------------------------------------------+ #
|
||||||
|
|
||||||
|
# If LuckPerms should produce extra logging output when it handles logins.
|
||||||
|
#
|
||||||
|
# - Useful if you're having issues with UUID forwarding or data not being loaded.
|
||||||
|
debug-logins: false
|
||||||
|
|
||||||
|
# If LuckPerms should allow usernames with non alphanumeric characters.
|
||||||
|
#
|
||||||
|
# - Note that due to the design of the storage implementation, usernames must still be 16 characters
|
||||||
|
# or less.
|
||||||
|
allow-invalid-usernames: false
|
||||||
|
|
||||||
|
# If LuckPerms should allow a users primary group to be removed with the 'parent remove' command.
|
||||||
|
#
|
||||||
|
# - When this happens, the plugin will set their primary group back to default.
|
||||||
|
prevent-primary-group-removal: false
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# +----------------------------------------------------------------------------------------------+ #
|
||||||
|
# | | #
|
||||||
|
# | DEFAULT ASSIGNMENTS | #
|
||||||
|
# | | #
|
||||||
|
# +----------------------------------------------------------------------------------------------+ #
|
||||||
|
|
||||||
|
# This section allows you to define defaults to give users whenever they connect to the server.
|
||||||
|
# The default assignments are highly configurable and conditional.
|
||||||
|
#
|
||||||
|
# There is one default assignment built into LuckPerms, which will add all users to the "default"
|
||||||
|
# group if they are not a member of any other group. This setting cannot be disabled. However, you
|
||||||
|
# can use this section to add more of your own.
|
||||||
|
#
|
||||||
|
# IMPORTANT:
|
||||||
|
# In order to save storage space, LuckPerms does not store users who have no permissions defined,
|
||||||
|
# and are only a member of the default group. Adding default assignments to this section will negate
|
||||||
|
# this effect. It is HIGHLY RECCOMENDED that instead of assigning defaults here, you add permissions
|
||||||
|
# to the "default" group, or set the "default" group to inherit other groups, and then use the
|
||||||
|
# group-name-rewrite rule above.
|
||||||
|
#
|
||||||
|
# It is also important to note that these rules are considered every time a player logs into the
|
||||||
|
# server, and are applied directly to the user's data. Simply removing a rule here will not reverse
|
||||||
|
# the effect of that rule on any users who have already had it applied to them.
|
||||||
|
#
|
||||||
|
# The "has" and "lacks" conditions below support standard boolean logic, using the 'and' & 'or'
|
||||||
|
# characters used in Java.
|
||||||
|
# e.g. "(some.other.permission | some.permission.other) & some.thing.else" == a user has
|
||||||
|
# 'some.other.permission', or 'some.permission.other', and they also have 'some.thing.else'
|
||||||
|
#
|
||||||
|
# Groups are represented by the permission node: group.<group name>
|
||||||
|
# Per server and per world nodes are represented by "server-world/permission" or "server/permission"
|
||||||
|
#
|
||||||
|
# Within conditions, permission nodes MUST be escaped using "<" and ">". See the example below.
|
||||||
|
#
|
||||||
|
# Explanation of the examples below: (they're just to demonstrate the features & use cases)
|
||||||
|
#
|
||||||
|
# rule1:
|
||||||
|
# If a user is either in the vip or vip+ group, and they have the "titles.titlecollector" permission
|
||||||
|
# set to true, and the "some.random.permission" set to false... if they're not in the group
|
||||||
|
# "prison_titlepack" on the "prison" server, then give add them to the "prison_titlepack" group on
|
||||||
|
# the "prison" server, and remove "some.random.permission".
|
||||||
|
#
|
||||||
|
# rule2:
|
||||||
|
# If the user isn't in any of the following groups on the skyblock server: sb_level1, sb_level2,
|
||||||
|
# sb_level3, then add them to sb_level1 on the skyblock server.
|
||||||
|
#
|
||||||
|
# rule3:
|
||||||
|
# If the user is a member of the default group, remove them from default, add them to member, and
|
||||||
|
# set their primary group to member.
|
||||||
|
#
|
||||||
|
# WARNING: Unlike internal commands, this system does not ensure that a group exists before adding
|
||||||
|
# a user to it. It also does not unsure that a user is a member of a group before making that group
|
||||||
|
# their primary group.
|
||||||
|
#
|
||||||
|
# Before you use "give: group.<name>" or "set-primary-group", make sure that the group exists, and
|
||||||
|
# that the user is a member of the group.
|
||||||
|
default-assignments:
|
||||||
|
# rule1:
|
||||||
|
# if:
|
||||||
|
# has-true: (<group.vip> | <group.vip+>) & <titles.tilecollector>
|
||||||
|
# has-false: <some.random.permission>
|
||||||
|
# lacks: <prison/group.prison_titlepack>
|
||||||
|
# give:
|
||||||
|
# - prison/group.prison_titlepack
|
||||||
|
# take:
|
||||||
|
# - some.random.permission
|
||||||
|
# rule2:
|
||||||
|
# if:
|
||||||
|
# lacks: <skyblock/group.sb_level1> & <skyblock/group.sb_level2> & <skyblock/group.sb_level3>
|
||||||
|
# give:
|
||||||
|
# - skyblock/group.sb_level1
|
||||||
|
# rule3:
|
||||||
|
# if:
|
||||||
|
# has-true: <group.default>
|
||||||
|
# take:
|
||||||
|
# - group.default
|
||||||
|
# give:
|
||||||
|
# - group.member
|
||||||
|
# set-primary-group: member
|
Loading…
Reference in New Issue
Block a user