001/* 002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License 003 * 004 * Permission is hereby granted, free of charge, to any person obtaining 005 * a copy of this software and associated documentation files (the 006 * "Software"), to deal in the Software without restriction, including 007 * without limitation the rights to use, copy, modify, merge, publish, 008 * distribute, sublicense, and/or sell copies of the Software, and to 009 * permit persons to whom the Software is furnished to do so, subject to 010 * the following conditions: 011 * 012 * The above copyright notice and this permission notice shall be 013 * included in all copies or substantial portions of the Software. 014 * 015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 016 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 017 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 018 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 019 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 020 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 021 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 022 */ 023 024package co.aikar.commands; 025 026import net.md_5.bungee.api.ChatColor; 027import net.md_5.bungee.api.CommandSender; 028import net.md_5.bungee.api.ProxyServer; 029import net.md_5.bungee.api.connection.ProxiedPlayer; 030 031import java.util.ArrayList; 032import java.util.List; 033import java.util.regex.Pattern; 034import java.util.stream.Collectors; 035 036public class ACFBungeeUtil { 037 038 public static String color(String message) { 039 return ChatColor.translateAlternateColorCodes('&', message); 040 } 041 042 /** 043 * Move to Message Keys on the CommandIssuer 044 * 045 * @deprecated 046 */ 047 @Deprecated 048 public static void sendMsg(CommandSender player, String message) { 049 message = color(message); 050 for (String msg : ACFPatterns.NEWLINE.split(message)) { 051 player.sendMessage(msg); 052 } 053 } 054 055 public static String removeColors(String msg) { 056 return ChatColor.stripColor(color(msg)); 057 } 058 059 public static String replaceChatString(String message, String replace, String with) { 060 return replaceChatString(message, Pattern.compile(Pattern.quote(replace), Pattern.CASE_INSENSITIVE), with); 061 } 062 063 public static String replaceChatString(String message, Pattern replace, String with) { 064 final String[] split = replace.split(message + "1"); 065 066 if (split.length < 2) { 067 return replace.matcher(message).replaceAll(with); 068 } 069 message = split[0]; 070 071 for (int i = 1; i < split.length; i++) { 072 final String prev = getLastColors(message); 073 message += with + prev + split[i]; 074 } 075 return message.substring(0, message.length() - 1); 076 } 077 078 //Imported from org.bukkit.ChatColor 079 080 public static final char COLOR_CHAR = '\u00A7'; 081 082 public static String getLastColors(String input) { 083 StringBuilder result = new StringBuilder(); 084 int length = input.length(); 085 086 // Search backwards from the end as it is faster 087 for (int index = length - 1; index > -1; index--) { 088 char section = input.charAt(index); 089 if (section == COLOR_CHAR && index < length - 1) { 090 char c = input.charAt(index + 1); 091 ChatColor color = ChatColor.getByChar(c); 092 093 if (color != null) { 094 result.insert(0, color.toString()); 095 096 // Once we find a color or reset we can stop searching 097 if (isChatColorAColor(color) || color.equals(ChatColor.RESET)) { 098 break; 099 } 100 } 101 } 102 } 103 return result.toString(); 104 } 105 106 public static boolean isChatColorAColor(ChatColor chatColor) { 107 return chatColor != ChatColor.MAGIC && chatColor != ChatColor.BOLD 108 && chatColor != ChatColor.STRIKETHROUGH && chatColor != ChatColor.UNDERLINE 109 && chatColor != ChatColor.ITALIC; 110 } 111 112 113 public static ProxiedPlayer findPlayerSmart(CommandIssuer issuer, String search) { 114 CommandSender requester = issuer.getIssuer(); 115 String name = ACFUtil.replace(search, ":confirm", ""); 116 if (!isValidName(name)) { 117 issuer.sendError(MinecraftMessageKeys.IS_NOT_A_VALID_NAME, "{name}", name); 118 return null; 119 } 120 121 List<ProxiedPlayer> matches = new ArrayList<>(ProxyServer.getInstance().matchPlayer(name)); 122 123 if (matches.size() > 1) { 124 String allMatches = matches.stream().map(ProxiedPlayer::getName).collect(Collectors.joining(", ")); 125 issuer.sendError(MinecraftMessageKeys.MULTIPLE_PLAYERS_MATCH, 126 "{search}", name, "{all}", allMatches); 127 return null; 128 } 129 130 if (matches.isEmpty()) { 131 issuer.sendError(MinecraftMessageKeys.NO_PLAYER_FOUND_SERVER, 132 "{search}", name); 133 return null; 134 } 135 136 return matches.get(0); 137 } 138 139 /** 140 * Please move to the CommandIssuer version 141 * 142 * @deprecated 143 */ 144 public static ProxiedPlayer findPlayerSmart(CommandSender requester, String search) { 145 CommandManager manager = CommandManager.getCurrentCommandManager(); 146 if (manager != null) { 147 return findPlayerSmart(manager.getCommandIssuer(requester), search); 148 } 149 throw new IllegalStateException("You may not use the ACFBungeeUtil#findPlayerSmart(CommandSender) async to the command execution."); 150 } 151 152 public static boolean isValidName(String name) { 153 return name != null && !name.isEmpty() && ACFPatterns.VALID_NAME_PATTERN.matcher(name).matches(); 154 } 155 156 public static <T> T validate(T object, String message, Object... values) { 157 if (object == null) { 158 throw new NullPointerException(String.format(message, values)); 159 } 160 return object; 161 } 162 163 164}