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:
@@ -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()) {
|
||||
|
@@ -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)
|
||||
|
@@ -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 &&
|
||||
|
@@ -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;
|
||||
|
@@ -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.
|
||||
|
@@ -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();
|
||||
}
|
||||
|
@@ -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 {
|
||||
|
@@ -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' " +
|
||||
|
Reference in New Issue
Block a user