mirror of
https://github.com/aikar/commands.git
synced 2026-05-31 06:11:55 +00:00
Add support for per issuer locale in Sponge and BungeeCord (#104)
* Add support for per issuer locale in Sponge and BungeeCord * Added Optional<UUID> getUniqueId to CommandIssuer * Added update task and delayed join listener in BungeeCord * Added settings change listener in Sponge * Moved setLocale method up to the CommandManager to remove the amount of duplicated code * Remove Optional usage * Remove player terminology in core
This commit is contained in:
@@ -54,13 +54,14 @@ class ACFBukkitListener implements Listener {
|
||||
this.manager.readPlayerLocale(player);
|
||||
this.plugin.getServer().getScheduler().runTaskLater(this.plugin, () -> manager.readPlayerLocale(player), 20);
|
||||
} else {
|
||||
this.manager.setPlayerLocale(player, this.manager.getLocales().getDefaultLocale());
|
||||
this.manager.setIssuerLocale(player, this.manager.getLocales().getDefaultLocale());
|
||||
this.manager.notifyLocaleChange(this.manager.getCommandIssuer(player), null, this.manager.getLocales().getDefaultLocale());
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerQuitEvent event) {
|
||||
manager.issuersLocale.remove(event.getPlayer().getUniqueId());
|
||||
public void onPlayerQuit(PlayerQuitEvent quitEvent) {
|
||||
//cleanup
|
||||
manager.issuersLocale.remove(quitEvent.getPlayer().getUniqueId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,8 +25,11 @@ package co.aikar.commands;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public class BukkitCommandIssuer implements CommandIssuer {
|
||||
private final BukkitCommandManager manager;
|
||||
@@ -52,6 +55,16 @@ public class BukkitCommandIssuer implements CommandIssuer {
|
||||
return isPlayer() ? (Player) sender : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull UUID getUniqueId() {
|
||||
if (isPlayer()) {
|
||||
return ((Player) sender).getUniqueId();
|
||||
}
|
||||
|
||||
//generate a unique id based of the name (like for the console command sender)
|
||||
return UUID.nameUUIDFromBytes(sender.getName().getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandManager getManager() {
|
||||
return manager;
|
||||
|
||||
@@ -26,7 +26,6 @@ package co.aikar.commands;
|
||||
import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil;
|
||||
import co.aikar.timings.lib.MCTiming;
|
||||
import co.aikar.timings.lib.TimingManager;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Server;
|
||||
@@ -52,7 +51,6 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -80,7 +78,6 @@ public class BukkitCommandManager extends CommandManager<
|
||||
protected BukkitLocales locales;
|
||||
private boolean cantReadLocale = false;
|
||||
protected boolean autoDetectFromClient = true;
|
||||
protected Map<UUID, Locale> issuersLocale = Maps.newConcurrentMap();
|
||||
|
||||
@SuppressWarnings("JavaReflectionMemberAccess")
|
||||
public BukkitCommandManager(Plugin plugin) {
|
||||
@@ -93,7 +90,9 @@ public class BukkitCommandManager extends CommandManager<
|
||||
this.formatters.put(MessageType.SYNTAX, new BukkitMessageFormatter(ChatColor.YELLOW, ChatColor.GREEN, ChatColor.WHITE));
|
||||
this.formatters.put(MessageType.INFO, new BukkitMessageFormatter(ChatColor.BLUE, ChatColor.DARK_GREEN, ChatColor.GREEN));
|
||||
this.formatters.put(MessageType.HELP, new BukkitMessageFormatter(ChatColor.AQUA, ChatColor.GREEN, ChatColor.YELLOW));
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(new ACFBukkitListener(this, plugin), plugin);
|
||||
|
||||
getLocales(); // auto load locales
|
||||
this.localeTask = Bukkit.getScheduler().runTaskTimer(plugin, () -> {
|
||||
if (this.cantReadLocale || !this.autoDetectFromClient) {
|
||||
@@ -341,26 +340,6 @@ public class BukkitCommandManager extends CommandManager<
|
||||
}
|
||||
}
|
||||
|
||||
public Locale setPlayerLocale(Player player, Locale locale) {
|
||||
Locale old = this.issuersLocale.put(player.getUniqueId(), locale);
|
||||
if (!Objects.equals(old, locale)) {
|
||||
this.notifyLocaleChange(getCommandIssuer(player), old, locale);
|
||||
}
|
||||
return old;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale getIssuerLocale(CommandIssuer issuer) {
|
||||
if (usingPerIssuerLocale() && issuer.getIssuer() instanceof Player) {
|
||||
UUID uniqueId = ((Player) issuer.getIssuer()).getUniqueId();
|
||||
Locale locale = issuersLocale.get(uniqueId);
|
||||
if (locale != null) {
|
||||
return locale;
|
||||
}
|
||||
}
|
||||
return super.getIssuerLocale(issuer);
|
||||
}
|
||||
|
||||
public boolean usePerIssuerLocale(boolean usePerIssuerLocale, boolean autoDetectFromClient) {
|
||||
boolean old = this.usePerIssuerLocale;
|
||||
this.usePerIssuerLocale = usePerIssuerLocale;
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package co.aikar.commands;
|
||||
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
|
||||
import net.md_5.bungee.api.event.PostLoginEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ACFBungeeListener implements Listener {
|
||||
|
||||
private final BungeeCommandManager manager;
|
||||
private final Plugin plugin;
|
||||
|
||||
public ACFBungeeListener(BungeeCommandManager manager, Plugin plugin) {
|
||||
this.manager = manager;
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PostLoginEvent loginEvent) {
|
||||
ProxiedPlayer player = loginEvent.getPlayer();
|
||||
|
||||
//the client settings are sent after a successful login
|
||||
Runnable task = () -> manager.readLocale(player);
|
||||
plugin.getProxy().getScheduler().schedule(plugin, task, 1, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDisconnect(PlayerDisconnectEvent disconnectEvent) {
|
||||
//cleanup
|
||||
ProxiedPlayer player = disconnectEvent.getPlayer();
|
||||
manager.issuersLocale.remove(player.getUniqueId());
|
||||
}
|
||||
}
|
||||
@@ -25,8 +25,11 @@ package co.aikar.commands;
|
||||
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public class BungeeCommandIssuer implements CommandIssuer {
|
||||
private final BungeeCommandManager manager;
|
||||
@@ -57,6 +60,16 @@ public class BungeeCommandIssuer implements CommandIssuer {
|
||||
return sender instanceof ProxiedPlayer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull UUID getUniqueId() {
|
||||
if (isPlayer()) {
|
||||
return ((ProxiedPlayer) sender).getUniqueId();
|
||||
}
|
||||
|
||||
//generate a unique id based of the name (like for the console command sender)
|
||||
return UUID.nameUUIDFromBytes(sender.getName().getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessageInternal(String message) {
|
||||
sender.sendMessage(ACFBungeeUtil.color(message));
|
||||
|
||||
@@ -26,13 +26,17 @@ package co.aikar.commands;
|
||||
import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -57,8 +61,16 @@ public class BungeeCommandManager extends CommandManager<
|
||||
this.formatters.put(MessageType.SYNTAX, new BungeeMessageFormatter(ChatColor.YELLOW, ChatColor.GREEN, ChatColor.WHITE));
|
||||
this.formatters.put(MessageType.INFO, new BungeeMessageFormatter(ChatColor.BLUE, ChatColor.DARK_GREEN, ChatColor.GREEN));
|
||||
this.formatters.put(MessageType.HELP, new BungeeMessageFormatter(ChatColor.AQUA, ChatColor.GREEN, ChatColor.YELLOW));
|
||||
|
||||
getLocales(); // auto load locales
|
||||
|
||||
plugin.getProxy().getPluginManager().registerListener(plugin, new ACFBungeeListener(this, plugin));
|
||||
|
||||
//BungeeCord has no event for listening for client setting changes
|
||||
plugin.getProxy().getScheduler().schedule(plugin, () -> {
|
||||
ProxyServer.getInstance().getPlayers().forEach(this::readLocale);
|
||||
}, 5, 5, TimeUnit.SECONDS);
|
||||
|
||||
// TODO more default dependencies for bungee
|
||||
registerDependency(plugin.getClass(), plugin);
|
||||
registerDependency(Plugin.class, plugin);
|
||||
@@ -93,6 +105,17 @@ public class BungeeCommandManager extends CommandManager<
|
||||
return locales;
|
||||
}
|
||||
|
||||
public void readLocale(ProxiedPlayer player) {
|
||||
if (!player.isConnected()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//This can be null if we didn't received a settings packet
|
||||
Locale locale = player.getLocale();
|
||||
if (locale != null) {
|
||||
setIssuerLocale(player, player.getLocale());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerCommand(BaseCommand command) {
|
||||
|
||||
@@ -25,6 +25,9 @@ package co.aikar.commands;
|
||||
|
||||
import co.aikar.locales.MessageKey;
|
||||
import co.aikar.locales.MessageKeyProvider;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface CommandIssuer {
|
||||
/**
|
||||
@@ -50,6 +53,11 @@ public interface CommandIssuer {
|
||||
getManager().sendMessage(this, MessageType.INFO, MessageKeys.INFO_MESSAGE, "{message}", message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the unique id of that issuer
|
||||
*/
|
||||
@NotNull UUID getUniqueId();
|
||||
|
||||
/**
|
||||
* Has permission node
|
||||
* @param permission
|
||||
|
||||
@@ -27,6 +27,7 @@ import co.aikar.commands.annotation.Dependency;
|
||||
import co.aikar.locales.MessageKeyProvider;
|
||||
import com.google.common.collect.HashBasedTable;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.Table;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -35,14 +36,16 @@ import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public abstract class CommandManager <
|
||||
@@ -76,6 +79,8 @@ public abstract class CommandManager <
|
||||
protected MF defaultFormatter;
|
||||
protected int defaultHelpPerPage = 10;
|
||||
|
||||
protected Map<UUID, Locale> issuersLocale = Maps.newConcurrentMap();
|
||||
|
||||
private Set<String> unstableAPIs = Sets.newHashSet();
|
||||
|
||||
public static CommandOperationContext getCurrentCommandOperationContext() {
|
||||
@@ -344,7 +349,25 @@ public abstract class CommandManager <
|
||||
});
|
||||
}
|
||||
|
||||
public Locale setIssuerLocale(IT issuer, Locale locale) {
|
||||
I commandIssuer = getCommandIssuer(issuer);
|
||||
|
||||
Locale old = issuersLocale.put(commandIssuer.getUniqueId(), locale);
|
||||
if (!Objects.equals(old, locale)) {
|
||||
this.notifyLocaleChange(commandIssuer, old, locale);
|
||||
}
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
public Locale getIssuerLocale(CommandIssuer issuer) {
|
||||
if (usingPerIssuerLocale()) {
|
||||
Locale locale = issuersLocale.get(issuer.getUniqueId());
|
||||
if (locale != null) {
|
||||
return locale;
|
||||
}
|
||||
}
|
||||
|
||||
return getLocales().getDefaultLocale();
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,9 @@ package co.aikar.commands;
|
||||
import net.dv8tion.jda.core.entities.Message;
|
||||
import net.dv8tion.jda.core.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.core.events.message.MessageReceivedEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class JDACommandEvent implements CommandIssuer {
|
||||
|
||||
@@ -34,6 +37,14 @@ public class JDACommandEvent implements CommandIssuer {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull UUID getUniqueId() {
|
||||
// Discord id only have 64 bit width (long) while UUIDs have twice the size.
|
||||
// In order to keep it unique we use 0L for the first 64 bit.
|
||||
long authorId = event.getAuthor().getIdLong();
|
||||
return new UUID(0, authorId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
CommandPermissionResolver permissionResolver = this.manager.getPermissionResolver();
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package co.aikar.commands;
|
||||
|
||||
import org.spongepowered.api.entity.living.player.Player;
|
||||
import org.spongepowered.api.event.Listener;
|
||||
import org.spongepowered.api.event.Order;
|
||||
import org.spongepowered.api.event.entity.living.humanoid.player.PlayerChangeClientSettingsEvent;
|
||||
import org.spongepowered.api.event.filter.cause.First;
|
||||
import org.spongepowered.api.event.network.ClientConnectionEvent;
|
||||
|
||||
public class ACFSpongeListener {
|
||||
|
||||
private final SpongeCommandManager manager;
|
||||
|
||||
public ACFSpongeListener(SpongeCommandManager manager) {
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Listener(order = Order.POST)
|
||||
public void onSettingsChange(PlayerChangeClientSettingsEvent changeSettingsEvent, @First Player targetPlayer) {
|
||||
//this event will be fired on join as well as every time the player changes it
|
||||
manager.setIssuerLocale(targetPlayer, targetPlayer.getLocale());
|
||||
}
|
||||
|
||||
@Listener
|
||||
public void onDisconnectCleanup(ClientConnectionEvent.Disconnect disconnectEvent, @First Player player) {
|
||||
manager.issuersLocale.remove(player.getUniqueId());
|
||||
}
|
||||
}
|
||||
@@ -23,11 +23,15 @@
|
||||
|
||||
package co.aikar.commands;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.spongepowered.api.command.CommandSource;
|
||||
import org.spongepowered.api.entity.living.player.Player;
|
||||
import org.spongepowered.api.text.serializer.TextSerializers;
|
||||
import org.spongepowered.api.util.Identifiable;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public class SpongeCommandIssuer implements CommandIssuer {
|
||||
|
||||
@@ -49,6 +53,16 @@ public class SpongeCommandIssuer implements CommandIssuer {
|
||||
return this.source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull UUID getUniqueId() {
|
||||
if (isPlayer()) {
|
||||
return ((Identifiable) source).getUniqueId();
|
||||
}
|
||||
|
||||
//generate a unique id based of the name (like for the console command sender)
|
||||
return UUID.nameUUIDFromBytes(source.getName().getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return isPlayer() ? (Player) source : null;
|
||||
}
|
||||
@@ -68,7 +82,6 @@ public class SpongeCommandIssuer implements CommandIssuer {
|
||||
return this.source.hasPermission(permission);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
||||
@@ -68,6 +68,8 @@ public class SpongeCommandManager extends CommandManager<
|
||||
this.formatters.put(MessageType.HELP, new SpongeMessageFormatter(TextColors.AQUA, TextColors.GREEN, TextColors.YELLOW));
|
||||
getLocales(); // auto load locales
|
||||
|
||||
Sponge.getEventManager().registerListeners(plugin, new ACFSpongeListener(this));
|
||||
|
||||
//TODO more default dependencies for sponge
|
||||
registerDependency(plugin.getClass(), plugin);
|
||||
}
|
||||
@@ -196,5 +198,4 @@ public class SpongeCommandManager extends CommandManager<
|
||||
public SpongeConditionContext createConditionContext(CommandIssuer issuer, String config) {
|
||||
return new SpongeConditionContext((SpongeCommandIssuer) issuer, config);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user