mirror of
https://github.com/TotalFreedomMC/TF-LibsDisguises.git
synced 2025-02-05 06:12:48 +00:00
Changes for the armor packets
This commit is contained in:
parent
5208424373
commit
db6660578a
7 changed files with 145 additions and 77 deletions
|
@ -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!");
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue