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 * @deprecated 045 */ 046 @Deprecated 047 public static void sendMsg(CommandSender player, String message) { 048 message = color(message); 049 for (String msg : ACFPatterns.NEWLINE.split(message)) { 050 player.sendMessage(msg); 051 } 052 } 053 054 public static String removeColors(String msg) { 055 return ChatColor.stripColor(color(msg)); 056 } 057 058 public static String replaceChatString(String message, String replace, String with) { 059 return replaceChatString(message, Pattern.compile(Pattern.quote(replace), Pattern.CASE_INSENSITIVE), with); 060 } 061 062 public static String replaceChatString(String message, Pattern replace, String with) { 063 final String[] split = replace.split(message + "1"); 064 065 if (split.length < 2) { 066 return replace.matcher(message).replaceAll(with); 067 } 068 message = split[0]; 069 070 for (int i = 1; i < split.length; i++) { 071 final String prev = getLastColors(message); 072 message += with + prev + split[i]; 073 } 074 return message.substring(0, message.length() - 1); 075 } 076 077 //Imported from org.bukkit.ChatColor 078 079 public static final char COLOR_CHAR = '\u00A7'; 080 081 public static String getLastColors(String input) { 082 String result = ""; 083 int length = input.length(); 084 085 // Search backwards from the end as it is faster 086 for (int index = length - 1; index > -1; index--) { 087 char section = input.charAt(index); 088 if (section == COLOR_CHAR && index < length - 1) { 089 char c = input.charAt(index + 1); 090 ChatColor color = ChatColor.getByChar(c); 091 092 if (color != null) { 093 result = color.toString() + result; 094 095 // Once we find a color or reset we can stop searching 096 if (isChatColorAColor(color) || color.equals(ChatColor.RESET)) { 097 break; 098 } 099 } 100 } 101 } 102 return result; 103 } 104 105 public static boolean isChatColorAColor(ChatColor chatColor) { 106 return chatColor != ChatColor.MAGIC && chatColor != ChatColor.BOLD 107 && chatColor != ChatColor.STRIKETHROUGH && chatColor != ChatColor.UNDERLINE 108 && chatColor != ChatColor.ITALIC; 109 } 110 111 112 public static ProxiedPlayer findPlayerSmart(CommandIssuer issuer, String search) { 113 CommandSender requester = issuer.getIssuer(); 114 String name = ACFUtil.replace(search, ":confirm", ""); 115 if (name.length() < 3) { 116 issuer.sendError(MinecraftMessageKeys.USERNAME_TOO_SHORT); 117 return null; 118 } 119 if (!isValidName(name)) { 120 issuer.sendError(MinecraftMessageKeys.IS_NOT_A_VALID_NAME, "{name}", name); 121 return null; 122 } 123 124 List<ProxiedPlayer> matches = new ArrayList<>(ProxyServer.getInstance().matchPlayer(name)); 125 126 if (matches.size() > 1) { 127 String allMatches = matches.stream().map(ProxiedPlayer::getName).collect(Collectors.joining(", ")); 128 issuer.sendError(MinecraftMessageKeys.MULTIPLE_PLAYERS_MATCH, 129 "{search}", name, "{all}", allMatches); 130 return null; 131 } 132 133 if (matches.isEmpty()) { 134 issuer.sendError(MinecraftMessageKeys.NO_PLAYER_FOUND_SERVER, 135 "{search}", name); 136 return null; 137 } 138 139 return matches.get(0); 140 } 141 142 /** 143 * Please move to the CommandIssuer version 144 * @deprecated 145 */ 146 public static ProxiedPlayer findPlayerSmart(CommandSender requester, String search) { 147 CommandManager manager = CommandManager.getCurrentCommandManager(); 148 if (manager != null) { 149 return findPlayerSmart(manager.getCommandIssuer(requester), search); 150 } 151 throw new IllegalStateException("You may not use the ACFBungeeUtil#findPlayerSmart(CommandSender) async to the command execution."); 152 } 153 154 public static boolean isValidName(String name) { 155 return name != null && !name.isEmpty() && ACFPatterns.VALID_NAME_PATTERN.matcher(name).matches(); 156 } 157 158 public static <T> T validate(T object, String message, Object... values) { 159 if (object == null) { 160 throw new NullPointerException(String.format(message, values)); 161 } 162 return object; 163 } 164 165 166}