diff --git a/api/src/main/java/net/luckperms/api/context/DefaultContextKeys.java b/api/src/main/java/net/luckperms/api/context/DefaultContextKeys.java
index 0097e3193..174b46c16 100644
--- a/api/src/main/java/net/luckperms/api/context/DefaultContextKeys.java
+++ b/api/src/main/java/net/luckperms/api/context/DefaultContextKeys.java
@@ -34,13 +34,31 @@ public final class DefaultContextKeys {
}
/**
- * The context key used to denote the subjects server.
+ * The context key used to denote the name of the subjects server.
*/
public static final String SERVER_KEY = "server";
/**
- * The context key used to denote the subjects world.
+ * The context key used to denote the name of the subjects world.
*/
public static final String WORLD_KEY = "world";
+ /**
+ * The context key used to denote the dimension type of the subjects world.
+ *
+ *
Possible values: overworld, the_nether, the_end
+ *
+ * @since 5.3
+ */
+ public static final String DIMENSION_TYPE_KEY = "dimension-type";
+
+ /**
+ * The context key used to denote the subjects gamemode.
+ *
+ * Possible values: survival, creative, adventure, spectator
+ *
+ * @since 5.3
+ */
+ public static final String GAMEMODE_KEY = "gamemode";
+
}
diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java
index ce36b47d6..ef2d01683 100644
--- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java
+++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java
@@ -28,7 +28,7 @@ package me.lucko.luckperms.bukkit;
import me.lucko.luckperms.bukkit.brigadier.LuckPermsBrigadier;
import me.lucko.luckperms.bukkit.calculator.BukkitCalculatorFactory;
import me.lucko.luckperms.bukkit.context.BukkitContextManager;
-import me.lucko.luckperms.bukkit.context.WorldCalculator;
+import me.lucko.luckperms.bukkit.context.BukkitPlayerCalculator;
import me.lucko.luckperms.bukkit.inject.permissible.LuckPermsPermissible;
import me.lucko.luckperms.bukkit.inject.permissible.PermissibleInjector;
import me.lucko.luckperms.bukkit.inject.permissible.PermissibleMonitoringInjector;
@@ -186,9 +186,9 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
protected void setupContextManager() {
this.contextManager = new BukkitContextManager(this);
- WorldCalculator worldCalculator = new WorldCalculator(this);
- this.bootstrap.getServer().getPluginManager().registerEvents(worldCalculator, this.bootstrap);
- this.contextManager.registerCalculator(worldCalculator);
+ BukkitPlayerCalculator playerCalculator = new BukkitPlayerCalculator(this);
+ this.bootstrap.getServer().getPluginManager().registerEvents(playerCalculator, this.bootstrap);
+ this.contextManager.registerCalculator(playerCalculator);
}
@Override
diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/context/WorldCalculator.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/context/BukkitPlayerCalculator.java
similarity index 58%
rename from bukkit/src/main/java/me/lucko/luckperms/bukkit/context/WorldCalculator.java
rename to bukkit/src/main/java/me/lucko/luckperms/bukkit/context/BukkitPlayerCalculator.java
index e4eae67de..1bdcfda2e 100644
--- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/context/WorldCalculator.java
+++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/context/BukkitPlayerCalculator.java
@@ -25,9 +25,12 @@
package me.lucko.luckperms.bukkit.context;
+import com.google.common.collect.ImmutableMap;
+
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.context.contextset.ImmutableContextSetImpl;
+import me.lucko.luckperms.common.util.EnumNamer;
import net.luckperms.api.context.Context;
import net.luckperms.api.context.ContextCalculator;
@@ -36,42 +39,57 @@ import net.luckperms.api.context.ContextSet;
import net.luckperms.api.context.DefaultContextKeys;
import net.luckperms.api.context.ImmutableContextSet;
+import org.bukkit.GameMode;
import org.bukkit.World;
+import org.bukkit.World.Environment;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerChangedWorldEvent;
+import org.bukkit.event.player.PlayerGameModeChangeEvent;
import org.checkerframework.checker.nullness.qual.NonNull;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+public class BukkitPlayerCalculator implements ContextCalculator, Listener {
+ private static final EnumNamer GAMEMODE_NAMER = new EnumNamer<>(
+ GameMode.class,
+ EnumNamer.LOWER_CASE_NAME
+ );
+ private static final EnumNamer DIMENSION_TYPE_NAMER = new EnumNamer<>(
+ Environment.class,
+ // use the namespaced keys used by the game
+ ImmutableMap.builder()
+ .put(Environment.NORMAL, "overworld")
+ .put(Environment.NETHER, "the_nether")
+ .put(Environment.THE_END, "the_end")
+ .build(),
+ EnumNamer.LOWER_CASE_NAME
+ );
-public class WorldCalculator implements ContextCalculator, Listener {
private final LPBukkitPlugin plugin;
- public WorldCalculator(LPBukkitPlugin plugin) {
+ public BukkitPlayerCalculator(LPBukkitPlugin plugin) {
this.plugin = plugin;
}
@Override
public void calculate(@NonNull Player subject, @NonNull ContextConsumer consumer) {
- Set seen = new HashSet<>();
- String world = subject.getWorld().getName().toLowerCase();
- // seems like world names can sometimes be the empty string
- // see: https://github.com/lucko/LuckPerms/issues/2119
- while (Context.isValidValue(world) && seen.add(world)) {
- consumer.accept(DefaultContextKeys.WORLD_KEY, world);
- world = this.plugin.getConfiguration().get(ConfigKeys.WORLD_REWRITES).getOrDefault(world, world).toLowerCase();
- }
+ World world = subject.getWorld();
+ consumer.accept(DefaultContextKeys.GAMEMODE_KEY, GAMEMODE_NAMER.name(subject.getGameMode()));
+ consumer.accept(DefaultContextKeys.DIMENSION_TYPE_KEY, DIMENSION_TYPE_NAMER.name(world.getEnvironment()));
+ this.plugin.getConfiguration().get(ConfigKeys.WORLD_REWRITES).rewriteAndSubmit(world.getName(), consumer);
}
@Override
public ContextSet estimatePotentialContexts() {
- List worlds = this.plugin.getBootstrap().getServer().getWorlds();
ImmutableContextSet.Builder builder = new ImmutableContextSetImpl.BuilderImpl();
- for (World world : worlds) {
+ for (GameMode mode : GameMode.values()) {
+ builder.add(DefaultContextKeys.GAMEMODE_KEY, GAMEMODE_NAMER.name(mode));
+ }
+ for (Environment env : Environment.values()) {
+ builder.add(DefaultContextKeys.DIMENSION_TYPE_KEY, DIMENSION_TYPE_NAMER.name(env));
+ }
+ for (World world : this.plugin.getBootstrap().getServer().getWorlds()) {
String name = world.getName().toLowerCase();
if (Context.isValidValue(name)) {
builder.add(DefaultContextKeys.WORLD_KEY, name);
@@ -84,4 +102,9 @@ public class WorldCalculator implements ContextCalculator, Listener {
public void onWorldChange(PlayerChangedWorldEvent e) {
this.plugin.getContextManager().signalContextUpdate(e.getPlayer());
}
+
+ @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
+ public void onGameModeChange(PlayerGameModeChangeEvent e) {
+ this.plugin.getContextManager().signalContextUpdate(e.getPlayer());
+ }
}
diff --git a/bungee/src/main/java/me/lucko/luckperms/bungee/LPBungeePlugin.java b/bungee/src/main/java/me/lucko/luckperms/bungee/LPBungeePlugin.java
index b227af8d1..fce7987e6 100644
--- a/bungee/src/main/java/me/lucko/luckperms/bungee/LPBungeePlugin.java
+++ b/bungee/src/main/java/me/lucko/luckperms/bungee/LPBungeePlugin.java
@@ -26,8 +26,8 @@
package me.lucko.luckperms.bungee;
import me.lucko.luckperms.bungee.calculator.BungeeCalculatorFactory;
-import me.lucko.luckperms.bungee.context.BackendServerCalculator;
import me.lucko.luckperms.bungee.context.BungeeContextManager;
+import me.lucko.luckperms.bungee.context.BungeePlayerCalculator;
import me.lucko.luckperms.bungee.context.RedisBungeeCalculator;
import me.lucko.luckperms.bungee.listeners.BungeeConnectionListener;
import me.lucko.luckperms.bungee.listeners.BungeePermissionCheckListener;
@@ -140,9 +140,9 @@ public class LPBungeePlugin extends AbstractLuckPermsPlugin {
protected void setupContextManager() {
this.contextManager = new BungeeContextManager(this);
- BackendServerCalculator backendServerCalculator = new BackendServerCalculator(this);
- this.bootstrap.getProxy().getPluginManager().registerListener(this.bootstrap, backendServerCalculator);
- this.contextManager.registerCalculator(backendServerCalculator);
+ BungeePlayerCalculator playerCalculator = new BungeePlayerCalculator(this);
+ this.bootstrap.getProxy().getPluginManager().registerListener(this.bootstrap, playerCalculator);
+ this.contextManager.registerCalculator(playerCalculator);
if (this.bootstrap.getProxy().getPluginManager().getPlugin("RedisBungee") != null) {
this.contextManager.registerCalculator(new RedisBungeeCalculator());
diff --git a/bungee/src/main/java/me/lucko/luckperms/bungee/context/BackendServerCalculator.java b/bungee/src/main/java/me/lucko/luckperms/bungee/context/BungeePlayerCalculator.java
similarity index 73%
rename from bungee/src/main/java/me/lucko/luckperms/bungee/context/BackendServerCalculator.java
rename to bungee/src/main/java/me/lucko/luckperms/bungee/context/BungeePlayerCalculator.java
index 5331de953..7c12921bb 100644
--- a/bungee/src/main/java/me/lucko/luckperms/bungee/context/BackendServerCalculator.java
+++ b/bungee/src/main/java/me/lucko/luckperms/bungee/context/BungeePlayerCalculator.java
@@ -36,49 +36,39 @@ import net.luckperms.api.context.DefaultContextKeys;
import net.luckperms.api.context.ImmutableContextSet;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.api.connection.Server;
import net.md_5.bungee.api.event.ServerSwitchEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
+import net.md_5.bungee.event.EventPriority;
import org.checkerframework.checker.nullness.qual.NonNull;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
-public class BackendServerCalculator implements ContextCalculator, Listener {
-
- private static String getServer(ProxiedPlayer player) {
- return player.getServer() == null ? null : (player.getServer().getInfo() == null ? null : player.getServer().getInfo().getName().toLowerCase());
- }
-
+public class BungeePlayerCalculator implements ContextCalculator, Listener {
private final LPBungeePlugin plugin;
- public BackendServerCalculator(LPBungeePlugin plugin) {
+ public BungeePlayerCalculator(LPBungeePlugin plugin) {
this.plugin = plugin;
}
@Override
public void calculate(@NonNull ProxiedPlayer subject, @NonNull ContextConsumer consumer) {
- Set seen = new HashSet<>();
- String server = getServer(subject);
- while (server != null && seen.add(server)) {
- consumer.accept(DefaultContextKeys.WORLD_KEY, server);
- server = this.plugin.getConfiguration().get(ConfigKeys.WORLD_REWRITES).getOrDefault(server, server).toLowerCase();
+ Server server = subject.getServer();
+ if (server != null) {
+ this.plugin.getConfiguration().get(ConfigKeys.WORLD_REWRITES).rewriteAndSubmit(server.getInfo().getName(), consumer);
}
}
@Override
public ContextSet estimatePotentialContexts() {
- Collection servers = this.plugin.getBootstrap().getProxy().getServers().values();
ImmutableContextSet.Builder builder = new ImmutableContextSetImpl.BuilderImpl();
- for (ServerInfo server : servers) {
+ for (ServerInfo server : this.plugin.getBootstrap().getProxy().getServers().values()) {
builder.add(DefaultContextKeys.WORLD_KEY, server.getName().toLowerCase());
}
return builder.build();
}
- @EventHandler
+ @EventHandler(priority = EventPriority.LOWEST)
public void onServerSwitch(ServerSwitchEvent e) {
this.plugin.getContextManager().signalContextUpdate(e.getPlayer());
}
diff --git a/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java b/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java
index 07c2dbde0..e6625cfc9 100644
--- a/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java
+++ b/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java
@@ -33,6 +33,7 @@ import me.lucko.luckperms.common.cacheddata.type.SimpleMetaValueSelector;
import me.lucko.luckperms.common.config.generic.KeyedConfiguration;
import me.lucko.luckperms.common.config.generic.key.ConfigKey;
import me.lucko.luckperms.common.config.generic.key.SimpleConfigKey;
+import me.lucko.luckperms.common.context.WorldNameRewriter;
import me.lucko.luckperms.common.graph.TraversalAlgorithm;
import me.lucko.luckperms.common.metastacking.SimpleMetaStackDefinition;
import me.lucko.luckperms.common.metastacking.StandardStackElements;
@@ -475,12 +476,12 @@ public final class ConfigKeys {
/**
* The world rewrites map
*/
- public static final ConfigKey