Improve handling of NPC names, fixes #1640 (#1642)

* Improve handling of NPC names, fixes #1640

Moves the logic to a Util method (instead of duplicated in each module), and adds the "prefixColors" portions (replacing just a static 'RESET' code).
If colors and effects are combined, using only the most recent effect is sufficient (eg reapplying bold) as that should produce effectively no change while still having a color code stuck into the name as is needed to break NPCs looking like real players internally.

* Additional NPC name improvement: fix color code splliting

a name consisting of a color code followed by 15 letters would get split in the middle of the color code, rather than around it. This fixes that.
This commit is contained in:
Alex "mcmonkey" Goodwin 2018-12-19 12:44:06 -08:00 committed by fullwall
parent 738a75e5c9
commit 9e0b4e0ab9
6 changed files with 77 additions and 175 deletions

View File

@ -1,8 +1,10 @@
package net.citizensnpcs.util; package net.citizensnpcs.util;
import java.util.Random; import java.util.Random;
import java.util.regex.Pattern;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
@ -36,6 +38,61 @@ public class Util {
} }
} }
private static Pattern NON_ALPHABET_MATCHER = Pattern.compile(".*[^A-Za-z0-9_].*");
public static String[] splitPlayerName(String coloredName) {
String name = coloredName, prefix = null, suffix = null;
if (coloredName.length() > 16) {
if (coloredName.length() >= 30) {
prefix = coloredName.substring(0, 16);
int len = 30;
name = coloredName.substring(16, 30);
if (NON_ALPHABET_MATCHER.matcher(name).matches()) {
if (coloredName.length() >= 32) {
len = 32;
name = coloredName.substring(16, 32);
} else if (coloredName.length() == 31) {
len = 31;
name = coloredName.substring(16, 31);
}
} else {
String prefixColors = ChatColor.getLastColors(prefix);
if (prefixColors.isEmpty()) {
prefixColors = ChatColor.RESET.toString();
}
else if (prefixColors.length() > 2) {
prefixColors = prefixColors.substring(prefixColors.length() - 2);
}
name = prefixColors + name;
}
suffix = coloredName.substring(len);
} else {
prefix = coloredName.substring(0, coloredName.length() - 16);
name = coloredName.substring(prefix.length());
if (prefix.endsWith(String.valueOf(ChatColor.COLOR_CHAR))) {
prefix = prefix.substring(0, prefix.length() - 1);
name = ChatColor.COLOR_CHAR + name;
}
if (!NON_ALPHABET_MATCHER.matcher(name).matches()) {
String prefixColors = ChatColor.getLastColors(prefix);
if (prefixColors.isEmpty()) {
prefixColors = ChatColor.RESET.toString();
}
else if (prefixColors.length() > 2) {
prefixColors = prefixColors.substring(prefixColors.length() - 2);
}
name = prefixColors + name;
}
if (name.length() > 16) {
suffix = name.substring(16);
name = name.substring(0, 16);
}
}
}
return new String[] { name, prefix, suffix };
}
public static NPCPushEvent callPushEvent(NPC npc, Vector vector) { public static NPCPushEvent callPushEvent(NPC npc, Vector vector) {
NPCPushEvent event = new NPCPushEvent(npc, vector); NPCPushEvent event = new NPCPushEvent(npc, vector);
event.setCancelled(npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true)); event.setCancelled(npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true));

View File

@ -1,10 +1,9 @@
package net.citizensnpcs.nms.v1_10_R1.entity; package net.citizensnpcs.nms.v1_10_R1.entity;
import java.util.UUID; import java.util.UUID;
import java.util.regex.Pattern;
import net.citizensnpcs.util.Util;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_10_R1.CraftWorld; import org.bukkit.craftbukkit.v1_10_R1.CraftWorld;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
@ -35,38 +34,10 @@ public class HumanController extends AbstractEntityController {
final WorldServer nmsWorld = ((CraftWorld) at.getWorld()).getHandle(); final WorldServer nmsWorld = ((CraftWorld) at.getWorld()).getHandle();
String coloredName = Colorizer.parseColors(npc.getFullName()); String coloredName = Colorizer.parseColors(npc.getFullName());
String name = coloredName, prefix = null, suffix = null; String[] nameSplit = Util.splitPlayerName(coloredName);
if (coloredName.length() > 16) { String name = nameSplit[0];
if (coloredName.length() >= 30) {
prefix = coloredName.substring(0, 16);
int len = 30;
name = coloredName.substring(16, 30);
if (NON_ALPHABET_MATCHER.matcher(name).matches()) {
if (coloredName.length() >= 32) {
len = 32;
name = coloredName.substring(16, 32);
} else if (coloredName.length() == 31) {
len = 31;
name = coloredName.substring(16, 31);
}
} else {
name = ChatColor.RESET + name;
}
suffix = coloredName.substring(len);
} else {
prefix = coloredName.substring(0, coloredName.length() - 16);
name = coloredName.substring(prefix.length());
if (!NON_ALPHABET_MATCHER.matcher(name).matches()) {
name = ChatColor.RESET + name;
}
if (name.length() > 16) {
suffix = name.substring(16);
name = name.substring(0, 16);
}
}
}
final String prefixCapture = prefix, suffixCapture = suffix; final String prefixCapture = nameSplit[1], suffixCapture = nameSplit[2];
UUID uuid = npc.getUniqueId(); UUID uuid = npc.getUniqueId();
if (uuid.version() == 4) { // clear version if (uuid.version() == 4) { // clear version
@ -148,6 +119,4 @@ public class HumanController extends AbstractEntityController {
} }
super.remove(); super.remove();
} }
private static Pattern NON_ALPHABET_MATCHER = Pattern.compile(".*[^A-Za-z0-9_].*");
} }

View File

@ -1,10 +1,9 @@
package net.citizensnpcs.nms.v1_11_R1.entity; package net.citizensnpcs.nms.v1_11_R1.entity;
import java.util.UUID; import java.util.UUID;
import java.util.regex.Pattern;
import net.citizensnpcs.util.Util;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_11_R1.CraftWorld; import org.bukkit.craftbukkit.v1_11_R1.CraftWorld;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
@ -35,38 +34,10 @@ public class HumanController extends AbstractEntityController {
final WorldServer nmsWorld = ((CraftWorld) at.getWorld()).getHandle(); final WorldServer nmsWorld = ((CraftWorld) at.getWorld()).getHandle();
String coloredName = Colorizer.parseColors(npc.getFullName()); String coloredName = Colorizer.parseColors(npc.getFullName());
String name = coloredName, prefix = null, suffix = null; String[] nameSplit = Util.splitPlayerName(coloredName);
if (coloredName.length() > 16) { String name = nameSplit[0];
if (coloredName.length() >= 30) {
prefix = coloredName.substring(0, 16);
int len = 30;
name = coloredName.substring(16, 30);
if (NON_ALPHABET_MATCHER.matcher(name).matches()) {
if (coloredName.length() >= 32) {
len = 32;
name = coloredName.substring(16, 32);
} else if (coloredName.length() == 31) {
len = 31;
name = coloredName.substring(16, 31);
}
} else {
name = ChatColor.RESET + name;
}
suffix = coloredName.substring(len);
} else {
prefix = coloredName.substring(0, coloredName.length() - 16);
name = coloredName.substring(prefix.length());
if (!NON_ALPHABET_MATCHER.matcher(name).matches()) {
name = ChatColor.RESET + name;
}
if (name.length() > 16) {
suffix = name.substring(16);
name = name.substring(0, 16);
}
}
}
final String prefixCapture = prefix, suffixCapture = suffix; final String prefixCapture = nameSplit[1], suffixCapture = nameSplit[2];
UUID uuid = npc.getUniqueId(); UUID uuid = npc.getUniqueId();
if (uuid.version() == 4) { // clear version if (uuid.version() == 4) { // clear version
@ -148,6 +119,4 @@ public class HumanController extends AbstractEntityController {
} }
super.remove(); super.remove();
} }
private static Pattern NON_ALPHABET_MATCHER = Pattern.compile(".*[^A-Za-z0-9_].*");
} }

View File

@ -1,10 +1,9 @@
package net.citizensnpcs.nms.v1_12_R1.entity; package net.citizensnpcs.nms.v1_12_R1.entity;
import java.util.UUID; import java.util.UUID;
import java.util.regex.Pattern;
import net.citizensnpcs.util.Util;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_12_R1.CraftWorld; import org.bukkit.craftbukkit.v1_12_R1.CraftWorld;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
@ -35,38 +34,10 @@ public class HumanController extends AbstractEntityController {
final WorldServer nmsWorld = ((CraftWorld) at.getWorld()).getHandle(); final WorldServer nmsWorld = ((CraftWorld) at.getWorld()).getHandle();
String coloredName = Colorizer.parseColors(npc.getFullName()); String coloredName = Colorizer.parseColors(npc.getFullName());
String name = coloredName, prefix = null, suffix = null; String[] nameSplit = Util.splitPlayerName(coloredName);
if (coloredName.length() > 16) { String name = nameSplit[0];
if (coloredName.length() >= 30) {
prefix = coloredName.substring(0, 16);
int len = 30;
name = coloredName.substring(16, 30);
if (NON_ALPHABET_MATCHER.matcher(name).matches()) {
if (coloredName.length() >= 32) {
len = 32;
name = coloredName.substring(16, 32);
} else if (coloredName.length() == 31) {
len = 31;
name = coloredName.substring(16, 31);
}
} else {
name = ChatColor.RESET + name;
}
suffix = coloredName.substring(len);
} else {
prefix = coloredName.substring(0, coloredName.length() - 16);
name = coloredName.substring(prefix.length());
if (!NON_ALPHABET_MATCHER.matcher(name).matches()) {
name = ChatColor.RESET + name;
}
if (name.length() > 16) {
suffix = name.substring(16);
name = name.substring(0, 16);
}
}
}
final String prefixCapture = prefix, suffixCapture = suffix; final String prefixCapture = nameSplit[1], suffixCapture = nameSplit[2];
UUID uuid = npc.getUniqueId(); UUID uuid = npc.getUniqueId();
if (uuid.version() == 4) { // clear version if (uuid.version() == 4) { // clear version
@ -148,6 +119,4 @@ public class HumanController extends AbstractEntityController {
} }
super.remove(); super.remove();
} }
private static Pattern NON_ALPHABET_MATCHER = Pattern.compile(".*[^A-Za-z0-9_].*");
} }

View File

@ -1,10 +1,9 @@
package net.citizensnpcs.nms.v1_13_R2.entity; package net.citizensnpcs.nms.v1_13_R2.entity;
import java.util.UUID; import java.util.UUID;
import java.util.regex.Pattern;
import net.citizensnpcs.util.Util;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_13_R2.CraftWorld; import org.bukkit.craftbukkit.v1_13_R2.CraftWorld;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
@ -35,38 +34,10 @@ public class HumanController extends AbstractEntityController {
final WorldServer nmsWorld = ((CraftWorld) at.getWorld()).getHandle(); final WorldServer nmsWorld = ((CraftWorld) at.getWorld()).getHandle();
String coloredName = Colorizer.parseColors(npc.getFullName()); String coloredName = Colorizer.parseColors(npc.getFullName());
String name = coloredName, prefix = null, suffix = null; String[] nameSplit = Util.splitPlayerName(coloredName);
if (coloredName.length() > 16) { String name = nameSplit[0];
if (coloredName.length() >= 30) {
prefix = coloredName.substring(0, 16);
int len = 30;
name = coloredName.substring(16, 30);
if (NON_ALPHABET_MATCHER.matcher(name).matches()) {
if (coloredName.length() >= 32) {
len = 32;
name = coloredName.substring(16, 32);
} else if (coloredName.length() == 31) {
len = 31;
name = coloredName.substring(16, 31);
}
} else {
name = ChatColor.RESET + name;
}
suffix = coloredName.substring(len);
} else {
prefix = coloredName.substring(0, coloredName.length() - 16);
name = coloredName.substring(prefix.length());
if (!NON_ALPHABET_MATCHER.matcher(name).matches()) {
name = ChatColor.RESET + name;
}
if (name.length() > 16) {
suffix = name.substring(16);
name = name.substring(0, 16);
}
}
}
final String prefixCapture = prefix, suffixCapture = suffix; final String prefixCapture = nameSplit[1], suffixCapture = nameSplit[2];
UUID uuid = npc.getUniqueId(); UUID uuid = npc.getUniqueId();
if (uuid.version() == 4) { // clear version if (uuid.version() == 4) { // clear version
@ -148,6 +119,4 @@ public class HumanController extends AbstractEntityController {
} }
super.remove(); super.remove();
} }
private static Pattern NON_ALPHABET_MATCHER = Pattern.compile(".*[^A-Za-z0-9_].*");
} }

View File

@ -1,10 +1,9 @@
package net.citizensnpcs.nms.v1_8_R3.entity; package net.citizensnpcs.nms.v1_8_R3.entity;
import java.util.UUID; import java.util.UUID;
import java.util.regex.Pattern;
import net.citizensnpcs.util.Util;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; import org.bukkit.craftbukkit.v1_8_R3.CraftWorld;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
@ -35,38 +34,10 @@ public class HumanController extends AbstractEntityController {
final WorldServer nmsWorld = ((CraftWorld) at.getWorld()).getHandle(); final WorldServer nmsWorld = ((CraftWorld) at.getWorld()).getHandle();
String coloredName = Colorizer.parseColors(npc.getFullName()); String coloredName = Colorizer.parseColors(npc.getFullName());
String name = coloredName, prefix = null, suffix = null; String[] nameSplit = Util.splitPlayerName(coloredName);
if (coloredName.length() > 16) { String name = nameSplit[0];
if (coloredName.length() >= 30) {
prefix = coloredName.substring(0, 16);
int len = 30;
name = coloredName.substring(16, 30);
if (NON_ALPHABET_MATCHER.matcher(name).matches()) {
if (coloredName.length() >= 32) {
len = 32;
name = coloredName.substring(16, 32);
} else if (coloredName.length() == 31) {
len = 31;
name = coloredName.substring(16, 31);
}
} else {
name = ChatColor.RESET + name;
}
suffix = coloredName.substring(len);
} else {
prefix = coloredName.substring(0, coloredName.length() - 16);
name = coloredName.substring(prefix.length());
if (!NON_ALPHABET_MATCHER.matcher(name).matches()) {
name = ChatColor.RESET + name;
}
if (name.length() > 16) {
suffix = name.substring(16);
name = name.substring(0, 16);
}
}
}
final String prefixCapture = prefix, suffixCapture = suffix; final String prefixCapture = nameSplit[1], suffixCapture = nameSplit[2];
UUID uuid = npc.getUniqueId(); UUID uuid = npc.getUniqueId();
if (uuid.version() == 4) { // clear version if (uuid.version() == 4) { // clear version
@ -148,6 +119,4 @@ public class HumanController extends AbstractEntityController {
} }
super.remove(); super.remove();
} }
private static Pattern NON_ALPHABET_MATCHER = Pattern.compile(".*[^A-Za-z0-9_].*");
} }