Add new armorstand option for player disguise names, clean up config cos of the player name options

Added ability to set multiple names on a player disguise, also normal mob but that is untested and has no command accessibility
Permission to do this is libsdisguises.multiname
Renamed "Now disguised as a %s" to "Now disguised as %s" for messages
This commit is contained in:
libraryaddict
2020-05-07 21:27:07 +12:00
parent 6170d8e77f
commit 888bbd9521
16 changed files with 406 additions and 104 deletions

View File

@@ -22,6 +22,7 @@ import me.libraryaddict.disguise.LibsDisguises;
import me.libraryaddict.disguise.disguisetypes.*;
import me.libraryaddict.disguise.disguisetypes.TargetedDisguise.TargetType;
import me.libraryaddict.disguise.disguisetypes.watchers.AgeableWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.ZombieWatcher;
import me.libraryaddict.disguise.utilities.json.*;
import me.libraryaddict.disguise.utilities.mineskin.MineSkinAPI;
@@ -84,6 +85,7 @@ public class DisguiseUtilities {
}
public void handleTeam(Scoreboard board, boolean nameVisible) {
nameVisible = !DisguiseConfig.isArmorstandsName() && nameVisible;
Team team = board.getTeam(getTeamName());
if (team == null) {
@@ -1037,7 +1039,7 @@ public class DisguiseUtilities {
if (disguise.isDisguiseInUse() && disguise.getEntity() instanceof Player &&
disguise.getEntity().getName().equalsIgnoreCase(player)) {
removeSelfDisguise((Player) disguise.getEntity());
removeSelfDisguise(disguise);
if (disguise.isSelfDisguiseVisible()) {
selfDisguised.add(disguise.getEntity().getUniqueId());
@@ -1167,7 +1169,7 @@ public class DisguiseUtilities {
try {
if (selfDisguised.contains(disguise.getEntity().getUniqueId()) && disguise.isDisguiseInUse()) {
removeSelfDisguise((Player) disguise.getEntity());
removeSelfDisguise(disguise);
selfDisguised.add(disguise.getEntity().getUniqueId());
@@ -1257,16 +1259,21 @@ public class DisguiseUtilities {
file.delete();
}
public static void removeSelfDisguise(Player player) {
public static void removeSelfDisguise(Disguise disguise) {
if (!Bukkit.isPrimaryThread())
throw new IllegalStateException("Cannot modify disguises on an async thread");
Player player = (Player) disguise.getEntity();
if (!selfDisguised.contains(player.getUniqueId())) {
return;
}
int[] ids = Arrays.copyOf(disguise.getArmorstandIds(), 1 + disguise.getMultiName().length);
ids[ids.length - 1] = DisguiseAPI.getSelfDisguiseId();
// Send a packet to destroy the fake entity
PacketContainer packet = getDestroyPacket(DisguiseAPI.getSelfDisguiseId());
PacketContainer packet = getDestroyPacket(ids);
try {
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet);
@@ -1439,7 +1446,7 @@ public class DisguiseUtilities {
}
public static String[] getExtendedNameSplit(String playerName, String name) {
if (name.length() <= 16 && !DisguiseConfig.isScoreboardDisguiseNames()) {
if (name.length() <= 16 && !DisguiseConfig.isScoreboardNames()) {
throw new IllegalStateException("This can only be used for names longer than 16 characters!");
}
@@ -1450,7 +1457,7 @@ public class DisguiseUtilities {
Scoreboard board = Bukkit.getScoreboardManager().getMainScoreboard();
// If name is short enough to be used outside of player name
if (DisguiseConfig.isScoreboardDisguiseNames() && name.length() <= 32) {
if (DisguiseConfig.isScoreboardNames() && name.length() <= 32) {
String[] newName = new String[]{name, playerName, ""};
if (name.length() > 16) {
@@ -1749,6 +1756,39 @@ public class DisguiseUtilities {
"\"";
}
public static String quoteNewLine(String string) {
return string.replaceAll("\\\\(?=\\\\+n)", "\\\\\\\\");
}
public static String[] splitNewLine(String string) {
Pattern regex = Pattern.compile("\\\\+n");
Matcher result = regex.matcher(string);
ArrayList<String> lines = new ArrayList<>();
StringBuilder builder = new StringBuilder();
int last = 0;
while (result.find()) {
builder.append(string, last, result.start());
last = result.end();
if (result.group().matches("(\\\\\\\\)+n")) {
builder.append(result.group().replace("\\\\", "\\"));
} else {
String group = result.group().replace("\\\\", "\\");
builder.append(group, 0, group.length() - 2);
lines.add(builder.toString());
builder = new StringBuilder();
}
}
lines.add(builder.toString() + string.substring(last));
return lines.toArray(new String[0]);
}
public static String[] split(String string) {
// Regex where we first match any character that isn't a slash, if it is a slash then it must not have more
// slashes until it hits the quote
@@ -2020,7 +2060,7 @@ public class DisguiseUtilities {
}
// Remove the old disguise, else we have weird disguises around the place
DisguiseUtilities.removeSelfDisguise(player);
DisguiseUtilities.removeSelfDisguise(disguise);
// If the disguised player can't see himself. Return
if (!disguise.isSelfDisguiseVisible() || !PacketsManager.isViewDisguisesListenerEnabled() ||
@@ -2237,6 +2277,100 @@ public class DisguiseUtilities {
}
}
public static ArrayList<PacketContainer> getNamePackets(Disguise disguise, String[] oldNames) {
ArrayList<PacketContainer> packets = new ArrayList<>();
String[] newNames =
(disguise instanceof PlayerDisguise && !((PlayerDisguise) disguise).isNameVisible()) ? new String[0] :
disguise.getMultiName();
int[] standIds = disguise.getArmorstandIds();
int[] destroyIds = new int[0];
if (oldNames.length > newNames.length) {
// Destroy packet
destroyIds = Arrays.copyOfRange(standIds, newNames.length, oldNames.length);
}
for (int i = 0; i < newNames.length; i++) {
if (i < oldNames.length) {
if (newNames[i].equals(oldNames[i]) || newNames[i].isEmpty()) {
continue;
}
WrappedDataWatcher watcher = new WrappedDataWatcher();
Object name = NmsVersion.v1_13.isSupported() ? Optional.of(WrappedChatComponent.fromText(newNames[i])) :
newNames[i];
WrappedDataWatcher.WrappedDataWatcherObject obj = ReflectionManager.createDataWatcherObject(
NmsVersion.v1_13.isSupported() ? MetaIndex.ENTITY_CUSTOM_NAME :
MetaIndex.ENTITY_CUSTOM_NAME_OLD, name);
watcher.setObject(obj, ReflectionManager.convertInvalidMeta(name));
PacketContainer metaPacket = ProtocolLibrary.getProtocolManager()
.createPacketConstructor(PacketType.Play.Server.ENTITY_METADATA, 0, watcher, true)
.createPacket(standIds[i], watcher, true);
packets.add(metaPacket);
} else if (newNames[i].isEmpty()) {
destroyIds = Arrays.copyOf(destroyIds, destroyIds.length + 1);
destroyIds[destroyIds.length - 1] = standIds[i];
} else {
PacketContainer packet = new PacketContainer(Server.SPAWN_ENTITY_LIVING);
packet.getIntegers().write(0, standIds[i]);
packet.getIntegers().write(1, DisguiseType.ARMOR_STAND.getTypeId());
packet.getUUIDs().write(0, UUID.randomUUID());
Location loc = disguise.getEntity().getLocation();
packet.getDoubles().write(0, loc.getX());
packet.getDoubles().write(1, loc.getY() + -0.175 + (0.28 * i));
packet.getDoubles().write(2, loc.getZ());
packets.add(packet);
WrappedDataWatcher watcher = new WrappedDataWatcher();
for (MetaIndex index : MetaIndex.getMetaIndexes(LivingWatcher.class)) {
Object val = index.getDefault();
if (index == MetaIndex.ENTITY_META) {
val = (byte) 32;
} else if (index == MetaIndex.ARMORSTAND_META) {
val = (byte) 17;
} else if (index == MetaIndex.ENTITY_CUSTOM_NAME) {
val = Optional.of(WrappedChatComponent.fromText(newNames[i]));
} else if (index == MetaIndex.ENTITY_CUSTOM_NAME_OLD) {
val = newNames[i];
} else if (index == MetaIndex.ENTITY_CUSTOM_NAME_VISIBLE) {
val = true;
}
WrappedDataWatcher.WrappedDataWatcherObject obj = ReflectionManager
.createDataWatcherObject(index, val);
watcher.setObject(obj, ReflectionManager.convertInvalidMeta(val));
}
if (NmsVersion.v1_15.isSupported()) {
PacketContainer metaPacket = ProtocolLibrary.getProtocolManager()
.createPacketConstructor(PacketType.Play.Server.ENTITY_METADATA, 0, watcher, true)
.createPacket(standIds[i], watcher, true);
packets.add(metaPacket);
} else {
packet.getDataWatcherModifier().write(0, watcher);
}
}
}
if (destroyIds.length > 0) {
packets.add(getDestroyPacket(destroyIds));
}
return packets;
}
public static Disguise getDisguise(Player observer, int entityId) {
// If the entity ID is the same as self disguises id, then it needs to be set to the observers id
if (entityId == DisguiseAPI.getSelfDisguiseId()) {

View File

@@ -583,12 +583,19 @@ public class DisguiseListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onVehicleEnter(VehicleEnterEvent event) {
if (event.getEntered() instanceof Player &&
DisguiseAPI.isDisguised((Player) event.getEntered(), event.getEntered())) {
DisguiseUtilities.removeSelfDisguise((Player) event.getEntered());
((Player) event.getEntered()).updateInventory();
if (!(event.getEntered() instanceof Player)) {
return;
}
Disguise disguise = DisguiseAPI.getDisguise((Player) event.getEntered(), event.getEntered());
if (disguise == null) {
return;
}
DisguiseUtilities.removeSelfDisguise(disguise);
((Player) event.getEntered()).updateInventory();
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)

View File

@@ -25,6 +25,7 @@ public class PacketsManager {
private static PacketListener viewDisguisesListener;
private static boolean viewDisguisesListenerEnabled;
private static PacketsHandler packetsHandler;
private static PacketListener destroyListener;
public static void addPacketListeners() {
// Add a client listener to cancel them interacting with uninteractable disguised entitys.
@@ -160,8 +161,10 @@ public class PacketsManager {
}
mainListener = new PacketListenerMain(LibsDisguises.getInstance(), packetsToListen);
destroyListener = new PacketListenerDestroyEntity(LibsDisguises.getInstance());
ProtocolLibrary.getProtocolManager().addPacketListener(mainListener);
ProtocolLibrary.getProtocolManager().addPacketListener(destroyListener);
}
}
@@ -183,7 +186,7 @@ public class PacketsManager {
if (enabled) {
DisguiseUtilities.setupFakeDisguise(disguise);
} else {
DisguiseUtilities.removeSelfDisguise(player);
DisguiseUtilities.removeSelfDisguise(disguise);
}
if (inventoryModifierEnabled &&

View File

@@ -18,6 +18,8 @@ import org.bukkit.entity.Player;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.util.Vector;
import java.util.ArrayList;
/**
* Created by libraryaddict on 3/01/2019.
*/
@@ -38,6 +40,36 @@ public class PacketHandlerMovement implements IPacketHandler {
@Override
public void handle(Disguise disguise, PacketContainer sentPacket, LibsPackets packets, Player observer,
Entity entity) {
handle2(disguise, sentPacket, packets, observer, entity);
int len = disguise.getMultiName().length;
if (len == 0) {
return;
}
ArrayList<PacketContainer> toAdd = new ArrayList<>();
for (PacketContainer packet : packets.getPackets()) {
for (int i = 0; i < len; i++) {
for (int standId : disguise.getArmorstandIds()) {
PacketContainer packet2 = packet.shallowClone();
packet2.getIntegers().write(0, standId);
if (packet2.getType() == PacketType.Play.Server.ENTITY_TELEPORT) {
packet2.getDoubles().write(1, packet2.getDoubles().read(1) + -0.175 + (0.28 * i));
}
toAdd.add(packet2);
}
}
}
packets.getPackets().addAll(toAdd);
}
public void handle2(Disguise disguise, PacketContainer sentPacket, LibsPackets packets, Player observer,
Entity entity) {
if (invalid && RandomUtils.nextDouble() < 0.1) {
packets.clear();
return;

View File

@@ -151,7 +151,7 @@ public class PacketHandlerSpawn implements IPacketHandler {
mods.write(5, pitch);
} else if (disguise.getType().isPlayer()) {
PlayerDisguise playerDisguise = (PlayerDisguise) disguise;
boolean visibleOrNewCompat = playerDisguise.isNameVisible() || DisguiseConfig.isScoreboardDisguiseNames();
boolean visibleOrNewCompat = playerDisguise.isNameVisible() || DisguiseConfig.isScoreboardNames();
WrappedGameProfile spawnProfile = visibleOrNewCompat ? playerDisguise.getGameProfile() : ReflectionManager
.getGameProfileWithThisSkin(UUID.randomUUID(), visibleOrNewCompat ? playerDisguise.getName() : "",
@@ -387,6 +387,8 @@ public class PacketHandlerSpawn implements IPacketHandler {
packets.addPacket(newPacket);
}
DisguiseUtilities.getNamePackets(disguise, new String[0]).forEach(packets::addPacket);
// If armor must be sent because its currently not displayed and would've been sent normally
// This sends the armor packets so that the player isn't naked.

View File

@@ -78,7 +78,8 @@ public class PacketListenerViewSelfDisguise extends PacketAdapter {
}
for (PacketContainer newPacket : transformed.getPackets()) {
if (newPacket.getType() != Server.PLAYER_INFO) {
if (newPacket.getType() != Server.PLAYER_INFO &&
newPacket.getIntegers().read(0) == observer.getEntityId()) {
if (newPacket == packet) {
newPacket = newPacket.shallowClone();
}

View File

@@ -698,6 +698,10 @@ public class DisguiseParser {
args[1] = args[1].replace("\\_", " ");
if (DisguiseConfig.isArmorstandsName() && !sender.hasPermission("libsdisguises.multiname")) {
args[1] = DisguiseUtilities.quoteNewLine(args[1]);
}
// Construct the player disguise
disguise = new PlayerDisguise(ChatColor.translateAlternateColorCodes('&', args[1]));
@@ -904,6 +908,10 @@ public class DisguiseParser {
}
}
if (DisguiseConfig.isArmorstandsName() && methodToUse.getName().equals("setName") && !sender.hasPermission("libsdisguises.multiname")) {
valueToSet = DisguiseUtilities.quoteNewLine((String) valueToSet);
}
if (FlagWatcher.class.isAssignableFrom(methodToUse.getDeclaringClass())) {
methodToUse.invoke(disguise.getWatcher(), valueToSet);
} else {

View File

@@ -59,7 +59,7 @@ public enum LibsMsg {
DISG_HELP4(ChatColor.DARK_GREEN + "/disguise <Dropped_Item/Falling_Block> <Id> <Durability>"),
DISG_PLAYER_AS_DISG(ChatColor.RED + "Successfully disguised %s as a %s!"),
DISG_PLAYER_AS_DISG_FAIL(ChatColor.RED + "Failed to disguise %s as a %s!"),
DISGUISED(ChatColor.RED + "Now disguised as a %s"),
DISGUISED(ChatColor.RED + "Now disguised as %s"),
DISRADIUS(ChatColor.RED + "Successfully disguised %s entities!"),
DISRADIUS_FAIL(ChatColor.RED + "Couldn't find any entities to disguise!"),
DMODENT_HELP1(ChatColor.DARK_GREEN + "Choose the options for a disguise then right click a entity to modify it!"),
@@ -116,7 +116,7 @@ public enum LibsMsg {
"disabled in the config"),
DRADIUS_NEEDOPTIONS(ChatColor.RED + "You need to supply a disguise as well as the radius"),
DRADIUS_NEEDOPTIONS_ENTITY(ChatColor.RED + "You need to supply a disguise as well as the radius and EntityType"),
FAILED_DISGIUSE(ChatColor.RED + "Failed to disguise as a %s"),
FAILED_DISGIUSE(ChatColor.RED + "Failed to disguise as %s"),
GRABBED_SKIN(ChatColor.GOLD + "Grabbed skin and saved as %s!"),
PLEASE_WAIT(ChatColor.GRAY + "Please wait..."),
INVALID_CLONE(ChatColor.DARK_RED + "Unknown method '%s' - Valid methods are 'IgnoreEquipment' 'DoSneakSprint' " +