Changes for the armor packets

This commit is contained in:
libraryaddict 2020-01-30 12:01:49 +13:00
parent 5208424373
commit db6660578a
No known key found for this signature in database
GPG key ID: 052E4FBCD257AEA4
7 changed files with 145 additions and 77 deletions

View file

@ -82,6 +82,15 @@ public class DisguiseConfig {
private static UpdatesBranch updatesBranch = UpdatesBranch.SAME_BUILDS;
private static int playerDisguisesTablistExpires;
private static boolean dynamicExpiry;
private static boolean playerHideArmor;
public static boolean isPlayerHideArmor() {
return playerHideArmor;
}
public static void setPlayerHideArmor(boolean playerHiddenArmor) {
playerHideArmor = playerHiddenArmor;
}
public static boolean isDynamicExpiry() {
return dynamicExpiry;
@ -336,6 +345,7 @@ public class DisguiseConfig {
setUUIDGeneratedVersion(config.getInt("UUIDVersion"));
setPlayerDisguisesTablistExpires(config.getInt("PlayerDisguisesTablistExpires"));
setDynamicExpiry(config.getBoolean("DynamicExpiry"));
setPlayerHideArmor(config.getBoolean("PlayerHideArmor"));
if (!LibsPremium.isPremium() && (isSavePlayerDisguises() || isSaveEntityDisguises())) {
DisguiseUtilities.getLogger().warning("You must purchase the plugin to use saved disguises!");

View file

@ -5,6 +5,7 @@ import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.PacketContainer;
import me.libraryaddict.disguise.LibsDisguises;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@ -20,6 +21,7 @@ public class LibsPackets {
private boolean isSpawnPacket;
private Disguise disguise;
private boolean doNothing;
private int removeMetaAt = -1;
public LibsPackets(Disguise disguise) {
this.disguise = disguise;
@ -29,6 +31,10 @@ public class LibsPackets {
doNothing = true;
}
public void setRemoveMetaAt(int tick) {
removeMetaAt = tick;
}
public boolean isUnhandled() {
return doNothing;
}
@ -70,18 +76,17 @@ public class LibsPackets {
public void sendDelayed(final Player observer) {
Iterator<Map.Entry<Integer, ArrayList<PacketContainer>>> itel = delayedPackets.entrySet().iterator();
Optional<Integer> largestTick = delayedPackets.keySet().stream().max(Integer::compare);
if (!largestTick.isPresent()) {
return;
}
while (itel.hasNext()) {
Map.Entry<Integer, ArrayList<PacketContainer>> entry = itel.next();
// If this is the last delayed packet
final boolean isRemoveCancel = isSpawnPacket && largestTick.get().equals(entry.getKey());
final boolean isRemoveCancel = isSpawnPacket && entry.getKey() >= removeMetaAt && removeMetaAt >= 0;
Bukkit.getScheduler().scheduleSyncDelayedTask(LibsDisguises.getInstance(), () -> {
if (isRemoveCancel) {
PacketsManager.getPacketsHandler().removeCancel(disguise, observer);
}
try {
for (PacketContainer packet : entry.getValue()) {
ProtocolLibrary.getProtocolManager().sendServerPacket(observer, packet, false);
@ -90,10 +95,6 @@ public class LibsPackets {
catch (InvocationTargetException e) {
e.printStackTrace();
}
if (isRemoveCancel) {
PacketsManager.getPacketsHandler().removeCancel(disguise, observer);
}
}, entry.getKey());
}
}

View file

@ -31,7 +31,7 @@ public class PacketsHandler {
packetHandlers.add(new PacketHandlerBed());
packetHandlers.add(new PacketHandlerCollect());
packetHandlers.add(new PacketHandlerEntityStatus());
packetHandlers.add(new PacketHandlerEquipment());
packetHandlers.add(new PacketHandlerEquipment(this));
packetHandlers.add(new PacketHandlerHeadRotation());
packetHandlers.add(new PacketHandlerMetadata(this));
packetHandlers.add(new PacketHandlerMovement());

View file

@ -6,8 +6,11 @@ import com.comphenix.protocol.wrappers.WrappedDataWatcher;
import com.comphenix.protocol.wrappers.WrappedWatchableObject;
import me.libraryaddict.disguise.DisguiseConfig;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
import me.libraryaddict.disguise.utilities.packets.IPacketHandler;
import me.libraryaddict.disguise.utilities.packets.LibsPackets;
import me.libraryaddict.disguise.utilities.packets.PacketsHandler;
import me.libraryaddict.disguise.utilities.reflection.ReflectionManager;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
@ -22,6 +25,12 @@ import java.util.List;
* Created by libraryaddict on 3/01/2019.
*/
public class PacketHandlerEquipment implements IPacketHandler {
private PacketsHandler packetsHandler;
public PacketHandlerEquipment(PacketsHandler packetsHandler) {
this.packetsHandler = packetsHandler;
}
@Override
public PacketType[] getHandledPackets() {
return new PacketType[]{PacketType.Play.Server.ENTITY_EQUIPMENT};
@ -30,6 +39,17 @@ public class PacketHandlerEquipment implements IPacketHandler {
@Override
public void handle(Disguise disguise, PacketContainer sentPacket, LibsPackets packets, Player observer,
Entity entity) {
if (DisguiseConfig.isPlayerHideArmor() && packetsHandler.isCancelMeta(disguise, observer)) {
packets.clear();
PacketContainer equipPacket = sentPacket.shallowClone();
packets.addPacket(equipPacket);
equipPacket.getModifier().write(2, ReflectionManager.getNmsItem(new ItemStack(Material.AIR)));
return;
}
// Else if the disguise is updating equipment
EquipmentSlot slot = ReflectionManager.createEquipmentSlot(packets.getPackets().get(0).getModifier().read(1));
@ -55,8 +75,8 @@ public class PacketHandlerEquipment implements IPacketHandler {
List<WrappedWatchableObject> list = new ArrayList<>();
if (DisguiseConfig.isMetadataPacketsEnabled()) {
WrappedWatchableObject watch = ReflectionManager
.createWatchable(0, WrappedDataWatcher.getEntityWatcher(entity).getByte(0));
WrappedWatchableObject watch = ReflectionManager.createWatchable(MetaIndex.ENTITY_META.getIndex(),
WrappedDataWatcher.getEntityWatcher(entity).getByte(0));
if (watch != null)
list.add(watch);

View file

@ -11,8 +11,8 @@ import me.libraryaddict.disguise.DisguiseConfig;
import me.libraryaddict.disguise.disguisetypes.*;
import me.libraryaddict.disguise.disguisetypes.watchers.FallingBlockWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.PlayerWatcher;
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
import me.libraryaddict.disguise.utilities.LibsPremium;
import me.libraryaddict.disguise.utilities.packets.IPacketHandler;
import me.libraryaddict.disguise.utilities.packets.LibsPackets;
import me.libraryaddict.disguise.utilities.packets.PacketsHandler;
@ -32,6 +32,7 @@ import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
/**
* Created by libraryaddict on 3/01/2019.
@ -56,6 +57,10 @@ public class PacketHandlerSpawn implements IPacketHandler {
packets.clear();
if (disguise.getType() == DisguiseType.UNKNOWN) {
return;
}
constructSpawnPackets(observer, packets, entity);
}
@ -69,36 +74,6 @@ public class PacketHandlerSpawn implements IPacketHandler {
disguise.setEntity(disguisedEntity);
}
// This sends the armor packets so that the player isn't naked.
// Please note it only sends the packets that wouldn't be sent normally
if (DisguiseConfig.isEquipmentPacketsEnabled()) {
for (EquipmentSlot slot : EquipmentSlot.values()) {
ItemStack itemstack = disguise.getWatcher().getItemStack(slot);
if (itemstack == null || itemstack.getType() == Material.AIR) {
continue;
}
if (disguisedEntity instanceof LivingEntity) {
ItemStack item = ReflectionManager.getEquipment(slot, disguisedEntity);
if (item != null && item.getType() != Material.AIR) {
continue;
}
}
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_EQUIPMENT);
StructureModifier<Object> mods = packet.getModifier();
mods.write(0, disguisedEntity.getEntityId());
mods.write(1, ReflectionManager.createEnumItemSlot(slot));
mods.write(2, ReflectionManager.getNmsItem(itemstack));
packets.addDelayedPacket(packet);
}
}
if (DisguiseConfig.isMiscDisguisesForLivingEnabled()) {
if (disguise.getWatcher() instanceof LivingWatcher) {
@ -180,30 +155,35 @@ public class PacketHandlerSpawn implements IPacketHandler {
} else if (disguise.getType().isPlayer()) {
PlayerDisguise playerDisguise = (PlayerDisguise) disguise;
String name = playerDisguise.getName();
WrappedGameProfile gameProfile = playerDisguise.getGameProfile();
WrappedGameProfile spawnProfile = playerDisguise.getGameProfile();
int entityId = disguisedEntity.getEntityId();
// Send player info along with the disguise
PacketContainer sendTab = new PacketContainer(PacketType.Play.Server.PLAYER_INFO);
if (!playerDisguise.isDisplayedInTab()) {
// Send player info along with the disguise
PacketContainer sendTab = new PacketContainer(PacketType.Play.Server.PLAYER_INFO);
if (!((PlayerDisguise) disguise).isDisplayedInTab()) {
// Add player to the list, necessary to spawn them
sendTab.getModifier().write(0, ReflectionManager.getEnumPlayerInfoAction(0));
List playerList = Collections
.singletonList(ReflectionManager.getPlayerInfoData(sendTab.getHandle(), gameProfile));
.singletonList(ReflectionManager.getPlayerInfoData(sendTab.getHandle(), spawnProfile));
sendTab.getModifier().write(1, playerList);
packets.addPacket(sendTab);
// Remove player from the list
PacketContainer deleteTab = sendTab.shallowClone();
deleteTab.getModifier().write(0, ReflectionManager.getEnumPlayerInfoAction(4));
packets.addDelayedPacket(deleteTab, DisguiseConfig.getPlayerDisguisesTablistExpires());
}
// Spawn the player
PacketContainer spawnPlayer = new PacketContainer(PacketType.Play.Server.NAMED_ENTITY_SPAWN);
spawnPlayer.getIntegers().write(0, entityId); // Id
spawnPlayer.getModifier().write(1, gameProfile.getUUID());
spawnPlayer.getModifier().write(1, spawnProfile.getUUID());
Location spawnAt = disguisedEntity.getLocation();
@ -240,15 +220,7 @@ public class PacketHandlerSpawn implements IPacketHandler {
packets.addPacket(spawnPlayer);
if (DisguiseConfig.isBedPacketsEnabled() && ((PlayerWatcher) disguise.getWatcher()).isSleeping()) {
PacketContainer[] bedPackets = DisguiseUtilities.getBedPackets(
loc.clone().subtract(0, DisguiseUtilities.getYModifier(disguisedEntity, disguise), 0),
observer.getLocation(), ((PlayerDisguise) disguise));
for (PacketContainer packet : bedPackets) {
packets.addPacket(packet);
}
} else if (!selfDisguise) {
if (!selfDisguise) {
// Teleport the player back to where he's supposed to be
PacketContainer teleportPacket = new PacketContainer(PacketType.Play.Server.ENTITY_TELEPORT);
@ -263,10 +235,8 @@ public class PacketHandlerSpawn implements IPacketHandler {
bytes.write(0, yaw);
bytes.write(1, pitch);
packets.addPacket(teleportPacket);
}
packets.addDelayedPacket(teleportPacket, 3);
if (!selfDisguise) {
// Send a metadata packet
PacketContainer metaPacket = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
@ -281,15 +251,8 @@ public class PacketHandlerSpawn implements IPacketHandler {
// Add a delay to remove the entry from 'cancelMeta'
packets.addDelayedPacket(metaPacket, 4);
}
// Remove player from the list
PacketContainer deleteTab = sendTab.shallowClone();
deleteTab.getModifier().write(0, ReflectionManager.getEnumPlayerInfoAction(4));
if (!((PlayerDisguise) disguise).isDisplayedInTab()) {
packets.addDelayedPacket(deleteTab, DisguiseConfig.getPlayerDisguisesTablistExpires());
packets.addDelayedPacket(metaPacket, 7);
packets.setRemoveMetaAt(7);
}
} else if (disguise.getType().isMob() || disguise.getType() == DisguiseType.ARMOR_STAND) {
Vector vec = disguisedEntity.getVelocity();
@ -336,8 +299,10 @@ public class PacketHandlerSpawn implements IPacketHandler {
.createSanitizedDataWatcher(WrappedDataWatcher.getEntityWatcher(disguisedEntity),
disguise.getWatcher()));
} else if (disguise.getType().isMisc()) {
int objectId = disguise.getType().getObjectId();
int data = ((MiscDisguise) disguise).getData();
double x = loc.getX();
double y = loc.getY();
double z = loc.getZ();
if (disguise.getType() == DisguiseType.FALLING_BLOCK) {
ItemStack block = ((FallingBlockWatcher) disguise.getWatcher()).getBlock();
@ -351,11 +316,14 @@ public class PacketHandlerSpawn implements IPacketHandler {
data = ((((int) loc.getYaw() % 360) + 720 + 45) / 90) % 4;
}
Object nmsEntity = ReflectionManager.getNmsEntity(disguisedEntity);
Object entityType = ReflectionManager.getEntityType(disguise.getType().getEntityType());
Object[] params = new Object[]{disguisedEntity.getEntityId(), disguisedEntity.getUniqueId(), x, y, z,
loc.getPitch(), loc.getYaw(), entityType, data,
ReflectionManager.getVec3D(disguisedEntity.getVelocity())};
PacketContainer spawnEntity = ProtocolLibrary.getProtocolManager()
.createPacketConstructor(PacketType.Play.Server.SPAWN_ENTITY, nmsEntity, objectId, data)
.createPacket(nmsEntity, objectId, data);
.createPacketConstructor(PacketType.Play.Server.SPAWN_ENTITY, params).createPacket(params);
packets.addPacket(spawnEntity);
// If it's not the same type, then highly likely they have different velocity settings which we'd want to
@ -399,5 +367,55 @@ public class PacketHandlerSpawn implements IPacketHandler {
packets.addPacket(newPacket);
}
// If armor must be sent because its currently not displayed and would've been sent normally
boolean delayedArmor =
DisguiseConfig.isPlayerHideArmor() && (disguise.isPlayerDisguise() && disguisedEntity != observer) &&
disguisedEntity instanceof LivingEntity;
// This sends the armor packets so that the player isn't naked.
if (DisguiseConfig.isEquipmentPacketsEnabled() || delayedArmor) {
for (EquipmentSlot slot : EquipmentSlot.values()) {
// Get what the disguise wants to show for its armor
ItemStack itemToSend = disguise.getWatcher().getItemStack(slot);
// If the disguise armor isn't visible
if (itemToSend == null || itemToSend.getType() == Material.AIR) {
// If we need to send the natural armor if possible
if (delayedArmor) {
itemToSend = ReflectionManager.getEquipment(slot, disguisedEntity);
// If natural armor isn't sent either
if (itemToSend == null || itemToSend.getType() == Material.AIR) {
continue;
}
} else {
// We don't need to send natural armor and disguise armor isn't visible
continue;
}
} else if (!delayedArmor && disguisedEntity instanceof LivingEntity) {
ItemStack item = ReflectionManager.getEquipment(slot, disguisedEntity);
// If the item was going to be sent anyways
if (item != null && item.getType() != Material.AIR) {
continue;
}
}
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_EQUIPMENT);
StructureModifier<Object> mods = packet.getModifier();
mods.write(0, disguisedEntity.getEntityId());
mods.write(1, ReflectionManager.createEnumItemSlot(slot));
mods.write(2, ReflectionManager.getNmsItem(itemToSend));
if (delayedArmor) {
packets.addDelayedPacket(packet, 7);
packets.setRemoveMetaAt(7);
} else {
packets.addDelayedPacket(packet);
}
}
}
}
}

View file

@ -16,6 +16,7 @@ import org.bukkit.entity.*;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
import org.bukkit.util.Vector;
import java.io.IOException;
import java.io.InputStream;
@ -976,6 +977,19 @@ public class ReflectionManager {
return null;
}
public static Object getVec3D(Vector vector) {
try {
Constructor c = getNmsConstructor("Vec3D", double.class, double.class, double.class);
return c.newInstance(vector.getX(), vector.getY(), vector.getZ());
}
catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static int getEntityType(Object nmsEntity) {
try {
Field entityTypesField = null;

View file

@ -197,7 +197,7 @@ ShowPlayerDisguisesInTab: false
# 2 seconds is normally long enough to load the skin properly, but sometimes the server needs longer
# This is in ticks, there are 20 ticks in every second. 40 ticks = 2 seconds. 200 ticks = 10 seconds.
# This option is ignored if 'ShowPlayerDisguisesInTab' is enabled.
PlayerDisguisesTablistExpires: 40
PlayerDisguisesTablistExpires: 60
# Don't like players able to set themselves invisible when using the disguise commands? Toggle this to true and no one can use setInvisible! Plugins can still use this however.
DisableInvisibility: false
@ -208,6 +208,11 @@ DisableInvisibility: false
# Expired message can be hidden with an empty translation message
DynamicExpiry: false
# Some players have issues with conflicting plugins where disguised entities will show the wrong armor
# This should be left alone unless you're trying to solve this issue. Such as MM and stone blocks.
# When true, the plugin will hide player disguises armor to prevent a minor visual bug for half a second
PlayerHideArmor: true
# This will help performance, especially with CPU
# Due to safety reasons, self disguises can never have their packets disabled.
PacketsEnabled: