LibsDisguises/plugin/src/main/java/me/libraryaddict/disguise/utilities/packets/packetlisteners/PacketListenerViewSelfDisgu...

215 lines
9.7 KiB
Java

package me.libraryaddict.disguise.utilities.packets.packetlisteners;
import com.comphenix.protocol.PacketType.Play.Server;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.wrappers.EnumWrappers;
import com.comphenix.protocol.wrappers.WrappedDataValue;
import com.comphenix.protocol.wrappers.WrappedWatchableObject;
import me.libraryaddict.disguise.DisguiseAPI;
import me.libraryaddict.disguise.LibsDisguises;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
import me.libraryaddict.disguise.disguisetypes.PlayerDisguise;
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
import me.libraryaddict.disguise.utilities.LibsPremium;
import me.libraryaddict.disguise.utilities.packets.LibsPackets;
import me.libraryaddict.disguise.utilities.packets.PacketsManager;
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
import me.libraryaddict.disguise.utilities.reflection.ReflectionManager;
import me.libraryaddict.disguise.utilities.reflection.WatcherValue;
import me.libraryaddict.disguise.utilities.sounds.SoundGroup;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class PacketListenerViewSelfDisguise extends PacketAdapter {
public PacketListenerViewSelfDisguise(LibsDisguises plugin) {
super(plugin, ListenerPriority.HIGH, NmsVersion.v1_20_R2.isSupported() ? Server.SPAWN_ENTITY : Server.NAMED_ENTITY_SPAWN,
Server.ATTACH_ENTITY, Server.REL_ENTITY_MOVE, Server.REL_ENTITY_MOVE_LOOK, Server.ENTITY_LOOK, Server.ENTITY_TELEPORT,
Server.ENTITY_HEAD_ROTATION, Server.ENTITY_METADATA, Server.ENTITY_EQUIPMENT, Server.ANIMATION, Server.ENTITY_EFFECT,
Server.ENTITY_VELOCITY, Server.UPDATE_ATTRIBUTES, Server.ENTITY_STATUS);
}
@Override
public void onPacketSending(final PacketEvent event) {
if (event.isCancelled()) {
return;
}
try {
final Player observer = event.getPlayer();
if (observer.getName().contains("UNKNOWN[")) {// If the player is temporary
return;
}
PacketContainer packet = event.getPacket();
// If packet isn't meant for the disguised player's self disguise
if (packet.getIntegers().read(0) != observer.getEntityId()) {
return;
}
if (!DisguiseAPI.isSelfDisguised(observer)) {
return;
}
final Disguise disguise = DisguiseAPI.getDisguise(observer, observer);
if (disguise == null) {
return;
}
// Here I grab the packets to convert them to, So I can display them as if the disguise sent them.
LibsPackets transformed = PacketsManager.getPacketsHandler().transformPacket(packet, disguise, observer, observer);
if (transformed.isUnhandled()) {
transformed.addPacket(packet);
}
LibsPackets selfTransformed = new LibsPackets(disguise);
selfTransformed.setSkinHandling(transformed.isSkinHandling());
for (PacketContainer newPacket : transformed.getPackets()) {
if (newPacket.getType() != Server.PLAYER_INFO && newPacket.getType() != Server.ENTITY_DESTROY &&
newPacket.getIntegers().read(0) == observer.getEntityId()) {
if (newPacket == packet) {
newPacket = newPacket.shallowClone();
}
newPacket.getIntegers().write(0, DisguiseAPI.getSelfDisguiseId());
}
selfTransformed.addPacket(newPacket);
}
for (Map.Entry<Integer, ArrayList<PacketContainer>> entry : transformed.getDelayedPacketsMap().entrySet()) {
for (PacketContainer newPacket : entry.getValue()) {
if (newPacket == packet) {
newPacket = newPacket.shallowClone();
}
if (newPacket.getType() != Server.PLAYER_INFO && newPacket.getType() != Server.ENTITY_DESTROY) {
newPacket.getIntegers().write(0, DisguiseAPI.getSelfDisguiseId());
}
selfTransformed.addDelayedPacket(newPacket, entry.getKey());
}
}
if (disguise.isPlayerDisguise()) {
LibsDisguises.getInstance().getSkinHandler().handlePackets(observer, (PlayerDisguise) disguise, selfTransformed);
}
for (PacketContainer newPacket : selfTransformed.getPackets()) {
ProtocolLibrary.getProtocolManager().sendServerPacket(observer, newPacket, false);
}
selfTransformed.sendDelayed(observer);
if (event.getPacketType() == Server.ENTITY_METADATA) {
if (!LibsPremium.getPluginInformation().isPremium() || LibsPremium.getPaidInformation() != null ||
LibsPremium.getPluginInformation().getBuildNumber().matches("#\\d+")) {
event.setPacket(packet = packet.deepClone());
}
if (NmsVersion.v1_19_R2.isSupported()) {
for (WrappedDataValue watch : packet.getDataValueCollectionModifier().read(0)) {
if (watch.getIndex() != 0) {
continue;
}
byte b = (byte) watch.getRawValue();
// Add invisibility, remove glowing
byte a = (byte) ((b | 1 << 5) & ~(1 << 6));
watch.setValue(a);
}
} else {
for (WrappedWatchableObject watch : packet.getWatchableCollectionModifier().read(0)) {
if (watch.getIndex() != 0) {
continue;
}
byte b = (byte) watch.getRawValue();
// Add invisibility, remove glowing
byte a = (byte) ((b | 1 << 5) & ~(1 << 6));
watch.setValue(a);
}
}
} else if (event.getPacketType() == Server.NAMED_ENTITY_SPAWN || event.getPacketType() == Server.SPAWN_ENTITY) {
event.setCancelled(true);
List<WatcherValue> watchableList = new ArrayList<>();
byte b = 1 << 5;
if (observer.isSprinting()) {
b = (byte) (b | 1 << 3);
}
WatcherValue watch = new WatcherValue(MetaIndex.ENTITY_META, b);
watchableList.add(watch);
PacketContainer metaPacket = ReflectionManager.getMetadataPacket(observer.getEntityId(), watchableList);
ProtocolLibrary.getProtocolManager().sendServerPacket(observer, metaPacket);
} else if (event.getPacketType() == Server.ANIMATION) {
if (packet.getIntegers().read(1) != 2) {
event.setCancelled(true);
}
} else if (event.getPacketType() == Server.ATTACH_ENTITY || event.getPacketType() == Server.REL_ENTITY_MOVE ||
event.getPacketType() == Server.REL_ENTITY_MOVE_LOOK || event.getPacketType() == Server.ENTITY_LOOK ||
event.getPacketType() == Server.ENTITY_TELEPORT || event.getPacketType() == Server.ENTITY_HEAD_ROTATION ||
event.getPacketType() == Server.ENTITY_EQUIPMENT) {
event.setCancelled(true);
} else if (event.getPacketType() == Server.ENTITY_STATUS) {
if (disguise.isSelfDisguiseSoundsReplaced() && !disguise.getType().isPlayer() && packet.getBytes().read(0) == 2) {
event.setCancelled(true);
// As of 1.19.3, no sound is sent but instead the client is expected to play a hurt sound on entity status effect
if (NmsVersion.v1_19_R2.isSupported()) {
SoundGroup group = SoundGroup.getGroup(disguise);
Object sound = group.getSound(SoundGroup.SoundType.HURT);
if (sound != null) {
PacketContainer newPacket = new PacketContainer(Server.ENTITY_SOUND);
StructureModifier mods = newPacket.getModifier();
mods.write(0, sound);
// Category
mods.write(2, DisguiseAPI.getSelfDisguiseId());
mods.write(3, 1f);
mods.write(4, 1f);
mods.write(5, (long) (Math.random() * 1000L));
newPacket.getSoundCategories().write(0, EnumWrappers.SoundCategory.MASTER);
ProtocolLibrary.getProtocolManager().sendServerPacket(observer, newPacket);
}
}
}
} else if (event.getPacketType() == Server.ENTITY_VELOCITY && !DisguiseUtilities.isPlayerVelocity(observer)) {
// The player only sees velocity changes when there is a velocity event. As the method claims there
// was no velocity event...
event.setCancelled(true);
// Clear old velocity, this should only occur once.
DisguiseUtilities.clearPlayerVelocity(observer);
}
} catch (Throwable ex) {
event.setCancelled(true);
ex.printStackTrace();
}
}
}