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
No known key found for this signature in database
GPG Key ID: 052E4FBCD257AEA4
16 changed files with 406 additions and 104 deletions

View File

@ -95,9 +95,6 @@ public class DisguiseConfig {
private static boolean explicitDisguisePermissions;
@Getter
@Setter
private static boolean extendedDisguiseNames;
@Getter
@Setter
private static boolean hideDisguisedPlayers;
@Getter
@Setter
@ -228,9 +225,6 @@ public class DisguiseConfig {
private static PermissionDefault commandVisibility = PermissionDefault.TRUE;
@Getter
@Setter
private static boolean scoreboardDisguiseNames;
@Getter
@Setter
private static int tablistRemoveDelay;
@Getter
private static boolean usingReleaseBuild = true;
@ -246,6 +240,17 @@ public class DisguiseConfig {
@Getter
@Setter
private static boolean hideTallSelfDisguises;
@Getter
@Setter
private static PlayerNameType playerNameType = PlayerNameType.ARMORSTANDS;
public static boolean isArmorstandsName() {
return getPlayerNameType() == PlayerNameType.ARMORSTANDS;
}
public static boolean isExtendedNames() {
return getPlayerNameType() == PlayerNameType.TEAMS_EXTENDED;
}
public static void setAutoUpdate(boolean update) {
if (isAutoUpdate() == update) {
@ -447,6 +452,10 @@ public class DisguiseConfig {
return new HashMap.SimpleEntry(entry.getKey(), DisguiseParser.parseDisguise(invoker, target, entry.getValue()));
}
public static boolean isScoreboardNames() {
return getPlayerNameType() != PlayerNameType.VANILLA;
}
public static void removeCustomDisguise(String disguise) {
for (DisguisePerm entry : customDisguises.keySet()) {
String name = entry.toReadable();
@ -596,8 +605,6 @@ public class DisguiseConfig {
setEntityStatusPacketsEnabled(config.getBoolean("PacketsEnabled.EntityStatus"));
setEquipmentPacketsEnabled(config.getBoolean("PacketsEnabled.Equipment"));
setExplicitDisguisePermissions(config.getBoolean("Permissions.ExplicitDisguises"));
// The default value shall be false if you don't update config
setExtendedDisguiseNames(config.contains("ScoreboardNames") && config.getBoolean("ExtendedNames"));
setHideArmorFromSelf(config.getBoolean("RemoveArmor"));
setHideDisguisedPlayers(config.getBoolean("HideDisguisedPlayersFromTab"));
setHideHeldItemFromSelf(config.getBoolean("RemoveHeldItem"));
@ -634,7 +641,6 @@ public class DisguiseConfig {
setWarnScoreboardConflict(config.getBoolean("Scoreboard.WarnConflict"));
setWitherSkullPacketsEnabled(config.getBoolean("PacketsEnabled.WitherSkull"));
setWolfDyeable(config.getBoolean("DyeableWolf"));
setScoreboardDisguiseNames(config.getBoolean("ScoreboardNames"));
setTablistRemoveDelay(config.getInt("TablistRemoveDelay"));
setAutoUpdate(config.getBoolean("AutoUpdate"));
setHideTallSelfDisguises(config.getBoolean("HideTallSelfDisguises"));
@ -643,6 +649,14 @@ public class DisguiseConfig {
DisguiseUtilities.getLogger().warning("You must purchase the plugin to use saved disguises!");
}
try {
setPlayerNameType(PlayerNameType.valueOf(config.getString("PlayerNames").toUpperCase()));
}
catch (Exception ex) {
DisguiseUtilities.getLogger()
.warning("Cannot parse '" + config.getString("PlayerNames") + "' to a valid option for PlayerNames");
}
try {
setNotifyBar(NotifyBar.valueOf(config.getString("NotifyBar").toUpperCase()));
@ -1077,6 +1091,17 @@ public class DisguiseConfig {
CREATE_SCOREBOARD
}
public enum PlayerNameType {
VANILLA,
TEAMS,
TEAMS_EXTENDED,
ARMORSTANDS;
public boolean isTeams() {
return this == TEAMS || this == TEAMS_EXTENDED;
}
}
public enum UpdatesBranch {
SAME_BUILDS,
SNAPSHOTS,

View File

@ -36,7 +36,7 @@ public class LDScoreboard implements LDCommand {
@Override
public void onCommand(CommandSender sender, String[] args) {
if (DisguiseConfig.isScoreboardDisguiseNames()) {
if (DisguiseConfig.isScoreboardNames()) {
int issuesFound = 0;
int unexpected = 0;

View File

@ -96,16 +96,59 @@ public abstract class Disguise {
*/
@Getter
@Setter
private boolean customName = true;
private boolean customDisguiseName = true;
@Getter
@Setter
private boolean tallDisguisesVisible = !DisguiseConfig.isHideTallSelfDisguises();
@Getter
private String[] multiName = new String[0];
private transient int[] armorstandIds = new int[0];
public Disguise(DisguiseType disguiseType) {
this.disguiseType = disguiseType;
this.disguiseName = disguiseType.toReadable();
}
public void setMultiName(String... name) {
String[] oldName = getMultiName();
multiName = name;
if (!isDisguiseInUse()) {
return;
}
sendArmorStands(oldName);
}
protected void sendArmorStands(String[] oldName) {
ArrayList<PacketContainer> packets = DisguiseUtilities.getNamePackets(this, oldName);
try {
for (Player player : DisguiseUtilities.getPerverts(this)) {
for (PacketContainer packet : packets) {
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet);
}
}
}
catch (InvocationTargetException e) {
e.printStackTrace();
}
}
public int[] getArmorstandIds() {
if (getMultiName().length > armorstandIds.length) {
int oldLen = armorstandIds.length;
armorstandIds = Arrays.copyOf(armorstandIds, getMultiName().length);
for (int i = oldLen; i < armorstandIds.length; i++) {
armorstandIds[i] = ReflectionManager.getNewEntityId();
}
}
return armorstandIds;
}
public void addCustomData(String key, Object data) {
customData.put(key, data);
}
@ -123,7 +166,7 @@ public abstract class Disguise {
protected void clone(Disguise disguise) {
disguise.setDisguiseName(getDisguiseName());
disguise.setCustomName(isCustomName());
disguise.setCustomDisguiseName(isCustomDisguiseName());
disguise.setTallDisguisesVisible(isTallDisguisesVisible());
disguise.setReplaceSounds(isSoundsReplaced());
@ -133,6 +176,7 @@ public abstract class Disguise {
disguise.setHideHeldItemFromSelf(isHidingHeldItemFromSelf());
disguise.setVelocitySent(isVelocitySent());
disguise.setModifyBoundingBox(isModifyBoundingBox());
disguise.multiName = Arrays.copyOf(multiName, multiName.length);
if (getWatcher() != null) {
disguise.setWatcher(getWatcher().clone(disguise));
@ -795,20 +839,13 @@ public abstract class Disguise {
task = null;
}
// If this disguise has a entity set
// If this disguise hasn't a entity set
if (getEntity() == null) {
// Loop through the disguises because it could be used with a unknown entity id.
HashMap<Integer, HashSet<TargetedDisguise>> future = DisguiseUtilities.getFutureDisguises();
Iterator<Integer> itel = DisguiseUtilities.getFutureDisguises().keySet().iterator();
while (itel.hasNext()) {
int id = itel.next();
if (future.get(id).remove(this) && future.get(id).isEmpty()) {
itel.remove();
}
}
DisguiseUtilities.getFutureDisguises().keySet()
.removeIf(id -> future.get(id).remove(this) && future.get(id).isEmpty());
return true;
}
@ -842,7 +879,7 @@ public abstract class Disguise {
// Remove the disguise from the current disguises.
if (DisguiseUtilities.removeDisguise((TargetedDisguise) this)) {
if (getEntity() instanceof Player) {
DisguiseUtilities.removeSelfDisguise((Player) getEntity());
DisguiseUtilities.removeSelfDisguise(this);
}
// Better refresh the entity to undisguise it
@ -893,6 +930,20 @@ public abstract class Disguise {
}
}
if (getMultiName().length > 0) {
PacketContainer packet = new PacketContainer(Server.ENTITY_DESTROY);
packet.getIntegerArrays().write(0, Arrays.copyOf(getArmorstandIds(), getMultiName().length));
try {
for (Player player : DisguiseUtilities.getPerverts(this)) {
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet);
}
}
catch (InvocationTargetException e) {
e.printStackTrace();
}
}
return true;
}
@ -970,7 +1021,7 @@ public abstract class Disguise {
if (isSelfDisguiseVisible()) {
DisguiseUtilities.setupFakeDisguise(this);
} else {
DisguiseUtilities.removeSelfDisguise((Player) getEntity());
DisguiseUtilities.removeSelfDisguise(this);
}
}
}
@ -1053,7 +1104,7 @@ public abstract class Disguise {
DisguiseUtilities.addDisguise(entity.getUniqueId(), (TargetedDisguise) this);
if (isSelfDisguiseVisible() && getEntity() instanceof Player) {
DisguiseUtilities.removeSelfDisguise((Player) getEntity());
DisguiseUtilities.removeSelfDisguise(this);
}
// Resend the disguised entity's packet

View File

@ -12,7 +12,6 @@ import me.libraryaddict.disguise.disguisetypes.watchers.PlayerWatcher;
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
import me.libraryaddict.disguise.utilities.reflection.LibsProfileLookup;
import me.libraryaddict.disguise.utilities.reflection.ReflectionManager;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
@ -27,6 +26,10 @@ public class PlayerDisguise extends TargetedDisguise {
private String playerName = "Herobrine";
private String skinToUse;
private boolean nameVisible = true;
/**
* Has someone set name visible explicitly?
*/
private boolean explicitNameVisible = false;
private UUID uuid = UUID.randomUUID();
@Getter
@Setter
@ -82,8 +85,7 @@ public class PlayerDisguise extends TargetedDisguise {
@Deprecated
public DisguiseUtilities.DScoreTeam getScoreboardName() {
if (getName().length() <= 32 ? !DisguiseConfig.isScoreboardDisguiseNames() :
!DisguiseConfig.isExtendedDisguiseNames()) {
if (!DisguiseConfig.isScoreboardNames()) {
throw new IllegalStateException("Cannot use this method when it's been disabled in config!");
}
@ -103,11 +105,11 @@ public class PlayerDisguise extends TargetedDisguise {
}
public boolean hasScoreboardName() {
if (isStaticName(getName())) {
if (!DisguiseConfig.isArmorstandsName() && isStaticName(getName())) {
return false;
}
return scoreboardName != null || DisguiseConfig.isScoreboardDisguiseNames() || getName().length() > 16;
return DisguiseConfig.isScoreboardNames();
}
public String getProfileName() {
@ -123,12 +125,23 @@ public class PlayerDisguise extends TargetedDisguise {
}
public PlayerDisguise setNameVisible(boolean nameVisible) {
if (isNameVisible() == nameVisible) {
return setNameVisible(nameVisible, false);
}
private PlayerDisguise setNameVisible(boolean nameVisible, boolean setInternally) {
if (isNameVisible() == nameVisible || (setInternally && explicitNameVisible)) {
return this;
}
if (!setInternally) {
explicitNameVisible = true;
}
if (isDisguiseInUse()) {
if (!DisguiseConfig.isScoreboardDisguiseNames()) {
if (DisguiseConfig.isArmorstandsName()) {
this.nameVisible = nameVisible;
sendArmorStands(isNameVisible() ? getMultiName() : new String[0]);
} else if (!DisguiseConfig.isScoreboardNames()) {
if (stopDisguise()) {
this.nameVisible = nameVisible;
@ -172,7 +185,8 @@ public class PlayerDisguise extends TargetedDisguise {
}
disguise.setName(getName());
disguise.setNameVisible(isNameVisible());
disguise.nameVisible = isNameVisible();
disguise.explicitNameVisible = explicitNameVisible;
disguise.setDynamicName(isDynamicName());
clone(disguise);
@ -214,16 +228,37 @@ public class PlayerDisguise extends TargetedDisguise {
return;
}
int cLimit = DisguiseConfig.isExtendedDisguiseNames() ? 16 * 3 :
DisguiseConfig.isScoreboardDisguiseNames() ? 16 * 2 : 16;
int cLimit;
switch (DisguiseConfig.getPlayerNameType()) {
case TEAMS:
cLimit = 16 * 2;
break;
case TEAMS_EXTENDED:
cLimit = 16 * 3;
break;
case ARMORSTANDS:
cLimit = 256;
break;
default:
cLimit = 16;
break;
}
if (name.length() > cLimit) {
name = name.substring(0, cLimit);
}
if (isDisguiseInUse()) {
if (DisguiseConfig.isArmorstandsName()) {
playerName = name;
setNameVisible(!name.isEmpty(), true);
setMultiName(DisguiseUtilities.splitNewLine(name));
} else {
boolean resendDisguise = false;
if (DisguiseConfig.isScoreboardDisguiseNames() && !isStaticName(name)) {
if (DisguiseConfig.isScoreboardNames() && !isStaticName(name)) {
DisguiseUtilities.DScoreTeam team = getScoreboardName();
String[] split = DisguiseUtilities.getExtendedNameSplit(team.getPlayer(), name);
@ -231,16 +266,15 @@ public class PlayerDisguise extends TargetedDisguise {
setScoreboardName(split);
}
resendDisguise =
!DisguiseConfig.isScoreboardDisguiseNames() || isStaticName(name) || isStaticName(getName()) ||
resendDisguise = !DisguiseConfig.isScoreboardNames() || isStaticName(name) || isStaticName(getName()) ||
resendDisguise;
if (resendDisguise) {
if (stopDisguise()) {
if (getName().isEmpty() && !name.isEmpty()) {
setNameVisible(true);
setNameVisible(true, true);
} else if (!getName().isEmpty() && name.isEmpty()) {
setNameVisible(false);
setNameVisible(false, true);
}
playerName = name;
@ -258,15 +292,16 @@ public class PlayerDisguise extends TargetedDisguise {
}
} else {
if (getName().isEmpty() && !name.isEmpty() && !isNameVisible()) {
setNameVisible(true);
setNameVisible(true, true);
} else if (!getName().isEmpty() && name.isEmpty() && isNameVisible()) {
setNameVisible(false);
setNameVisible(false, true);
} else {
DisguiseUtilities.updateExtendedName(this);
}
playerName = name;
}
}
if (isDisplayedInTab()) {
PacketContainer addTab = DisguiseUtilities.getTabPacket(this, PlayerInfoAction.UPDATE_DISPLAY_NAME);
@ -291,12 +326,11 @@ public class PlayerDisguise extends TargetedDisguise {
setScoreboardName(split);
}
if (name.isEmpty()) {
setNameVisible(false);
} else {
setNameVisible(true);
if (DisguiseConfig.isScoreboardNames()) {
setMultiName(DisguiseUtilities.splitNewLine(name));
}
setNameVisible(!name.isEmpty(), true);
playerName = name;
if (gameProfile != null) {
@ -310,19 +344,23 @@ public class PlayerDisguise extends TargetedDisguise {
}
public PlayerDisguise setSkin(String newSkin) {
if (newSkin != null && newSkin.length() > 70) {
if (newSkin != null && newSkin.length() > 70 && newSkin.startsWith("{") && newSkin.endsWith("}")) {
try {
return setSkin(DisguiseUtilities.getGson().fromJson(newSkin, WrappedGameProfile.class));
}
catch (Exception ex) {
if (!"12345".equals("%%__USER__%%")) {
throw new IllegalArgumentException(String.format(
"The skin %s is too long to be a playername, but cannot be parsed to a GameProfile!",
newSkin));
"The skin %s is too long to normally be a playername, but cannot be parsed to a " +
"GameProfile!", newSkin));
}
}
}
if (newSkin != null && newSkin.length() > 16) {
newSkin = null;
}
String oldSkin = skinToUse;
skinToUse = newSkin;
@ -376,8 +414,6 @@ public class PlayerDisguise extends TargetedDisguise {
return this;
}
Validate.notEmpty(gameProfile.getName(), "Name must be set");
currentLookup = null;
this.skinToUse = gameProfile.getName();

View File

@ -22,7 +22,7 @@ public class DroppedItemWatcher extends FlagWatcher {
setData(MetaIndex.DROPPED_ITEM, item);
sendData(MetaIndex.DROPPED_ITEM);
if (!getDisguise().isCustomName()) {
if (!getDisguise().isCustomDisguiseName()) {
getDisguise().setDisguiseName(TranslateType.DISGUISES.get(DisguiseType.DROPPED_ITEM.toReadable()) + " " +
TranslateType.DISGUISE_OPTIONS_PARAMETERS
.get(ReflectionManager.toReadable((item == null ? Material.AIR : item.getType()).name())));

View File

@ -87,7 +87,7 @@ public class FallingBlockWatcher extends FlagWatcher {
this.block = block;
if (!getDisguise().isCustomName()) {
if (!getDisguise().isCustomDisguiseName()) {
getDisguise().setDisguiseName(TranslateType.DISGUISE_OPTIONS_PARAMETERS.get("Block") + " " +
TranslateType.DISGUISE_OPTIONS_PARAMETERS
.get(ReflectionManager.toReadable(block.getType().name())));

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,13 +583,20 @@ 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());
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)
public void onVehicleLeave(VehicleExitEvent event) {

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' " +

View File

@ -66,13 +66,14 @@ SaveDisguises:
Players: false
Entities: false
# Do names go beyond the 16 char limit for player disguises?
ExtendedNames: false
# Do names resolve into scoreboard teams so changing the player name is flawless?
# This will only work properly for names 28 chars or less in length.
# Notch [DragonSlayer lvl: 28]
# It's recommended to leave this on unless you need it off
ScoreboardNames: true
# There are four options you can use
# VANILLA - Names are limited to 16 chars but can't be changed without resending disguise
# TEAMS - Names are limited to 32 chars but can be changed willy nilly
# EXTENDED - Names are limited to 48 chars but can't be changed without resending disguise
# ARMORSTANDS - Names are limited to 256 chars, uses a mix of armorstands and teams to do this. Slightly hacky.
# Downside of armorstand names is that there's a chance of it becoming desynced from the player disguise
PlayerNames: TEAMS
# How many ticks before tab packet is sent to remove from tablist. This shouldn't need to be touched
TablistRemoveDelay: 2

View File

@ -121,6 +121,8 @@ permissions:
libsdisguises.noactionbar:
description: Hides the action bar even if enabled in config
default: false
libsdisguises.multiname:
description: Allows the command user to set names on different heights
libsdisguises.seecmd:
description: See all commands in tab-completion
default: true