Armorstand names now adapt to basic entity sizes, and player sneaking. Doesn't handle poses.

This commit is contained in:
libraryaddict 2020-05-09 21:57:07 +12:00
parent 93eef36c58
commit e6b7651571
No known key found for this signature in database
GPG Key ID: 052E4FBCD257AEA4
13 changed files with 171 additions and 33 deletions

View File

@ -116,6 +116,8 @@ public abstract class Disguise {
return DisguiseUtilities.reverse(multiName);
}
public abstract double getHeight();
public void setMultiName(String... name) {
if (name.length == 1 && name[0].isEmpty()) {
name = new String[0];

View File

@ -47,10 +47,12 @@ public class FlagWatcher {
private HashMap<Integer, Object> entityValues = new HashMap<>();
private LibsEquipment equipment;
private boolean hasDied;
@Getter
private boolean[] modifiedEntityAnimations = new boolean[8];
private transient List<WrappedWatchableObject> watchableObjects;
private boolean sleeping;
private boolean swimming;
private transient boolean previouslySneaking;
public FlagWatcher(Disguise disguise) {
this.disguise = (TargetedDisguise) disguise;
@ -150,8 +152,10 @@ public class FlagWatcher {
}
if (value != null) {
if (isEntityAnimationsAdded() && id == 0) {
if (isEntityAnimationsAdded() && id == MetaIndex.ENTITY_META.getIndex()) {
value = addEntityAnimations((byte) value, (byte) watch.getValue());
doSneakCheck((Byte) value);
}
boolean isDirty = watch.getDirtyState();
@ -175,6 +179,10 @@ public class FlagWatcher {
if (!isDirty) {
watch.setDirtyState(false);
}
if (id == MetaIndex.ENTITY_META.getIndex()) {
doSneakCheck((Byte) watch.getValue());
}
}
newList.add(watch);
@ -207,7 +215,7 @@ public class FlagWatcher {
getDisguise().getEntity() instanceof Player) {
for (WrappedWatchableObject watch : newList) {
// Its a health packet
if (watch.getIndex() == 6) {
if (watch.getIndex() == MetaIndex.LIVING_HEALTH.getIndex()) {
Object value = watch.getValue();
if (value instanceof Float) {
@ -236,6 +244,21 @@ public class FlagWatcher {
return newList;
}
private void doSneakCheck(byte value) {
if (getModifiedEntityAnimations()[1] || !getDisguise().isPlayerDisguise()) {
return;
}
boolean sneak = (value & 1 << 1) != 0;
if (sneak == previouslySneaking) {
return;
}
previouslySneaking = sneak;
updateNameHeight();
}
@NmsAddedIn(val = NmsVersion.v1_14)
public EntityPose getEntityPose() {
return getData(MetaIndex.ENTITY_POSE);
@ -255,6 +278,55 @@ public class FlagWatcher {
getEquipment().setArmorContents(items);
}
protected void updateNameHeight() {
if (!getDisguise().isDisguiseInUse()) {
return;
}
if (!DisguiseConfig.isArmorstandsName()) {
return;
}
if (!getDisguise().isPlayerDisguise() && !DisguiseConfig.isOverrideCustomNames()) {
return;
}
if (getDisguise().getEntity() == null) {
return;
}
// Not using this as it's "Smooth" and looks a bit weirder
/*int[] ids = getDisguise().getArmorstandIds();
ArrayList<PacketContainer> packets = new ArrayList<>();
Location loc = getDisguise().getEntity().getLocation();
for (int i = 0; i < getDisguise().getMultiNameLength(); i++) {
PacketContainer packet = new PacketContainer(Server.ENTITY_TELEPORT);
packet.getIntegers().write(0, ids[i]);
StructureModifier<Double> doubles = packet.getDoubles();
doubles.write(0, loc.getX());
doubles.write(1, loc.getY() + getDisguise().getHeight() + (0.28 * i));
doubles.write(2, loc.getZ());
packets.add(packet);
}*/
ArrayList<PacketContainer> packets = DisguiseUtilities.getNamePackets(getDisguise(), new String[0]);
try {
for (Player player : DisguiseUtilities.getPerverts(getDisguise())) {
for (PacketContainer packet : packets) {
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet);
}
}
}
catch (InvocationTargetException e) {
e.printStackTrace();
}
}
public String getCustomName() {
if (!getDisguise().isPlayerDisguise() && DisguiseConfig.isOverrideCustomNames() &&
DisguiseConfig.isArmorstandsName()) {
@ -266,6 +338,10 @@ public class FlagWatcher {
}
if (!NmsVersion.v1_13.isSupported()) {
if (!hasValue(MetaIndex.ENTITY_CUSTOM_NAME_OLD)) {
return null;
}
return getData(MetaIndex.ENTITY_CUSTOM_NAME_OLD);
}
@ -470,6 +546,10 @@ public class FlagWatcher {
setEntityFlag(1, setSneaking);
sendData(MetaIndex.ENTITY_META);
if (getDisguise().isPlayerDisguise()) {
updateNameHeight();
}
if (NmsVersion.v1_14.isSupported()) {
updatePose();
}

View File

@ -4,6 +4,7 @@ import me.libraryaddict.disguise.disguisetypes.watchers.DroppedItemWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.FallingBlockWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.PaintingWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.SplashPotionWatcher;
import me.libraryaddict.disguise.utilities.DisguiseValues;
import org.bukkit.Art;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
@ -63,6 +64,17 @@ public class MiscDisguise extends TargetedDisguise {
apply(id, new ItemStack(Material.STONE));
}
@Override
public double getHeight() {
DisguiseValues values = DisguiseValues.getDisguiseValues(getType());
if (values == null || values.getAdultBox() == null) {
return 0;
}
return values.getAdultBox().getY();
}
private void apply(int id, ItemStack itemStack) {
createDisguise();

View File

@ -1,8 +1,7 @@
package me.libraryaddict.disguise.disguisetypes;
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.disguisetypes.watchers.*;
import me.libraryaddict.disguise.utilities.DisguiseValues;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
@ -30,6 +29,30 @@ public class MobDisguise extends TargetedDisguise {
createDisguise();
}
@Override
public double getHeight() {
DisguiseValues values = DisguiseValues.getDisguiseValues(getType());
if (values == null || values.getAdultBox() == null) {
return 0;
}
if (!isAdult() && values.getBabyBox() != null) {
return values.getBabyBox().getY();
}
if (getWatcher() != null) {
if (getType() == DisguiseType.ARMOR_STAND) {
return (((ArmorStandWatcher) getWatcher()).isSmall() ? values.getBabyBox() : values.getAdultBox())
.getY();
} else if (getType() == DisguiseType.SLIME || getType() == DisguiseType.MAGMA_CUBE) {
return 0.51 * (0.255 * ((SlimeWatcher) getWatcher()).getSize());
}
}
return values.getAdultBox().getY();
}
@Override
public MobDisguise addPlayer(Player player) {
return (MobDisguise) super.addPlayer(player);

View File

@ -38,6 +38,11 @@ public class ModdedDisguise extends TargetedDisguise {
createDisguise();
}
@Override
public double getHeight() {
return 0;
}
@Override
public boolean isCustomDisguise() {
return true;

View File

@ -83,6 +83,19 @@ public class PlayerDisguise extends TargetedDisguise {
createDisguise();
}
@Override
public double getHeight() {
if (getWatcher() == null) {
return 1.8;
}
if (getEntity() == null || getWatcher().getModifiedEntityAnimations()[1]) {
return getWatcher().isSneaking() ? 1.5 : 1.8;
}
return getEntity() instanceof Player && ((Player) getEntity()).isSneaking() ? 1.5 : 1.8;
}
@Deprecated
public DisguiseUtilities.DScoreTeam getScoreboardName() {
if (!DisguiseConfig.isScoreboardNames()) {

View File

@ -25,7 +25,13 @@ public class SlimeWatcher extends InsentientWatcher {
size = 50;
}
if (hasValue(MetaIndex.SLIME_SIZE) && getData(MetaIndex.SLIME_SIZE) == size) {
return;
}
setData(MetaIndex.SLIME_SIZE, size);
sendData(MetaIndex.SLIME_SIZE);
updateNameHeight();
}
}

View File

@ -22,7 +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.ArmorStandWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.ZombieWatcher;
import me.libraryaddict.disguise.utilities.json.*;
import me.libraryaddict.disguise.utilities.mineskin.MineSkinAPI;
@ -2323,6 +2323,8 @@ public class DisguiseUtilities {
destroyIds = Arrays.copyOfRange(standIds, newNames.length, internalOldNames.length);
}
double height = disguise.getHeight();
for (int i = 0; i < newNames.length; i++) {
if (i < internalOldNames.length) {
if (newNames[i].equals(internalOldNames[i]) || newNames[i].isEmpty()) {
@ -2358,19 +2360,19 @@ public class DisguiseUtilities {
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(1, loc.getY() + height + (0.28 * i));
packet.getDoubles().write(2, loc.getZ());
packets.add(packet);
WrappedDataWatcher watcher = new WrappedDataWatcher();
for (MetaIndex index : MetaIndex.getMetaIndexes(LivingWatcher.class)) {
for (MetaIndex index : MetaIndex.getMetaIndexes(ArmorStandWatcher.class)) {
Object val = index.getDefault();
if (index == MetaIndex.ENTITY_META) {
val = (byte) 32;
} else if (index == MetaIndex.ARMORSTAND_META) {
val = (byte) 17;
val = (byte) 19;
} else if (index == MetaIndex.ENTITY_CUSTOM_NAME) {
val = Optional.of(WrappedChatComponent.fromText(newNames[i]));
} else if (index == MetaIndex.ENTITY_CUSTOM_NAME_OLD) {
@ -2387,7 +2389,7 @@ public class DisguiseUtilities {
if (NmsVersion.v1_15.isSupported()) {
PacketContainer metaPacket = ProtocolLibrary.getProtocolManager()
.createPacketConstructor(PacketType.Play.Server.ENTITY_METADATA, 0, watcher, true)
.createPacketConstructor(PacketType.Play.Server.ENTITY_METADATA, standIds[i], watcher, true)
.createPacket(standIds[i], watcher, true);
packets.add(metaPacket);

View File

@ -15,19 +15,12 @@ public class DisguiseValues {
return values.get(type);
}
public static Class getNmsEntityClass(DisguiseType type) {
return getDisguiseValues(type).getNmsEntityClass();
}
private FakeBoundingBox adultBox;
private FakeBoundingBox babyBox;
private float[] entitySize;
private double maxHealth;
private Class nmsEntityClass;
private final double maxHealth;
public DisguiseValues(DisguiseType type, Class classType, double maxHealth) {
public DisguiseValues(DisguiseType type, double maxHealth) {
values.put(type, this);
nmsEntityClass = classType;
this.maxHealth = maxHealth;
}
@ -50,8 +43,4 @@ public class DisguiseValues {
public double getMaxHealth() {
return maxHealth;
}
public Class getNmsEntityClass() {
return nmsEntityClass;
}
}

View File

@ -49,6 +49,7 @@ public class PacketHandlerMovement implements IPacketHandler {
}
ArrayList<PacketContainer> toAdd = new ArrayList<>();
double height = disguise.getHeight();
for (PacketContainer packet : packets.getPackets()) {
for (int i = 0; i < len; i++) {
@ -57,7 +58,7 @@ public class PacketHandlerMovement implements IPacketHandler {
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));
packet2.getDoubles().write(1, packet2.getDoubles().read(1) + height + (0.28 * i));
}
toAdd.add(packet2);

View File

@ -48,8 +48,10 @@ public class DisguiseParser {
disguise = new MiscDisguise(type);
} else if (type.isMob()) {
disguise = new MobDisguise(type);
} else {
} else if (type.isPlayer()) {
disguise = new PlayerDisguise("Foobar");
} else {
continue;
}
FlagWatcher watcher = type.getWatcherClass().getConstructor(Disguise.class).newInstance(disguise);
@ -217,15 +219,14 @@ public class DisguiseParser {
}
private static void addWatcherDefault(Method setMethod, Method getMethod, Object object) {
if (defaultWatcherValues.containsKey(setMethod)) {
Object dObj = defaultWatcherValues.get(setMethod).getValue();
if (!Objects.deepEquals(dObj, object)) {
throw new IllegalStateException(String.format(
"%s has conflicting values! This means it expected the same value again but received a " +
"different value on a different disguise! %s is not the same as %s!", setMethod.getName(), object,
dObj));
"different value on a different disguise! %s is not the same as %s!",
setMethod.getName(), object, dObj));
}
return;

View File

@ -1722,7 +1722,7 @@ public class ReflectionManager {
try {
if (disguiseType == DisguiseType.UNKNOWN || disguiseType.isCustom()) {
DisguiseValues disguiseValues = new DisguiseValues(disguiseType, null, 0);
DisguiseValues disguiseValues = new DisguiseValues(disguiseType, 0);
disguiseValues.setAdultBox(new FakeBoundingBox(0, 0, 0));
@ -1763,7 +1763,7 @@ public class ReflectionManager {
}
}
DisguiseValues disguiseValues = new DisguiseValues(disguiseType, nmsEntity.getClass(),
DisguiseValues disguiseValues = new DisguiseValues(disguiseType,
bukkitEntity instanceof Damageable ? ((Damageable) bukkitEntity).getMaxHealth() : 0);
WrappedDataWatcher watcher = WrappedDataWatcher.getEntityWatcher(bukkitEntity);
@ -1841,9 +1841,11 @@ public class ReflectionManager {
((Zombie) bukkitEntity).setBaby(true);
disguiseValues.setBabyBox(ReflectionManager.getBoundingBox(bukkitEntity));
}
} else if (bukkitEntity instanceof ArmorStand) {
((ArmorStand) bukkitEntity).setSmall(true);
//disguiseValues.setEntitySize(ReflectionManager.getSize(bukkitEntity));
disguiseValues.setBabyBox(ReflectionManager.getBoundingBox(bukkitEntity));
}
}
catch (SecurityException | IllegalArgumentException | IllegalAccessException | FieldAccessException ex) {
DisguiseUtilities.getLogger()

View File

@ -72,8 +72,10 @@ SaveDisguises:
# 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
# And names will always display even if the entity is invisible using potion effects
PlayerNames: TEAMS
# If doing armorstands, should CustomNames be overridden to use armorstands too?
# If doing ARMORSTANDS in the above option, should CustomNames be overridden to use armorstands too?
# This allows multiline names
OverrideCustomNames: true
# How many ticks before tab packet is sent to remove from tablist. This shouldn't need to be touched