aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCow <cow@volloeko.de>2020-04-28 12:44:09 +0200
committerCow <cow@volloeko.de>2020-04-28 12:44:09 +0200
commit38cd6cc98ba320e54754a270c889549b793b6b90 (patch)
treeafee59b68a33f9ca183fc48c9d58e5fdf0dda95b /src
parent35553dceb9c683000095ce1a62b4e094234304bc (diff)
downloadCowlection-38cd6cc98ba320e54754a270c889549b793b6b90.tar.gz
Cowlection-38cd6cc98ba320e54754a270c889549b793b6b90.tar.bz2
Cowlection-38cd6cc98ba320e54754a270c889549b793b6b90.zip
Added Tab-completable usernames for various commands
- use /tabcompletablecommand for a full list of valid commands (e.g. party, msg, boop, ...) - list of supported commands can be modified via config
Diffstat (limited to 'src')
-rw-r--r--src/main/java/eu/olli/cowmoonication/Cowmoonication.java11
-rw-r--r--src/main/java/eu/olli/cowmoonication/command/MooCommand.java4
-rw-r--r--src/main/java/eu/olli/cowmoonication/command/TabCompletableCommand.java81
-rw-r--r--src/main/java/eu/olli/cowmoonication/config/MooConfig.java25
-rw-r--r--src/main/java/eu/olli/cowmoonication/listener/ChatListener.java43
-rw-r--r--src/main/java/eu/olli/cowmoonication/listener/PlayerListener.java1
-rw-r--r--src/main/java/eu/olli/cowmoonication/util/PlayerCache.java46
-rw-r--r--src/main/resources/assets/cowmoonication/lang/en_US.lang2
8 files changed, 201 insertions, 12 deletions
diff --git a/src/main/java/eu/olli/cowmoonication/Cowmoonication.java b/src/main/java/eu/olli/cowmoonication/Cowmoonication.java
index 748883a..30ac662 100644
--- a/src/main/java/eu/olli/cowmoonication/Cowmoonication.java
+++ b/src/main/java/eu/olli/cowmoonication/Cowmoonication.java
@@ -2,11 +2,13 @@ package eu.olli.cowmoonication;
import eu.olli.cowmoonication.command.MooCommand;
import eu.olli.cowmoonication.command.ShrugCommand;
+import eu.olli.cowmoonication.command.TabCompletableCommand;
import eu.olli.cowmoonication.config.MooConfig;
import eu.olli.cowmoonication.friends.Friends;
import eu.olli.cowmoonication.listener.ChatListener;
import eu.olli.cowmoonication.listener.PlayerListener;
import eu.olli.cowmoonication.util.ChatHelper;
+import eu.olli.cowmoonication.util.PlayerCache;
import eu.olli.cowmoonication.util.VersionChecker;
import net.minecraftforge.client.ClientCommandHandler;
import net.minecraftforge.common.MinecraftForge;
@@ -33,6 +35,7 @@ public class Cowmoonication {
private Friends friends;
private VersionChecker versionChecker;
private ChatHelper chatHelper;
+ private PlayerCache playerCache;
private Logger logger;
@Mod.EventHandler
@@ -45,7 +48,7 @@ public class Cowmoonication {
}
friends = new Friends(this, new File(modDir, "friends.json"));
- config = new MooConfig(new Configuration(new File(modDir, MODID + ".cfg")));
+ config = new MooConfig(this, new Configuration(new File(modDir, MODID + ".cfg")));
chatHelper = new ChatHelper();
modsDir = e.getSourceFile().getParentFile();
@@ -57,11 +60,13 @@ public class Cowmoonication {
MinecraftForge.EVENT_BUS.register(new PlayerListener(this));
ClientCommandHandler.instance.registerCommand(new MooCommand(this));
ClientCommandHandler.instance.registerCommand(new ShrugCommand(this));
+ ClientCommandHandler.instance.registerCommand(new TabCompletableCommand(this));
}
@EventHandler
public void postInit(FMLPostInitializationEvent e) {
versionChecker = new VersionChecker(this);
+ playerCache = new PlayerCache(this);
}
public MooConfig getConfig() {
@@ -80,6 +85,10 @@ public class Cowmoonication {
return chatHelper;
}
+ public PlayerCache getPlayerCache() {
+ return playerCache;
+ }
+
public File getModsFolder() {
return modsDir;
}
diff --git a/src/main/java/eu/olli/cowmoonication/command/MooCommand.java b/src/main/java/eu/olli/cowmoonication/command/MooCommand.java
index 58d01a5..c1a8318 100644
--- a/src/main/java/eu/olli/cowmoonication/command/MooCommand.java
+++ b/src/main/java/eu/olli/cowmoonication/command/MooCommand.java
@@ -302,6 +302,10 @@ public class MooCommand extends CommandBase {
/* miscellaneous */ "config", "guiscale", "shrug", "apikey",
/* update mod */ "update", "updateHelp", "version", "folder",
/* help */ "help");
+ } else if (args.length == 2 && args[0].equalsIgnoreCase("remove")) {
+ return getListOfStringsMatchingLastWord(args, main.getFriends().getBestFriends());
+ } else if (args.length == 2 && args[0].equalsIgnoreCase("stalk")) {
+ return getListOfStringsMatchingLastWord(args, main.getPlayerCache().getAllNamesSorted());
}
return null;
}
diff --git a/src/main/java/eu/olli/cowmoonication/command/TabCompletableCommand.java b/src/main/java/eu/olli/cowmoonication/command/TabCompletableCommand.java
new file mode 100644
index 0000000..b1ffa33
--- /dev/null
+++ b/src/main/java/eu/olli/cowmoonication/command/TabCompletableCommand.java
@@ -0,0 +1,81 @@
+package eu.olli.cowmoonication.command;
+
+import com.mojang.realmsclient.util.Pair;
+import eu.olli.cowmoonication.Cowmoonication;
+import eu.olli.cowmoonication.config.MooConfig;
+import net.minecraft.client.Minecraft;
+import net.minecraft.command.CommandBase;
+import net.minecraft.command.CommandException;
+import net.minecraft.command.ICommandSender;
+import net.minecraft.util.BlockPos;
+import net.minecraft.util.EnumChatFormatting;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class TabCompletableCommand extends CommandBase {
+ private final Cowmoonication main;
+
+ public TabCompletableCommand(Cowmoonication main) {
+ this.main = main;
+ }
+
+ @Override
+ public String getCommandName() {
+ return "tabcompletablecommand";
+ }
+
+ @Override
+ public String getCommandUsage(ICommandSender sender) {
+ return EnumChatFormatting.YELLOW + "Commands where player names can be Tab-completed: " + EnumChatFormatting.GOLD + StringUtils.join(getCommandAliases(), EnumChatFormatting.YELLOW + ", " + EnumChatFormatting.GOLD)
+ + EnumChatFormatting.YELLOW + ". Use " + EnumChatFormatting.GOLD + "/moo config " + EnumChatFormatting.YELLOW + " to edit the list of commands with tab-completable usernames.";
+ }
+
+ @Override
+ public void processCommand(ICommandSender sender, String[] args) throws CommandException {
+ Pair<String, String> lastCommand = getLastCommand();
+ if (lastCommand == null) {
+ main.getChatHelper().sendMessage(EnumChatFormatting.RED, "Something went wrong trying to process this command.");
+ } else if (lastCommand.first().equalsIgnoreCase(getCommandName())) {
+ main.getChatHelper().sendMessage(EnumChatFormatting.YELLOW, getCommandUsage(sender));
+ } else {
+ Minecraft.getMinecraft().thePlayer.sendChatMessage(lastCommand.second());
+ }
+ }
+
+ /**
+ * Work-around to get last used command name or alias (by default it's impossible to detect the used alias)
+ *
+ * @return 1st: last command used by thePlayer, 2nd: (full) last message sent thePlayer; or null if no command was sent as the last message
+ */
+ private Pair<String, String> getLastCommand() {
+ List<String> sentMessages = Minecraft.getMinecraft().ingameGUI.getChatGUI().getSentMessages();
+ String lastMessage = sentMessages.get(sentMessages.size() - 1);
+ if (lastMessage.startsWith("/")) {
+ int endOfCommandName = lastMessage.indexOf(" ");
+ return Pair.of(lastMessage.substring(1, endOfCommandName == -1 ? lastMessage.length() : endOfCommandName),
+ lastMessage);
+ }
+ return null;
+ }
+
+ @Override
+ public int getRequiredPermissionLevel() {
+ return 0;
+ }
+
+ @Override
+ public List<String> getCommandAliases() {
+ // list of commands that require a player name as one their 1st or 2nd argument
+ return Arrays.asList(MooConfig.tabCompletableNamesCommands);
+ }
+
+ @Override
+ public List<String> addTabCompletionOptions(ICommandSender sender, String[] args, BlockPos pos) {
+ if (args.length == 1 || args.length == 2) {
+ return getListOfStringsMatchingLastWord(args, main.getPlayerCache().getAllNamesSorted());
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/eu/olli/cowmoonication/config/MooConfig.java b/src/main/java/eu/olli/cowmoonication/config/MooConfig.java
index 41cec89..cb852a7 100644
--- a/src/main/java/eu/olli/cowmoonication/config/MooConfig.java
+++ b/src/main/java/eu/olli/cowmoonication/config/MooConfig.java
@@ -2,6 +2,8 @@ package eu.olli.cowmoonication.config;
import eu.olli.cowmoonication.Cowmoonication;
import eu.olli.cowmoonication.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.util.EnumChatFormatting;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property;
@@ -10,18 +12,23 @@ import net.minecraftforge.fml.common.eventhandler.EventPriority;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import java.util.regex.Pattern;
public class MooConfig {
public static boolean doUpdateCheck;
public static boolean showBestFriendNotifications;
public static boolean showFriendNotifications;
public static boolean showGuildNotifications;
+ public static String[] tabCompletableNamesCommands;
public static String moo;
private static Configuration cfg = null;
+ private final Cowmoonication main;
private List<String> propOrderGeneral;
- public MooConfig(Configuration configuration) {
+ public MooConfig(Cowmoonication main, Configuration configuration) {
+ this.main = main;
cfg = configuration;
initConfig();
}
@@ -79,26 +86,42 @@ public class MooConfig {
"showFriendNotifications", false, "Set to true to receive friends' login/logout messages, set to false hide them."), true);
Property propShowGuildNotifications = addConfigEntry(cfg.get(Configuration.CATEGORY_CLIENT,
"showGuildNotifications", false, "Set to true to receive guild members' login/logout messages, set to false hide them."), true);
+ Property propTabCompletableNamesCommands = addConfigEntry(cfg.get(Configuration.CATEGORY_CLIENT,
+ "tabCompletableNamesCommands", new String[]{"party", "p", "invite", "visit", "ignore", "msg", "tell", "w", "boop", "profile"}, "List of commands with a Tab-completable username argument."), true)
+ .setValidationPattern(Pattern.compile("^[A-Za-z]+$"));
Property propMoo = addConfigEntry(cfg.get(Configuration.CATEGORY_CLIENT,
"moo", "", "The answer to life the universe and everything. Don't edit this entry manually!", Utils.VALID_UUID_PATTERN), false);
cfg.setCategoryPropertyOrder(Configuration.CATEGORY_CLIENT, propOrderGeneral);
+ // 'manual' replacement for propTabCompletableNamesCommands.hasChanged()
+ boolean modifiedTabCompletableCommandsList = false;
+ String[] tabCompletableCommandsPreChange = tabCompletableNamesCommands != null ? tabCompletableNamesCommands.clone() : null;
+
if (readFieldsFromConfig) {
doUpdateCheck = propDoUpdateCheck.getBoolean();
showBestFriendNotifications = propShowBestFriendNotifications.getBoolean();
showFriendNotifications = propShowFriendNotifications.getBoolean();
showGuildNotifications = propShowGuildNotifications.getBoolean();
+ tabCompletableNamesCommands = propTabCompletableNamesCommands.getStringList();
moo = propMoo.getString();
+
+ if (!Arrays.equals(tabCompletableCommandsPreChange, tabCompletableNamesCommands)) {
+ modifiedTabCompletableCommandsList = true;
+ }
}
propDoUpdateCheck.set(doUpdateCheck);
propShowBestFriendNotifications.set(showBestFriendNotifications);
propShowFriendNotifications.set(showFriendNotifications);
propShowGuildNotifications.set(showGuildNotifications);
+ propTabCompletableNamesCommands.set(tabCompletableNamesCommands);
propMoo.set(moo);
if (cfg.hasChanged()) {
+ if (modifiedTabCompletableCommandsList && Minecraft.getMinecraft().thePlayer != null) {
+ main.getChatHelper().sendMessage(EnumChatFormatting.RED, "Added or removed commands with tab-completable usernames take effect after a game restart!");
+ }
cfg.save();
}
}
diff --git a/src/main/java/eu/olli/cowmoonication/listener/ChatListener.java b/src/main/java/eu/olli/cowmoonication/listener/ChatListener.java
index cf0f794..3c8847b 100644
--- a/src/main/java/eu/olli/cowmoonication/listener/ChatListener.java
+++ b/src/main/java/eu/olli/cowmoonication/listener/ChatListener.java
@@ -28,7 +28,8 @@ public class ChatListener {
* - §aFriend > §r§aNAME §r§eleft.§r
* - §2Guild > §r§aNAME §r§eleft.§r
*/
- private static final Pattern LOGIN_LOGOUT_NOTIFICATION = Pattern.compile("^(?<type>§aFriend|§2Guild) > §r(?<rank>§[0-9a-f])(?<playerName>[\\w]+)(?<joinLeave> §r§e(?:joined|left)\\.)§r$");
+ private static final Pattern LOGIN_LOGOUT_NOTIFICATION = Pattern.compile("^(?<type>§aFriend|§2Guild) > §r(?<rank>§[0-9a-f])(?<playerName>[\\w]+)(?<joinLeaveSuffix> §r§e(?<joinedLeft>joined|left)\\.)§r$");
+ private static final Pattern CHAT_MESSAGE_RECEIVED_PATTERN = Pattern.compile("^(?:Party|Guild) > (?:\\[.*?] )?(?<playerName>\\w+)(?: \\[.*?])?: ");
private static final Pattern PRIVATE_MESSAGE_RECEIVED_PATTERN = Pattern.compile("^From (?:\\[.*?] )?(\\w+): ");
private final Cowmoonication main;
private String lastTypedChars = "";
@@ -51,13 +52,23 @@ public class ChatListener {
String type = notificationMatcher.group("type");
String rank = notificationMatcher.group("rank");
String playerName = notificationMatcher.group("playerName");
- String joinLeave = notificationMatcher.group("joinLeave");
+ String joinLeaveSuffix = notificationMatcher.group("joinLeaveSuffix");
+ String joinedLeft = notificationMatcher.group("joinedLeft");
- if (MooConfig.showBestFriendNotifications) {
- boolean isBestFriend = main.getFriends().isBestFriend(playerName, false);
- if (isBestFriend) {
+
+ boolean isBestFriend = main.getFriends().isBestFriend(playerName, false);
+ if (isBestFriend) {
+ switch (joinedLeft) {
+ case "joined":
+ main.getPlayerCache().addBestFriend(playerName);
+ break;
+ case "left":
+ main.getPlayerCache().removeBestFriend(playerName);
+ break;
+ }
+ if (MooConfig.showBestFriendNotifications) {
// replace default (friend/guild) notification with best friend notification
- main.getChatHelper().sendMessage(EnumChatFormatting.YELLOW, "" + EnumChatFormatting.DARK_GREEN + EnumChatFormatting.BOLD + "Best friend" + EnumChatFormatting.DARK_GREEN + " > " + EnumChatFormatting.RESET + rank + playerName + joinLeave);
+ main.getChatHelper().sendMessage(EnumChatFormatting.YELLOW, "" + EnumChatFormatting.DARK_GREEN + EnumChatFormatting.BOLD + "Best friend" + EnumChatFormatting.DARK_GREEN + " > " + EnumChatFormatting.RESET + rank + playerName + joinLeaveSuffix);
e.setCanceled(true);
return;
}
@@ -125,11 +136,23 @@ public class ChatListener {
}
@SubscribeEvent
- public void onPrivateMsgReceive(ClientChatReceivedEvent e) {
+ public void onChatMsgReceive(ClientChatReceivedEvent e) {
if (e.type != 2) {
- Matcher matcher = PRIVATE_MESSAGE_RECEIVED_PATTERN.matcher(e.message.getUnformattedText());
- if (matcher.find()) {
- this.lastPMSender = matcher.group(1);
+ String messageSender = null;
+
+ String message = EnumChatFormatting.getTextWithoutFormattingCodes(e.message.getUnformattedText());
+
+ Matcher privateMessageMatcher = PRIVATE_MESSAGE_RECEIVED_PATTERN.matcher(message);
+ Matcher chatMessageMatcher = CHAT_MESSAGE_RECEIVED_PATTERN.matcher(message);
+ if (privateMessageMatcher.find()) {
+ messageSender = privateMessageMatcher.group(1);
+ this.lastPMSender = messageSender;
+ } else if (chatMessageMatcher.find()) {
+ messageSender = chatMessageMatcher.group("playerName");
+ }
+
+ if (messageSender != null) {
+ main.getPlayerCache().add(messageSender);
}
}
}
diff --git a/src/main/java/eu/olli/cowmoonication/listener/PlayerListener.java b/src/main/java/eu/olli/cowmoonication/listener/PlayerListener.java
index 304806d..95c35c6 100644
--- a/src/main/java/eu/olli/cowmoonication/listener/PlayerListener.java
+++ b/src/main/java/eu/olli/cowmoonication/listener/PlayerListener.java
@@ -21,5 +21,6 @@ public class PlayerListener {
@SubscribeEvent
public void onServerLeave(FMLNetworkEvent.ClientDisconnectionFromServerEvent e) {
main.getFriends().saveBestFriends();
+ main.getPlayerCache().clearAllCaches();
}
}
diff --git a/src/main/java/eu/olli/cowmoonication/util/PlayerCache.java b/src/main/java/eu/olli/cowmoonication/util/PlayerCache.java
new file mode 100644
index 0000000..1b5251a
--- /dev/null
+++ b/src/main/java/eu/olli/cowmoonication/util/PlayerCache.java
@@ -0,0 +1,46 @@
+package eu.olli.cowmoonication.util;
+
+import com.google.common.collect.EvictingQueue;
+import eu.olli.cowmoonication.Cowmoonication;
+
+import java.util.Set;
+import java.util.TreeSet;
+
+public class PlayerCache {
+ @SuppressWarnings("UnstableApiUsage")
+ private final EvictingQueue<String> nameCache = EvictingQueue.create(50);
+ @SuppressWarnings("UnstableApiUsage")
+ private final EvictingQueue<String> bestFriendCache = EvictingQueue.create(50);
+ private final Cowmoonication main;
+
+ public PlayerCache(Cowmoonication main) {
+ this.main = main;
+ }
+
+ public void add(String name) {
+ // remove old entry (if exists) to 'push' name to the end of the queue
+ nameCache.remove(name);
+ nameCache.add(name);
+ }
+
+ public void addBestFriend(String name) {
+ // remove old entry (if exists) to 'push' name to the end of the queue
+ bestFriendCache.remove(name);
+ bestFriendCache.add(name);
+ }
+
+ public void removeBestFriend(String name) {
+ bestFriendCache.remove(name);
+ }
+
+ public Set<String> getAllNamesSorted() {
+ Set<String> nameList = new TreeSet<>(bestFriendCache);
+ nameList.addAll(nameCache);
+ return nameList;
+ }
+
+ public void clearAllCaches() {
+ nameCache.clear();
+ bestFriendCache.clear();
+ }
+}
diff --git a/src/main/resources/assets/cowmoonication/lang/en_US.lang b/src/main/resources/assets/cowmoonication/lang/en_US.lang
index ad103b6..05cfc43 100644
--- a/src/main/resources/assets/cowmoonication/lang/en_US.lang
+++ b/src/main/resources/assets/cowmoonication/lang/en_US.lang
@@ -6,3 +6,5 @@ cowmoonication.config.showFriendNotifications=Show friend notifications
cowmoonication.config.showFriendNotifications.tooltip=Set to true to receive friends' login/logout messages, set to false hide them.
cowmoonication.config.showGuildNotifications=Show guild notifications
cowmoonication.config.showGuildNotifications.tooltip=Set to true to receive guild members' login/logout messages, set to false hide them.
+cowmoonication.config.tabCompletableNamesCommands=Commands with Tab-completable usernames
+cowmoonication.config.tabCompletableNamesCommands.tooltip=List of commands with a username argument that should be Tab-completable.\nRequires game restart to take effect!