2012-10-16 07:28:54 +02:00
|
|
|
/*
|
|
|
|
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
|
|
|
* Copyright (C) 2012 Kristian S. Stangeland
|
|
|
|
*
|
2015-06-19 19:14:20 +02:00
|
|
|
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
|
|
|
* GNU General Public License as published by the Free Software Foundation; either version 2 of
|
2012-10-16 07:28:54 +02:00
|
|
|
* the License, or (at your option) any later version.
|
|
|
|
*
|
2015-06-19 19:14:20 +02:00
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
|
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
2012-10-16 07:28:54 +02:00
|
|
|
* See the GNU General Public License for more details.
|
|
|
|
*
|
2015-06-19 19:14:20 +02:00
|
|
|
* You should have received a copy of the GNU General Public License along with this program;
|
|
|
|
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
2012-10-16 07:28:54 +02:00
|
|
|
* 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
package com.comphenix.protocol.events;
|
|
|
|
|
2022-07-24 17:02:56 +02:00
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.ObjectInputStream;
|
|
|
|
import java.io.ObjectOutputStream;
|
|
|
|
import java.lang.ref.WeakReference;
|
|
|
|
import java.util.EventObject;
|
|
|
|
|
2013-12-04 04:17:02 +01:00
|
|
|
import com.comphenix.protocol.PacketType;
|
2014-03-30 00:50:45 +01:00
|
|
|
import com.comphenix.protocol.ProtocolLibrary;
|
2012-10-16 07:28:54 +02:00
|
|
|
import com.comphenix.protocol.async.AsyncMarker;
|
2016-05-03 04:04:10 +02:00
|
|
|
import com.comphenix.protocol.error.PluginContext;
|
2014-03-30 00:50:45 +01:00
|
|
|
import com.comphenix.protocol.error.Report;
|
|
|
|
import com.comphenix.protocol.error.ReportType;
|
2022-03-08 04:09:04 +01:00
|
|
|
import com.comphenix.protocol.injector.temporary.TemporaryPlayer;
|
2014-03-22 23:21:57 +01:00
|
|
|
import com.google.common.base.Objects;
|
2013-07-17 03:52:27 +02:00
|
|
|
import com.google.common.base.Preconditions;
|
2014-03-30 00:50:45 +01:00
|
|
|
import com.google.common.collect.HashMultimap;
|
|
|
|
import com.google.common.collect.Multimaps;
|
|
|
|
import com.google.common.collect.SetMultimap;
|
2022-07-24 17:02:56 +02:00
|
|
|
|
2022-03-08 04:09:04 +01:00
|
|
|
import org.bukkit.Bukkit;
|
|
|
|
import org.bukkit.entity.Player;
|
|
|
|
import org.bukkit.event.Cancellable;
|
2012-10-16 07:28:54 +02:00
|
|
|
|
Packet filtering for bundled packets in 1.19.4 (#2258)
Since Minecraft 1.19.4, the protocol supports bundling consecutive packets to ensure the client processes them in one tick. However, Packet Events are not called for the individual packets in such a bundle in the current dev build of ProtocolLib. For example, no packet events are currently sent for the ENTITY_METADATA packet when an entity is first spawned as the packet is bundled with the ENTITY_SPAWN packet. However, if the entity metadata is changed later on, the event will be called.
This PR proposes to fix this by unpacking the bundled packets and invoking the packet filtering for each packet.
I also want to briefly explain how the bundling works. A bundle starts with a PACKET_DELIMITER (0x00, net.minecraft.network.protocol.BundleDelimiterPacket) packet followed by all packets that should be bundled and finished with another PACKET_DELIMITER (0x00). Within the Netty pipeline, this sequence is transformed into one synthesized packet found in net.minecraft.network.protocol.game.ClientboundBundlePacket, which is essentially just a list of packets. At the stage at which ProtocolLib injects into the clientbound netty pipeline, this packet has not been unpacked yet. Thus, we need to handle the ClientboundBundlePacket, which unfortunately is not registered in ProtocolLib. The fact that two different classes map to the same packet currently requires a dirty remapping in the packet structure modifier.
2023-03-26 04:08:31 +02:00
|
|
|
import javax.annotation.Nullable;
|
|
|
|
|
2014-03-30 00:50:45 +01:00
|
|
|
/**
|
2022-03-08 04:09:04 +01:00
|
|
|
* Represents a packet sending or receiving event. Changes to the packet will be reflected in the final version to be
|
|
|
|
* sent or received. It is also possible to cancel an event.
|
|
|
|
*
|
2014-03-30 00:50:45 +01:00
|
|
|
* @author Kristian
|
|
|
|
*/
|
2012-10-16 07:28:54 +02:00
|
|
|
public class PacketEvent extends EventObject implements Cancellable {
|
2022-03-08 04:09:04 +01:00
|
|
|
|
2014-03-30 00:50:45 +01:00
|
|
|
public static final ReportType REPORT_CHANGING_PACKET_TYPE_IS_CONFUSING = new ReportType(
|
|
|
|
"Plugin %s changed packet type from %s to %s in packet listener. This is confusing for other plugins! (Not an error, though!)");
|
2022-03-08 04:09:04 +01:00
|
|
|
|
2015-06-19 19:14:20 +02:00
|
|
|
private static final SetMultimap<PacketType, PacketType> CHANGE_WARNINGS =
|
2019-08-07 17:34:59 +02:00
|
|
|
Multimaps.synchronizedSetMultimap(HashMultimap.create());
|
2022-03-08 04:09:04 +01:00
|
|
|
|
2012-10-16 07:28:54 +02:00
|
|
|
/**
|
|
|
|
* Automatically generated by Eclipse.
|
|
|
|
*/
|
|
|
|
private static final long serialVersionUID = -5360289379097430620L;
|
2022-03-08 04:09:04 +01:00
|
|
|
// Network input and output handlers
|
|
|
|
NetworkMarker networkMarker;
|
2012-11-20 03:23:43 +01:00
|
|
|
private transient WeakReference<Player> playerReference;
|
2012-10-16 07:28:54 +02:00
|
|
|
private PacketContainer packet;
|
|
|
|
private boolean serverPacket;
|
|
|
|
private boolean cancel;
|
|
|
|
private AsyncMarker asyncMarker;
|
|
|
|
private boolean asynchronous;
|
2013-03-12 02:02:36 +01:00
|
|
|
// Whether or not a packet event is read only
|
|
|
|
private boolean readOnly;
|
2014-04-25 02:55:17 +02:00
|
|
|
private boolean filtered;
|
2022-03-08 04:09:04 +01:00
|
|
|
|
Packet filtering for bundled packets in 1.19.4 (#2258)
Since Minecraft 1.19.4, the protocol supports bundling consecutive packets to ensure the client processes them in one tick. However, Packet Events are not called for the individual packets in such a bundle in the current dev build of ProtocolLib. For example, no packet events are currently sent for the ENTITY_METADATA packet when an entity is first spawned as the packet is bundled with the ENTITY_SPAWN packet. However, if the entity metadata is changed later on, the event will be called.
This PR proposes to fix this by unpacking the bundled packets and invoking the packet filtering for each packet.
I also want to briefly explain how the bundling works. A bundle starts with a PACKET_DELIMITER (0x00, net.minecraft.network.protocol.BundleDelimiterPacket) packet followed by all packets that should be bundled and finished with another PACKET_DELIMITER (0x00). Within the Netty pipeline, this sequence is transformed into one synthesized packet found in net.minecraft.network.protocol.game.ClientboundBundlePacket, which is essentially just a list of packets. At the stage at which ProtocolLib injects into the clientbound netty pipeline, this packet has not been unpacked yet. Thus, we need to handle the ClientboundBundlePacket, which unfortunately is not registered in ProtocolLib. The fact that two different classes map to the same packet currently requires a dirty remapping in the packet structure modifier.
2023-03-26 04:08:31 +02:00
|
|
|
@Nullable
|
|
|
|
private PacketEvent bundle;
|
|
|
|
|
2012-10-16 07:28:54 +02:00
|
|
|
/**
|
|
|
|
* Use the static constructors to create instances of this event.
|
2022-03-08 04:09:04 +01:00
|
|
|
*
|
2012-10-16 07:28:54 +02:00
|
|
|
* @param source - the event source.
|
|
|
|
*/
|
|
|
|
public PacketEvent(Object source) {
|
|
|
|
super(source);
|
2014-04-25 02:55:17 +02:00
|
|
|
this.filtered = true;
|
2012-10-16 07:28:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private PacketEvent(Object source, PacketContainer packet, Player player, boolean serverPacket) {
|
Packet filtering for bundled packets in 1.19.4 (#2258)
Since Minecraft 1.19.4, the protocol supports bundling consecutive packets to ensure the client processes them in one tick. However, Packet Events are not called for the individual packets in such a bundle in the current dev build of ProtocolLib. For example, no packet events are currently sent for the ENTITY_METADATA packet when an entity is first spawned as the packet is bundled with the ENTITY_SPAWN packet. However, if the entity metadata is changed later on, the event will be called.
This PR proposes to fix this by unpacking the bundled packets and invoking the packet filtering for each packet.
I also want to briefly explain how the bundling works. A bundle starts with a PACKET_DELIMITER (0x00, net.minecraft.network.protocol.BundleDelimiterPacket) packet followed by all packets that should be bundled and finished with another PACKET_DELIMITER (0x00). Within the Netty pipeline, this sequence is transformed into one synthesized packet found in net.minecraft.network.protocol.game.ClientboundBundlePacket, which is essentially just a list of packets. At the stage at which ProtocolLib injects into the clientbound netty pipeline, this packet has not been unpacked yet. Thus, we need to handle the ClientboundBundlePacket, which unfortunately is not registered in ProtocolLib. The fact that two different classes map to the same packet currently requires a dirty remapping in the packet structure modifier.
2023-03-26 04:08:31 +02:00
|
|
|
this(source, packet, null, player, serverPacket, true, null);
|
2013-07-17 03:52:27 +02:00
|
|
|
}
|
2022-03-08 04:09:04 +01:00
|
|
|
|
|
|
|
private PacketEvent(Object source, PacketContainer packet, NetworkMarker marker, Player player, boolean serverPacket,
|
Packet filtering for bundled packets in 1.19.4 (#2258)
Since Minecraft 1.19.4, the protocol supports bundling consecutive packets to ensure the client processes them in one tick. However, Packet Events are not called for the individual packets in such a bundle in the current dev build of ProtocolLib. For example, no packet events are currently sent for the ENTITY_METADATA packet when an entity is first spawned as the packet is bundled with the ENTITY_SPAWN packet. However, if the entity metadata is changed later on, the event will be called.
This PR proposes to fix this by unpacking the bundled packets and invoking the packet filtering for each packet.
I also want to briefly explain how the bundling works. A bundle starts with a PACKET_DELIMITER (0x00, net.minecraft.network.protocol.BundleDelimiterPacket) packet followed by all packets that should be bundled and finished with another PACKET_DELIMITER (0x00). Within the Netty pipeline, this sequence is transformed into one synthesized packet found in net.minecraft.network.protocol.game.ClientboundBundlePacket, which is essentially just a list of packets. At the stage at which ProtocolLib injects into the clientbound netty pipeline, this packet has not been unpacked yet. Thus, we need to handle the ClientboundBundlePacket, which unfortunately is not registered in ProtocolLib. The fact that two different classes map to the same packet currently requires a dirty remapping in the packet structure modifier.
2023-03-26 04:08:31 +02:00
|
|
|
boolean filtered, @Nullable PacketEvent bundleEvent) {
|
2012-10-16 07:28:54 +02:00
|
|
|
super(source);
|
2023-04-11 15:13:03 +02:00
|
|
|
if(packet == null) {
|
|
|
|
throw new IllegalArgumentException("packet cannot be null");
|
|
|
|
}
|
2012-10-16 07:28:54 +02:00
|
|
|
this.packet = packet;
|
2019-08-07 17:34:59 +02:00
|
|
|
this.playerReference = new WeakReference<>(player);
|
2013-07-17 03:52:27 +02:00
|
|
|
this.networkMarker = marker;
|
2012-10-16 07:28:54 +02:00
|
|
|
this.serverPacket = serverPacket;
|
2014-04-25 02:55:17 +02:00
|
|
|
this.filtered = filtered;
|
Packet filtering for bundled packets in 1.19.4 (#2258)
Since Minecraft 1.19.4, the protocol supports bundling consecutive packets to ensure the client processes them in one tick. However, Packet Events are not called for the individual packets in such a bundle in the current dev build of ProtocolLib. For example, no packet events are currently sent for the ENTITY_METADATA packet when an entity is first spawned as the packet is bundled with the ENTITY_SPAWN packet. However, if the entity metadata is changed later on, the event will be called.
This PR proposes to fix this by unpacking the bundled packets and invoking the packet filtering for each packet.
I also want to briefly explain how the bundling works. A bundle starts with a PACKET_DELIMITER (0x00, net.minecraft.network.protocol.BundleDelimiterPacket) packet followed by all packets that should be bundled and finished with another PACKET_DELIMITER (0x00). Within the Netty pipeline, this sequence is transformed into one synthesized packet found in net.minecraft.network.protocol.game.ClientboundBundlePacket, which is essentially just a list of packets. At the stage at which ProtocolLib injects into the clientbound netty pipeline, this packet has not been unpacked yet. Thus, we need to handle the ClientboundBundlePacket, which unfortunately is not registered in ProtocolLib. The fact that two different classes map to the same packet currently requires a dirty remapping in the packet structure modifier.
2023-03-26 04:08:31 +02:00
|
|
|
this.bundle = bundleEvent;
|
2012-10-16 07:28:54 +02:00
|
|
|
}
|
2022-03-08 04:09:04 +01:00
|
|
|
|
Packet filtering for bundled packets in 1.19.4 (#2258)
Since Minecraft 1.19.4, the protocol supports bundling consecutive packets to ensure the client processes them in one tick. However, Packet Events are not called for the individual packets in such a bundle in the current dev build of ProtocolLib. For example, no packet events are currently sent for the ENTITY_METADATA packet when an entity is first spawned as the packet is bundled with the ENTITY_SPAWN packet. However, if the entity metadata is changed later on, the event will be called.
This PR proposes to fix this by unpacking the bundled packets and invoking the packet filtering for each packet.
I also want to briefly explain how the bundling works. A bundle starts with a PACKET_DELIMITER (0x00, net.minecraft.network.protocol.BundleDelimiterPacket) packet followed by all packets that should be bundled and finished with another PACKET_DELIMITER (0x00). Within the Netty pipeline, this sequence is transformed into one synthesized packet found in net.minecraft.network.protocol.game.ClientboundBundlePacket, which is essentially just a list of packets. At the stage at which ProtocolLib injects into the clientbound netty pipeline, this packet has not been unpacked yet. Thus, we need to handle the ClientboundBundlePacket, which unfortunately is not registered in ProtocolLib. The fact that two different classes map to the same packet currently requires a dirty remapping in the packet structure modifier.
2023-03-26 04:08:31 +02:00
|
|
|
private PacketEvent(PacketEvent original, AsyncMarker asyncMarker) {
|
|
|
|
super(original.source);
|
|
|
|
this.packet = original.packet;
|
|
|
|
this.playerReference = original.getPlayerReference();
|
|
|
|
this.cancel = original.cancel;
|
|
|
|
this.serverPacket = original.serverPacket;
|
|
|
|
this.filtered = original.filtered;
|
|
|
|
this.networkMarker = original.networkMarker;
|
2012-10-16 07:28:54 +02:00
|
|
|
this.asyncMarker = asyncMarker;
|
|
|
|
this.asynchronous = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates an event representing a client packet transmission.
|
2022-03-08 04:09:04 +01:00
|
|
|
*
|
2012-10-16 07:28:54 +02:00
|
|
|
* @param source - the event source.
|
|
|
|
* @param packet - the packet.
|
|
|
|
* @param client - the client that sent the packet.
|
|
|
|
* @return The event.
|
|
|
|
*/
|
|
|
|
public static PacketEvent fromClient(Object source, PacketContainer packet, Player client) {
|
|
|
|
return new PacketEvent(source, packet, client, false);
|
|
|
|
}
|
2022-03-08 04:09:04 +01:00
|
|
|
|
2013-07-17 03:52:27 +02:00
|
|
|
/**
|
|
|
|
* Creates an event representing a client packet transmission.
|
2022-03-08 04:09:04 +01:00
|
|
|
*
|
2013-07-17 03:52:27 +02:00
|
|
|
* @param source - the event source.
|
|
|
|
* @param packet - the packet.
|
|
|
|
* @param marker - the network marker.
|
|
|
|
* @param client - the client that sent the packet.
|
|
|
|
* @return The event.
|
|
|
|
*/
|
|
|
|
public static PacketEvent fromClient(Object source, PacketContainer packet, NetworkMarker marker, Player client) {
|
Packet filtering for bundled packets in 1.19.4 (#2258)
Since Minecraft 1.19.4, the protocol supports bundling consecutive packets to ensure the client processes them in one tick. However, Packet Events are not called for the individual packets in such a bundle in the current dev build of ProtocolLib. For example, no packet events are currently sent for the ENTITY_METADATA packet when an entity is first spawned as the packet is bundled with the ENTITY_SPAWN packet. However, if the entity metadata is changed later on, the event will be called.
This PR proposes to fix this by unpacking the bundled packets and invoking the packet filtering for each packet.
I also want to briefly explain how the bundling works. A bundle starts with a PACKET_DELIMITER (0x00, net.minecraft.network.protocol.BundleDelimiterPacket) packet followed by all packets that should be bundled and finished with another PACKET_DELIMITER (0x00). Within the Netty pipeline, this sequence is transformed into one synthesized packet found in net.minecraft.network.protocol.game.ClientboundBundlePacket, which is essentially just a list of packets. At the stage at which ProtocolLib injects into the clientbound netty pipeline, this packet has not been unpacked yet. Thus, we need to handle the ClientboundBundlePacket, which unfortunately is not registered in ProtocolLib. The fact that two different classes map to the same packet currently requires a dirty remapping in the packet structure modifier.
2023-03-26 04:08:31 +02:00
|
|
|
return new PacketEvent(source, packet, marker, client, false, true, null);
|
2014-04-25 02:55:17 +02:00
|
|
|
}
|
2022-03-08 04:09:04 +01:00
|
|
|
|
2014-04-25 02:55:17 +02:00
|
|
|
/**
|
|
|
|
* Creates an event representing a client packet transmission.
|
|
|
|
* <p>
|
|
|
|
* If <i>filtered</i> is FALSE, then this event is only processed by packet monitors.
|
2022-03-08 04:09:04 +01:00
|
|
|
*
|
|
|
|
* @param source - the event source.
|
|
|
|
* @param packet - the packet.
|
|
|
|
* @param marker - the network marker.
|
|
|
|
* @param client - the client that sent the packet.
|
2014-04-25 02:55:17 +02:00
|
|
|
* @param filtered - whether or not this packet event is processed by every packet listener.
|
|
|
|
* @return The event.
|
|
|
|
*/
|
2022-03-08 04:09:04 +01:00
|
|
|
public static PacketEvent fromClient(Object source, PacketContainer packet, NetworkMarker marker, Player client,
|
|
|
|
boolean filtered) {
|
Packet filtering for bundled packets in 1.19.4 (#2258)
Since Minecraft 1.19.4, the protocol supports bundling consecutive packets to ensure the client processes them in one tick. However, Packet Events are not called for the individual packets in such a bundle in the current dev build of ProtocolLib. For example, no packet events are currently sent for the ENTITY_METADATA packet when an entity is first spawned as the packet is bundled with the ENTITY_SPAWN packet. However, if the entity metadata is changed later on, the event will be called.
This PR proposes to fix this by unpacking the bundled packets and invoking the packet filtering for each packet.
I also want to briefly explain how the bundling works. A bundle starts with a PACKET_DELIMITER (0x00, net.minecraft.network.protocol.BundleDelimiterPacket) packet followed by all packets that should be bundled and finished with another PACKET_DELIMITER (0x00). Within the Netty pipeline, this sequence is transformed into one synthesized packet found in net.minecraft.network.protocol.game.ClientboundBundlePacket, which is essentially just a list of packets. At the stage at which ProtocolLib injects into the clientbound netty pipeline, this packet has not been unpacked yet. Thus, we need to handle the ClientboundBundlePacket, which unfortunately is not registered in ProtocolLib. The fact that two different classes map to the same packet currently requires a dirty remapping in the packet structure modifier.
2023-03-26 04:08:31 +02:00
|
|
|
return new PacketEvent(source, packet, marker, client, false, filtered, null);
|
2013-07-17 03:52:27 +02:00
|
|
|
}
|
2022-03-08 04:09:04 +01:00
|
|
|
|
2012-10-16 07:28:54 +02:00
|
|
|
/**
|
|
|
|
* Creates an event representing a server packet transmission.
|
2022-03-08 04:09:04 +01:00
|
|
|
*
|
|
|
|
* @param source - the event source.
|
|
|
|
* @param packet - the packet.
|
2012-10-16 07:28:54 +02:00
|
|
|
* @param recipient - the client that will receieve the packet.
|
|
|
|
* @return The event.
|
|
|
|
*/
|
2022-03-08 04:09:04 +01:00
|
|
|
public static PacketEvent fromServer(Object source, PacketContainer packet, Player recipient) {
|
2012-10-16 07:28:54 +02:00
|
|
|
return new PacketEvent(source, packet, recipient, true);
|
|
|
|
}
|
2022-03-08 04:09:04 +01:00
|
|
|
|
2013-07-17 03:52:27 +02:00
|
|
|
/**
|
|
|
|
* Creates an event representing a server packet transmission.
|
2022-03-08 04:09:04 +01:00
|
|
|
*
|
|
|
|
* @param source - the event source.
|
|
|
|
* @param packet - the packet.
|
|
|
|
* @param marker - the network marker.
|
2013-07-17 03:52:27 +02:00
|
|
|
* @param recipient - the client that will receieve the packet.
|
|
|
|
* @return The event.
|
|
|
|
*/
|
|
|
|
public static PacketEvent fromServer(Object source, PacketContainer packet, NetworkMarker marker, Player recipient) {
|
Packet filtering for bundled packets in 1.19.4 (#2258)
Since Minecraft 1.19.4, the protocol supports bundling consecutive packets to ensure the client processes them in one tick. However, Packet Events are not called for the individual packets in such a bundle in the current dev build of ProtocolLib. For example, no packet events are currently sent for the ENTITY_METADATA packet when an entity is first spawned as the packet is bundled with the ENTITY_SPAWN packet. However, if the entity metadata is changed later on, the event will be called.
This PR proposes to fix this by unpacking the bundled packets and invoking the packet filtering for each packet.
I also want to briefly explain how the bundling works. A bundle starts with a PACKET_DELIMITER (0x00, net.minecraft.network.protocol.BundleDelimiterPacket) packet followed by all packets that should be bundled and finished with another PACKET_DELIMITER (0x00). Within the Netty pipeline, this sequence is transformed into one synthesized packet found in net.minecraft.network.protocol.game.ClientboundBundlePacket, which is essentially just a list of packets. At the stage at which ProtocolLib injects into the clientbound netty pipeline, this packet has not been unpacked yet. Thus, we need to handle the ClientboundBundlePacket, which unfortunately is not registered in ProtocolLib. The fact that two different classes map to the same packet currently requires a dirty remapping in the packet structure modifier.
2023-03-26 04:08:31 +02:00
|
|
|
return new PacketEvent(source, packet, marker, recipient, true, true, null);
|
2014-04-25 02:55:17 +02:00
|
|
|
}
|
2022-03-08 04:09:04 +01:00
|
|
|
|
2014-04-25 02:55:17 +02:00
|
|
|
/**
|
|
|
|
* Creates an event representing a server packet transmission.
|
|
|
|
* <p>
|
|
|
|
* If <i>filtered</i> is FALSE, then this event is only processed by packet monitors.
|
2022-03-08 04:09:04 +01:00
|
|
|
*
|
|
|
|
* @param source - the event source.
|
|
|
|
* @param packet - the packet.
|
|
|
|
* @param marker - the network marker.
|
2014-04-25 02:55:17 +02:00
|
|
|
* @param recipient - the client that will receieve the packet.
|
2022-03-08 04:09:04 +01:00
|
|
|
* @param filtered - whether or not this packet event is processed by every packet listener.
|
2014-04-25 02:55:17 +02:00
|
|
|
* @return The event.
|
|
|
|
*/
|
2022-03-08 04:09:04 +01:00
|
|
|
public static PacketEvent fromServer(Object source, PacketContainer packet, NetworkMarker marker, Player recipient,
|
|
|
|
boolean filtered) {
|
Packet filtering for bundled packets in 1.19.4 (#2258)
Since Minecraft 1.19.4, the protocol supports bundling consecutive packets to ensure the client processes them in one tick. However, Packet Events are not called for the individual packets in such a bundle in the current dev build of ProtocolLib. For example, no packet events are currently sent for the ENTITY_METADATA packet when an entity is first spawned as the packet is bundled with the ENTITY_SPAWN packet. However, if the entity metadata is changed later on, the event will be called.
This PR proposes to fix this by unpacking the bundled packets and invoking the packet filtering for each packet.
I also want to briefly explain how the bundling works. A bundle starts with a PACKET_DELIMITER (0x00, net.minecraft.network.protocol.BundleDelimiterPacket) packet followed by all packets that should be bundled and finished with another PACKET_DELIMITER (0x00). Within the Netty pipeline, this sequence is transformed into one synthesized packet found in net.minecraft.network.protocol.game.ClientboundBundlePacket, which is essentially just a list of packets. At the stage at which ProtocolLib injects into the clientbound netty pipeline, this packet has not been unpacked yet. Thus, we need to handle the ClientboundBundlePacket, which unfortunately is not registered in ProtocolLib. The fact that two different classes map to the same packet currently requires a dirty remapping in the packet structure modifier.
2023-03-26 04:08:31 +02:00
|
|
|
return fromServer(source, packet, marker, recipient, filtered, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates an event representing a server packet transmission.
|
|
|
|
* <p>
|
|
|
|
* If <i>filtered</i> is FALSE, then this event is only processed by packet monitors.
|
|
|
|
*
|
|
|
|
* @param source - the event source.
|
|
|
|
* @param packet - the packet.
|
|
|
|
* @param marker - the network marker.
|
|
|
|
* @param recipient - the client that will receieve the packet.
|
|
|
|
* @param filtered - whether this packet event is processed by every packet listener.
|
|
|
|
* @param bundle - The corresponding packet event of the bundle if this packet is part of a bundle. Otherwise, null.
|
|
|
|
* @return The event.
|
|
|
|
*/
|
|
|
|
public static PacketEvent fromServer(Object source, PacketContainer packet, NetworkMarker marker, Player recipient,
|
|
|
|
boolean filtered, @Nullable PacketEvent bundle) {
|
|
|
|
return new PacketEvent(source, packet, marker, recipient, true, filtered, bundle);
|
2013-07-17 03:52:27 +02:00
|
|
|
}
|
2022-03-08 04:09:04 +01:00
|
|
|
|
2012-10-16 07:28:54 +02:00
|
|
|
/**
|
|
|
|
* Create an asynchronous packet event from a synchronous event and a async marker.
|
2022-03-08 04:09:04 +01:00
|
|
|
*
|
|
|
|
* @param event - the original synchronous event.
|
2012-10-16 07:28:54 +02:00
|
|
|
* @param marker - the asynchronous marker.
|
|
|
|
* @return The new packet event.
|
|
|
|
*/
|
|
|
|
public static PacketEvent fromSynchronous(PacketEvent event, AsyncMarker marker) {
|
|
|
|
return new PacketEvent(event, marker);
|
|
|
|
}
|
2022-03-08 04:09:04 +01:00
|
|
|
|
2013-12-06 01:21:35 +01:00
|
|
|
/**
|
|
|
|
* Determine if we are executing the packet event in an asynchronous thread.
|
|
|
|
* <p>
|
|
|
|
* If so, you must synchronize all calls to the Bukkit API.
|
|
|
|
* <p>
|
2022-03-08 04:09:04 +01:00
|
|
|
* Generally, most server packets are executed on the main thread, whereas client packets are all executed
|
|
|
|
* asynchronously.
|
|
|
|
*
|
2013-12-06 01:21:35 +01:00
|
|
|
* @return TRUE if we are, FALSE otherwise.
|
|
|
|
*/
|
|
|
|
public boolean isAsync() {
|
2016-03-19 21:01:38 +01:00
|
|
|
return !Bukkit.isPrimaryThread();
|
2013-12-06 01:21:35 +01:00
|
|
|
}
|
2022-03-08 04:09:04 +01:00
|
|
|
|
2012-10-16 07:28:54 +02:00
|
|
|
/**
|
|
|
|
* Retrieves the packet that will be sent to the player.
|
2022-03-08 04:09:04 +01:00
|
|
|
*
|
2012-10-16 07:28:54 +02:00
|
|
|
* @return Packet to send to the player.
|
|
|
|
*/
|
|
|
|
public PacketContainer getPacket() {
|
|
|
|
return packet;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Replace the packet that will be sent to the player.
|
2022-03-08 04:09:04 +01:00
|
|
|
*
|
2012-10-16 07:28:54 +02:00
|
|
|
* @param packet - the packet that will be sent instead.
|
|
|
|
*/
|
|
|
|
public void setPacket(PacketContainer packet) {
|
2022-03-08 04:09:04 +01:00
|
|
|
if (readOnly) {
|
2013-03-12 02:02:36 +01:00
|
|
|
throw new IllegalStateException("The packet event is read-only.");
|
2022-03-08 04:09:04 +01:00
|
|
|
}
|
|
|
|
if (packet == null) {
|
2014-03-22 23:20:16 +01:00
|
|
|
throw new IllegalArgumentException("Cannot set packet to NULL. Use setCancelled() instead.");
|
2022-03-08 04:09:04 +01:00
|
|
|
}
|
|
|
|
|
2014-03-30 00:50:45 +01:00
|
|
|
// Change warnings
|
|
|
|
final PacketType oldType = this.packet.getType();
|
|
|
|
final PacketType newType = packet.getType();
|
|
|
|
if (this.packet != null && !Objects.equal(oldType, newType)) {
|
|
|
|
// Only report this once
|
|
|
|
if (CHANGE_WARNINGS.put(oldType, newType)) {
|
2015-06-19 19:14:20 +02:00
|
|
|
ProtocolLibrary.getErrorReporter().reportWarning(this,
|
2014-03-30 00:50:45 +01:00
|
|
|
Report.newBuilder(REPORT_CHANGING_PACKET_TYPE_IS_CONFUSING).
|
2022-03-08 04:09:04 +01:00
|
|
|
messageParam(PluginContext.getPluginCaller(new Exception()), oldType, newType).
|
|
|
|
build());
|
2014-03-30 00:50:45 +01:00
|
|
|
}
|
|
|
|
}
|
2012-10-16 07:28:54 +02:00
|
|
|
this.packet = packet;
|
|
|
|
}
|
2022-03-08 04:09:04 +01:00
|
|
|
|
2012-10-16 07:28:54 +02:00
|
|
|
/**
|
|
|
|
* Retrieves the packet ID.
|
2013-12-04 04:17:02 +01:00
|
|
|
* <p>
|
|
|
|
* Deprecated: Use {@link #getPacketType()} instead.
|
2022-03-08 04:09:04 +01:00
|
|
|
*
|
2012-10-16 07:28:54 +02:00
|
|
|
* @return The current packet ID.
|
|
|
|
*/
|
2013-12-04 04:17:02 +01:00
|
|
|
@Deprecated
|
2012-10-16 07:28:54 +02:00
|
|
|
public int getPacketID() {
|
2020-06-06 21:13:29 +02:00
|
|
|
return packet.getId();
|
2012-10-16 07:28:54 +02:00
|
|
|
}
|
2022-03-08 04:09:04 +01:00
|
|
|
|
2013-12-04 04:17:02 +01:00
|
|
|
/**
|
|
|
|
* Retrieve the packet type.
|
2022-03-08 04:09:04 +01:00
|
|
|
*
|
2013-12-04 04:17:02 +01:00
|
|
|
* @return The type.
|
|
|
|
*/
|
|
|
|
public PacketType getPacketType() {
|
|
|
|
return packet.getType();
|
|
|
|
}
|
2022-03-08 04:09:04 +01:00
|
|
|
|
2012-10-16 07:28:54 +02:00
|
|
|
/**
|
|
|
|
* Retrieves whether or not the packet should be cancelled.
|
2022-03-08 04:09:04 +01:00
|
|
|
*
|
2012-10-16 07:28:54 +02:00
|
|
|
* @return TRUE if it should be cancelled, FALSE otherwise.
|
|
|
|
*/
|
2015-06-19 19:14:20 +02:00
|
|
|
@Override
|
2012-10-16 07:28:54 +02:00
|
|
|
public boolean isCancelled() {
|
|
|
|
return cancel;
|
|
|
|
}
|
2022-03-08 04:09:04 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets whether or not the packet should be cancelled. Uncancelling is possible.
|
|
|
|
* <p>
|
|
|
|
* <b>Warning</b>: A cancelled packet should never be re-transmitted. Use the asynchronous
|
|
|
|
* packet manager if you need to perform extensive processing. It should also be used if you need to synchronize with
|
|
|
|
* the main thread.
|
|
|
|
* <p>
|
|
|
|
* This ensures that other plugins can work with the same packet.
|
|
|
|
* <p>
|
|
|
|
* An asynchronous listener can also delay a packet indefinitely without having to block its thread.
|
|
|
|
*
|
|
|
|
* @param cancel - TRUE if it should be cancelled, FALSE otherwise.
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void setCancelled(boolean cancel) {
|
|
|
|
if (readOnly) {
|
|
|
|
throw new IllegalStateException("The packet event is read-only.");
|
|
|
|
}
|
|
|
|
this.cancel = cancel;
|
|
|
|
}
|
|
|
|
|
2013-07-17 03:52:27 +02:00
|
|
|
/**
|
|
|
|
* Retrieve the object responsible for managing the serialized input and output of a packet.
|
|
|
|
* <p>
|
2022-03-08 04:09:04 +01:00
|
|
|
* Note that the serialized input data is only available for client-side packets, and the output handlers can only be
|
|
|
|
* applied to server-side packets.
|
|
|
|
*
|
2013-07-17 03:52:27 +02:00
|
|
|
* @return The network manager.
|
|
|
|
*/
|
|
|
|
public NetworkMarker getNetworkMarker() {
|
|
|
|
if (networkMarker == null) {
|
|
|
|
if (isServerPacket()) {
|
2022-03-08 04:09:04 +01:00
|
|
|
networkMarker = new NetworkMarker(serverPacket ? ConnectionSide.SERVER_SIDE : ConnectionSide.CLIENT_SIDE, this.getPacketType());
|
2013-07-17 03:52:27 +02:00
|
|
|
} else {
|
|
|
|
throw new IllegalStateException("Add the option ListenerOptions.INTERCEPT_INPUT_BUFFER to your listener.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return networkMarker;
|
|
|
|
}
|
2012-10-16 07:28:54 +02:00
|
|
|
|
2013-07-17 03:52:27 +02:00
|
|
|
/**
|
|
|
|
* Update the network manager.
|
|
|
|
* <p>
|
|
|
|
* This method is internal - do not call.
|
2022-03-08 04:09:04 +01:00
|
|
|
*
|
2013-07-17 03:52:27 +02:00
|
|
|
* @param networkMarker - the new network manager.
|
|
|
|
*/
|
|
|
|
public void setNetworkMarker(NetworkMarker networkMarker) {
|
|
|
|
this.networkMarker = Preconditions.checkNotNull(networkMarker, "marker cannot be NULL");
|
|
|
|
}
|
2012-10-16 07:28:54 +02:00
|
|
|
|
2019-08-07 17:34:59 +02:00
|
|
|
private WeakReference<Player> getPlayerReference() {
|
2017-07-06 19:56:30 +02:00
|
|
|
Player player = playerReference.get();
|
|
|
|
|
|
|
|
if (player instanceof TemporaryPlayer) {
|
|
|
|
Player updated = player.getPlayer();
|
|
|
|
if (updated != null && !(updated instanceof TemporaryPlayer)) {
|
|
|
|
playerReference.clear();
|
|
|
|
playerReference = new WeakReference<>(updated);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-07 17:34:59 +02:00
|
|
|
return playerReference;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieves the player that has sent the packet or is receiving it.
|
2022-03-08 04:09:04 +01:00
|
|
|
*
|
2019-08-07 17:34:59 +02:00
|
|
|
* @return The player associated with this event.
|
|
|
|
*/
|
|
|
|
public Player getPlayer() {
|
|
|
|
return getPlayerReference().get();
|
2017-07-06 19:56:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Whether or not the player in this PacketEvent is temporary (i.e. they don't have a true player instance yet).
|
|
|
|
* Temporary players have a limited subset of methods that may be used:
|
|
|
|
* <ul>
|
|
|
|
* <li>getPlayer</li>
|
|
|
|
* <li>getAddress</li>
|
|
|
|
* <li>getServer</li>
|
|
|
|
* <li>chat</li>
|
|
|
|
* <li>sendMessage</li>
|
|
|
|
* <li>kickPlayer</li>
|
|
|
|
* <li>isOnline</li>
|
|
|
|
* </ul>
|
2022-03-08 04:09:04 +01:00
|
|
|
* <p>
|
2017-07-06 19:56:30 +02:00
|
|
|
* Anything else will throw an UnsupportedOperationException. Use this check before calling other methods when
|
|
|
|
* dealing with packets early in the login sequence or if you get the aforementioned exception.
|
|
|
|
*
|
|
|
|
* @return True if the player is temporary, false if not.
|
|
|
|
*/
|
|
|
|
public boolean isPlayerTemporary() {
|
|
|
|
return getPlayer() instanceof TemporaryPlayer;
|
2012-10-16 07:28:54 +02:00
|
|
|
}
|
2022-03-08 04:09:04 +01:00
|
|
|
|
2014-04-25 02:55:17 +02:00
|
|
|
/**
|
|
|
|
* Determine if this packet is filtered by every packet listener.
|
|
|
|
* <p>
|
|
|
|
* If not, it will only be intercepted by monitor packets.
|
2022-03-08 04:09:04 +01:00
|
|
|
*
|
2014-04-25 02:55:17 +02:00
|
|
|
* @return TRUE if it is, FALSE otherwise.
|
|
|
|
*/
|
|
|
|
public boolean isFiltered() {
|
|
|
|
return filtered;
|
|
|
|
}
|
2022-03-08 04:09:04 +01:00
|
|
|
|
2012-10-16 07:28:54 +02:00
|
|
|
/**
|
|
|
|
* Whether or not this packet was created by the server.
|
|
|
|
* <p>
|
|
|
|
* Most listeners can deduce this by noting which listener method was invoked.
|
2022-03-08 04:09:04 +01:00
|
|
|
*
|
2012-10-16 07:28:54 +02:00
|
|
|
* @return TRUE if the packet was created by the server, FALSE if it was created by a client.
|
|
|
|
*/
|
|
|
|
public boolean isServerPacket() {
|
|
|
|
return serverPacket;
|
|
|
|
}
|
2022-03-08 04:09:04 +01:00
|
|
|
|
2012-10-16 07:28:54 +02:00
|
|
|
/**
|
|
|
|
* Retrieve the asynchronous marker.
|
|
|
|
* <p>
|
|
|
|
* If the packet is synchronous, this marker will be used to schedule an asynchronous event. In the following
|
|
|
|
* asynchronous event, the marker is used to correctly pass the packet around to the different threads.
|
|
|
|
* <p>
|
|
|
|
* Note that if there are no asynchronous events that can receive this packet, the marker is NULL.
|
2022-03-08 04:09:04 +01:00
|
|
|
*
|
2012-10-16 07:28:54 +02:00
|
|
|
* @return The current asynchronous marker, or NULL.
|
|
|
|
*/
|
|
|
|
public AsyncMarker getAsyncMarker() {
|
|
|
|
return asyncMarker;
|
|
|
|
}
|
2022-03-08 04:09:04 +01:00
|
|
|
|
2012-10-16 07:28:54 +02:00
|
|
|
/**
|
2015-06-19 19:14:20 +02:00
|
|
|
* Set the asynchronous marker.
|
2012-10-16 07:28:54 +02:00
|
|
|
* <p>
|
2022-03-08 04:09:04 +01:00
|
|
|
* If the marker is non-null at the end of an synchronous event processing, the packet will be scheduled to be
|
|
|
|
* processed asynchronously with the given settings.
|
2012-10-16 07:28:54 +02:00
|
|
|
* <p>
|
2015-06-19 19:14:20 +02:00
|
|
|
* Note that if there are no asynchronous events that can receive this packet, the marker should be NULL.
|
2022-03-08 04:09:04 +01:00
|
|
|
*
|
2012-10-16 07:28:54 +02:00
|
|
|
* @param asyncMarker - the new asynchronous marker, or NULL.
|
|
|
|
* @throws IllegalStateException If the current event is asynchronous.
|
|
|
|
*/
|
|
|
|
public void setAsyncMarker(AsyncMarker asyncMarker) {
|
2022-03-08 04:09:04 +01:00
|
|
|
if (isAsynchronous()) {
|
2012-10-16 07:28:54 +02:00
|
|
|
throw new IllegalStateException("The marker is immutable for asynchronous events");
|
2022-03-08 04:09:04 +01:00
|
|
|
}
|
|
|
|
if (readOnly) {
|
2013-03-12 02:02:36 +01:00
|
|
|
throw new IllegalStateException("The packet event is read-only.");
|
2022-03-08 04:09:04 +01:00
|
|
|
}
|
2012-10-16 07:28:54 +02:00
|
|
|
this.asyncMarker = asyncMarker;
|
|
|
|
}
|
|
|
|
|
2013-03-12 02:02:36 +01:00
|
|
|
/**
|
|
|
|
* Determine if the current packet event is read only.
|
|
|
|
* <p>
|
2022-03-08 04:09:04 +01:00
|
|
|
* This is used to ensure that a monitor listener doesn't accidentally alter the state of the event. However, it is
|
|
|
|
* still possible to modify the packet itself, as it would require too many resources to verify its integrity.
|
2013-03-12 02:02:36 +01:00
|
|
|
* <p>
|
|
|
|
* Thus, the packet is considered immutable if the packet event is read only.
|
2022-03-08 04:09:04 +01:00
|
|
|
*
|
2013-03-12 02:02:36 +01:00
|
|
|
* @return TRUE if it is, FALSE otherwise.
|
|
|
|
*/
|
|
|
|
public boolean isReadOnly() {
|
|
|
|
return readOnly;
|
|
|
|
}
|
2022-03-08 04:09:04 +01:00
|
|
|
|
2013-03-12 02:02:36 +01:00
|
|
|
/**
|
|
|
|
* Set the read-only state of this packet event.
|
|
|
|
* <p>
|
|
|
|
* This will be reset for every packet listener.
|
2022-03-08 04:09:04 +01:00
|
|
|
*
|
2013-03-12 02:02:36 +01:00
|
|
|
* @param readOnly - TRUE if it is read-only, FALSE otherwise.
|
|
|
|
*/
|
|
|
|
public void setReadOnly(boolean readOnly) {
|
|
|
|
this.readOnly = readOnly;
|
|
|
|
}
|
2022-03-08 04:09:04 +01:00
|
|
|
|
2012-10-16 07:28:54 +02:00
|
|
|
/**
|
|
|
|
* Determine if the packet event has been executed asynchronously or not.
|
2022-03-08 04:09:04 +01:00
|
|
|
*
|
2012-10-16 07:28:54 +02:00
|
|
|
* @return TRUE if this packet event is asynchronous, FALSE otherwise.
|
|
|
|
*/
|
|
|
|
public boolean isAsynchronous() {
|
|
|
|
return asynchronous;
|
|
|
|
}
|
2013-03-12 02:02:36 +01:00
|
|
|
|
2014-04-26 00:20:50 +02:00
|
|
|
/**
|
|
|
|
* Schedule a packet for sending or receiving after the current packet event is successful.
|
|
|
|
* <p>
|
|
|
|
* The packet will be added to {@link NetworkMarker#getScheduledPackets()}.
|
2022-03-08 04:09:04 +01:00
|
|
|
*
|
2014-04-26 00:20:50 +02:00
|
|
|
* @param scheduled - the packet to transmit or receive.
|
|
|
|
*/
|
|
|
|
public void schedule(ScheduledPacket scheduled) {
|
|
|
|
getNetworkMarker().getScheduledPackets().add(scheduled);
|
|
|
|
}
|
2022-03-08 04:09:04 +01:00
|
|
|
|
2014-04-26 00:20:50 +02:00
|
|
|
/**
|
|
|
|
* Unschedule a specific packet.
|
2022-03-08 04:09:04 +01:00
|
|
|
*
|
2014-04-26 00:20:50 +02:00
|
|
|
* @param scheduled - the scheduled packet.
|
|
|
|
* @return TRUE if it was unscheduled, FALSE otherwise.
|
|
|
|
*/
|
|
|
|
public boolean unschedule(ScheduledPacket scheduled) {
|
|
|
|
if (networkMarker != null) {
|
|
|
|
return networkMarker.getScheduledPackets().remove(scheduled);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2022-03-08 04:09:04 +01:00
|
|
|
|
2012-10-16 07:28:54 +02:00
|
|
|
private void writeObject(ObjectOutputStream output) throws IOException {
|
2022-03-08 04:09:04 +01:00
|
|
|
// Default serialization
|
2012-10-16 07:28:54 +02:00
|
|
|
output.defaultWriteObject();
|
|
|
|
|
|
|
|
// Write the name of the player (or NULL if it's not set)
|
2019-08-07 17:34:59 +02:00
|
|
|
Player player = getPlayer();
|
|
|
|
output.writeObject(player != null ? new SerializedOfflinePlayer(player) : null);
|
2012-10-16 07:28:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private void readObject(ObjectInputStream input) throws ClassNotFoundException, IOException {
|
2022-03-08 04:09:04 +01:00
|
|
|
// Default deserialization
|
2012-10-16 07:28:54 +02:00
|
|
|
input.defaultReadObject();
|
|
|
|
|
2012-11-20 03:23:43 +01:00
|
|
|
final SerializedOfflinePlayer serialized = (SerializedOfflinePlayer) input.readObject();
|
2022-03-08 04:09:04 +01:00
|
|
|
|
2012-11-20 03:23:43 +01:00
|
|
|
// Better than nothing
|
2022-03-08 04:09:04 +01:00
|
|
|
if (serialized != null) {
|
|
|
|
// Store it, to prevent weak reference from cleaning up the reference
|
|
|
|
Player offlinePlayer = serialized.getPlayer();
|
|
|
|
playerReference = new WeakReference<>(offlinePlayer);
|
|
|
|
}
|
2012-10-16 07:28:54 +02:00
|
|
|
}
|
2015-06-19 19:14:20 +02:00
|
|
|
|
Packet filtering for bundled packets in 1.19.4 (#2258)
Since Minecraft 1.19.4, the protocol supports bundling consecutive packets to ensure the client processes them in one tick. However, Packet Events are not called for the individual packets in such a bundle in the current dev build of ProtocolLib. For example, no packet events are currently sent for the ENTITY_METADATA packet when an entity is first spawned as the packet is bundled with the ENTITY_SPAWN packet. However, if the entity metadata is changed later on, the event will be called.
This PR proposes to fix this by unpacking the bundled packets and invoking the packet filtering for each packet.
I also want to briefly explain how the bundling works. A bundle starts with a PACKET_DELIMITER (0x00, net.minecraft.network.protocol.BundleDelimiterPacket) packet followed by all packets that should be bundled and finished with another PACKET_DELIMITER (0x00). Within the Netty pipeline, this sequence is transformed into one synthesized packet found in net.minecraft.network.protocol.game.ClientboundBundlePacket, which is essentially just a list of packets. At the stage at which ProtocolLib injects into the clientbound netty pipeline, this packet has not been unpacked yet. Thus, we need to handle the ClientboundBundlePacket, which unfortunately is not registered in ProtocolLib. The fact that two different classes map to the same packet currently requires a dirty remapping in the packet structure modifier.
2023-03-26 04:08:31 +02:00
|
|
|
/**
|
|
|
|
* Returns the packet event corresponding to the bundle if this packet is sent as a part of a bundle, t. Otherwise, null.
|
|
|
|
* @return Corresponding packet event or null.
|
|
|
|
*/
|
|
|
|
@Nullable
|
|
|
|
public PacketEvent getBundle() {
|
|
|
|
return bundle;
|
|
|
|
}
|
|
|
|
|
2015-06-19 19:14:20 +02:00
|
|
|
@Override
|
|
|
|
public String toString() {
|
|
|
|
return "PacketEvent[player=" + getPlayer() + ", packet=" + packet + "]";
|
|
|
|
}
|
2016-05-21 23:37:13 +02:00
|
|
|
}
|