mirror of https://github.com/Minestom/Minestom.git
Add PlayerPacketOutEvent (#689)
This commit is contained in:
parent
be100fa5b8
commit
9b04e89552
|
@ -1,8 +1,8 @@
|
|||
package net.minestom.demo;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.demo.generator.ChunkGeneratorDemo;
|
||||
import net.minestom.demo.generator.NoiseTestGenerator;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.adventure.audience.Audiences;
|
||||
import net.minestom.server.coordinate.Pos;
|
||||
|
@ -17,10 +17,7 @@ import net.minestom.server.event.EventNode;
|
|||
import net.minestom.server.event.entity.EntityAttackEvent;
|
||||
import net.minestom.server.event.item.ItemDropEvent;
|
||||
import net.minestom.server.event.item.PickupItemEvent;
|
||||
import net.minestom.server.event.player.PlayerDeathEvent;
|
||||
import net.minestom.server.event.player.PlayerDisconnectEvent;
|
||||
import net.minestom.server.event.player.PlayerLoginEvent;
|
||||
import net.minestom.server.event.player.PlayerSpawnEvent;
|
||||
import net.minestom.server.event.player.*;
|
||||
import net.minestom.server.event.server.ServerTickMonitorEvent;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.instance.InstanceContainer;
|
||||
|
@ -114,6 +111,12 @@ public class PlayerInit {
|
|||
})
|
||||
.build();
|
||||
player.getInventory().addItemStack(bundle);
|
||||
})
|
||||
.addListener(PlayerPacketOutEvent.class, event -> {
|
||||
//System.out.println("out " + event.getPacket().getClass().getSimpleName());
|
||||
})
|
||||
.addListener(PlayerPacketEvent.class, event -> {
|
||||
//System.out.println("in " + event.getPacket().getClass().getSimpleName());
|
||||
});
|
||||
|
||||
static {
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package net.minestom.server.event.player;
|
||||
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.event.trait.PlayerEvent;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Listen to outgoing packets asynchronously.
|
||||
* <p>
|
||||
* Currently, do not support viewable packets.
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
public class PlayerPacketOutEvent implements PlayerEvent {
|
||||
|
||||
private final Player player;
|
||||
private final ServerPacket packet;
|
||||
|
||||
public PlayerPacketOutEvent(Player player, ServerPacket packet) {
|
||||
this.player = player;
|
||||
this.packet = packet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public @NotNull ServerPacket getPacket() {
|
||||
return packet;
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package net.minestom.server.listener.manager;
|
||||
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.network.ConnectionManager;
|
||||
import net.minestom.server.network.packet.client.ClientPacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Interface used to add a listener for incoming packets with {@link ConnectionManager#onPacketReceive(ClientPacketConsumer)}.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ClientPacketConsumer {
|
||||
|
||||
/**
|
||||
* Called when a packet is received from a client.
|
||||
*
|
||||
* @param player the player concerned by the packet
|
||||
* @param packetController the packet controller, can be used to cancel the packet
|
||||
* @param packet the packet
|
||||
*/
|
||||
void accept(@NotNull Player player, @NotNull PacketController packetController, @NotNull ClientPacket packet);
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package net.minestom.server.listener.manager;
|
||||
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.network.packet.client.ClientPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Used to control the output of a packet in {@link ClientPacketConsumer#accept(Player, PacketController, ClientPacket)}
|
||||
* and {@link ServerPacketConsumer#accept(Collection, PacketController, ServerPacket)}.
|
||||
*/
|
||||
public class PacketController {
|
||||
|
||||
private boolean cancel;
|
||||
|
||||
protected PacketController() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if the packet is cancelled.
|
||||
*
|
||||
* @return true if the packet will be cancelled, false otherwise
|
||||
*/
|
||||
public boolean isCancel() {
|
||||
return cancel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to cancel the packet.
|
||||
*
|
||||
* @param cancel true if the packet should be cancelled, false otherwise
|
||||
*/
|
||||
public void setCancel(boolean cancel) {
|
||||
this.cancel = cancel;
|
||||
}
|
||||
}
|
|
@ -6,16 +6,12 @@ import net.minestom.server.entity.Player;
|
|||
import net.minestom.server.event.EventDispatcher;
|
||||
import net.minestom.server.event.player.PlayerPacketEvent;
|
||||
import net.minestom.server.listener.*;
|
||||
import net.minestom.server.network.ConnectionManager;
|
||||
import net.minestom.server.network.packet.client.ClientPacket;
|
||||
import net.minestom.server.network.packet.client.play.*;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
|
@ -79,17 +75,6 @@ public final class PacketListenerManager {
|
|||
LOGGER.warn("Packet " + clazz + " does not have any default listener! (The issue comes from Minestom)");
|
||||
}
|
||||
|
||||
// TODO remove legacy
|
||||
{
|
||||
final PacketController packetController = new PacketController();
|
||||
for (ClientPacketConsumer clientPacketConsumer : serverProcess.connection().getReceivePacketConsumers()) {
|
||||
clientPacketConsumer.accept(player, packetController, packet);
|
||||
}
|
||||
|
||||
if (packetController.isCancel())
|
||||
return;
|
||||
}
|
||||
|
||||
// Event
|
||||
PlayerPacketEvent playerPacketEvent = new PlayerPacketEvent(player, packet);
|
||||
EventDispatcher.call(playerPacketEvent);
|
||||
|
@ -108,27 +93,6 @@ public final class PacketListenerManager {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the consumers from {@link ConnectionManager#onPacketSend(ServerPacketConsumer)}.
|
||||
*
|
||||
* @param packet the packet to process
|
||||
* @param players the players which should receive the packet
|
||||
* @return true if the packet is not cancelled, false otherwise
|
||||
*/
|
||||
public boolean processServerPacket(@NotNull ServerPacket packet, @NotNull Collection<Player> players) {
|
||||
final List<ServerPacketConsumer> consumers = serverProcess.connection().getSendPacketConsumers();
|
||||
if (consumers.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final PacketController packetController = new PacketController();
|
||||
for (ServerPacketConsumer serverPacketConsumer : consumers) {
|
||||
serverPacketConsumer.accept(players, packetController, packet);
|
||||
}
|
||||
|
||||
return !packetController.isCancel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the listener of a packet.
|
||||
* <p>
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
package net.minestom.server.listener.manager;
|
||||
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.network.ConnectionManager;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Interface used to add a listener for outgoing packets with {@link ConnectionManager#onPacketSend(ServerPacketConsumer)}.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ServerPacketConsumer {
|
||||
|
||||
/**
|
||||
* Called when a packet is sent to a client.
|
||||
*
|
||||
* @param players the players who will receive the packet
|
||||
* @param packetController the packet controller, can be used for cancelling
|
||||
* @param packet the packet to send
|
||||
*/
|
||||
void accept(@NotNull Collection<Player> players, @NotNull PacketController packetController, @NotNull ServerPacket packet);
|
||||
|
||||
}
|
|
@ -8,8 +8,6 @@ import net.minestom.server.event.EventDispatcher;
|
|||
import net.minestom.server.event.player.AsyncPlayerPreLoginEvent;
|
||||
import net.minestom.server.event.player.PlayerLoginEvent;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.listener.manager.ClientPacketConsumer;
|
||||
import net.minestom.server.listener.manager.ServerPacketConsumer;
|
||||
import net.minestom.server.network.packet.server.login.LoginSuccessPacket;
|
||||
import net.minestom.server.network.packet.server.play.DisconnectPacket;
|
||||
import net.minestom.server.network.packet.server.play.KeepAlivePacket;
|
||||
|
@ -25,7 +23,6 @@ import org.jetbrains.annotations.Nullable;
|
|||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.function.Function;
|
||||
|
||||
|
@ -42,10 +39,6 @@ public final class ConnectionManager {
|
|||
private final Set<Player> unmodifiablePlayers = Collections.unmodifiableSet(players);
|
||||
private final Map<PlayerConnection, Player> connectionPlayerMap = new ConcurrentHashMap<>();
|
||||
|
||||
// All the consumers to call once a packet is received
|
||||
private final List<ClientPacketConsumer> receiveClientPacketConsumers = new CopyOnWriteArrayList<>();
|
||||
// All the consumers to call once a packet is sent
|
||||
private final List<ServerPacketConsumer> sendClientPacketConsumers = new CopyOnWriteArrayList<>();
|
||||
// The uuid provider once a player login
|
||||
private volatile UuidProvider uuidProvider = (playerConnection, username) -> UUID.randomUUID();
|
||||
// The player provider to have your own Player implementation
|
||||
|
@ -126,56 +119,6 @@ public final class ConnectionManager {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the listeners which are called for each packet received.
|
||||
*
|
||||
* @return a list of packet's consumers
|
||||
* @deprecated see {@link net.minestom.server.event.player.PlayerPacketEvent}
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated
|
||||
public List<ClientPacketConsumer> getReceivePacketConsumers() {
|
||||
return receiveClientPacketConsumers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a consumer to call once a packet is received.
|
||||
*
|
||||
* @param clientPacketConsumer the packet consumer
|
||||
* @deprecated listen to {@link net.minestom.server.event.player.PlayerPacketEvent}
|
||||
*/
|
||||
@Deprecated
|
||||
public void onPacketReceive(@NotNull ClientPacketConsumer clientPacketConsumer) {
|
||||
this.receiveClientPacketConsumers.add(clientPacketConsumer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the listeners which are called for each packet sent.
|
||||
*
|
||||
* @return a list of packet's consumers
|
||||
* @deprecated all packet listening methods will ultimately be removed.
|
||||
* May or may not work depending on the packet.
|
||||
* It is instead recommended to use a proxy, improving scalability and increasing server performance
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated
|
||||
public List<ServerPacketConsumer> getSendPacketConsumers() {
|
||||
return sendClientPacketConsumers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a consumer to call once a packet is sent.
|
||||
*
|
||||
* @param serverPacketConsumer the packet consumer
|
||||
* @deprecated all packet listening methods will ultimately be removed.
|
||||
* May or may not work depending on the packet.
|
||||
* It is instead recommended to use a proxy, improving scalability and increasing server performance
|
||||
*/
|
||||
@Deprecated
|
||||
public void onPacketSend(@NotNull ServerPacketConsumer serverPacketConsumer) {
|
||||
this.sendClientPacketConsumers.add(serverPacketConsumer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes how {@link UUID} are attributed to players.
|
||||
* <p>
|
||||
|
|
|
@ -18,7 +18,6 @@ public class FakePlayerConnection extends PlayerConnection {
|
|||
public void sendPacket(@NotNull SendablePacket packet) {
|
||||
FakePlayerController controller = getFakePlayer().getController();
|
||||
final ServerPacket serverPacket = SendablePacket.extractServerPacket(packet);
|
||||
if (!shouldSendPacket(serverPacket)) return;
|
||||
controller.consumePacket(serverPacket);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,18 +5,14 @@ import net.kyori.adventure.text.format.NamedTextColor;
|
|||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.listener.manager.PacketListenerManager;
|
||||
import net.minestom.server.listener.manager.ServerPacketConsumer;
|
||||
import net.minestom.server.network.ConnectionManager;
|
||||
import net.minestom.server.network.ConnectionState;
|
||||
import net.minestom.server.network.packet.server.SendablePacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
|
@ -84,11 +80,8 @@ public abstract class PlayerConnection {
|
|||
|
||||
/**
|
||||
* Serializes the packet and send it to the client.
|
||||
* <p>
|
||||
* Also responsible for executing {@link ConnectionManager#onPacketSend(ServerPacketConsumer)} consumers.
|
||||
*
|
||||
* @param packet the packet to send
|
||||
* @see #shouldSendPacket(ServerPacket)
|
||||
*/
|
||||
public abstract void sendPacket(@NotNull SendablePacket packet);
|
||||
|
||||
|
@ -111,11 +104,6 @@ public abstract class PlayerConnection {
|
|||
// Empty
|
||||
}
|
||||
|
||||
protected boolean shouldSendPacket(@NotNull ServerPacket serverPacket) {
|
||||
return player == null ||
|
||||
PACKET_LISTENER_MANAGER.processServerPacket(serverPacket, Collections.singleton(player));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the remote address of the client.
|
||||
*
|
||||
|
|
|
@ -5,6 +5,8 @@ import net.minestom.server.MinecraftServer;
|
|||
import net.minestom.server.adventure.MinestomAdventure;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.entity.PlayerSkin;
|
||||
import net.minestom.server.event.ListenerHandle;
|
||||
import net.minestom.server.event.player.PlayerPacketOutEvent;
|
||||
import net.minestom.server.extras.mojangAuth.MojangCrypt;
|
||||
import net.minestom.server.network.ConnectionState;
|
||||
import net.minestom.server.network.PacketProcessor;
|
||||
|
@ -75,6 +77,8 @@ public class PlayerSocketConnection extends PlayerConnection {
|
|||
private final AtomicReference<BinaryBuffer> tickBuffer = new AtomicReference<>(PooledBuffers.get());
|
||||
private volatile BinaryBuffer cacheBuffer;
|
||||
|
||||
private final ListenerHandle<PlayerPacketOutEvent> outgoing = MinecraftServer.getGlobalEventHandler().getHandle(PlayerPacketOutEvent.class);
|
||||
|
||||
public PlayerSocketConnection(@NotNull Worker worker, @NotNull SocketChannel channel, SocketAddress remoteAddress) {
|
||||
super();
|
||||
this.worker = worker;
|
||||
|
@ -346,12 +350,21 @@ public class PlayerSocketConnection extends PlayerConnection {
|
|||
|
||||
private void writePacketSync(SendablePacket packet, boolean compressed) {
|
||||
if (!channel.isConnected()) return;
|
||||
final Player player = getPlayer();
|
||||
// Outgoing event
|
||||
if (player != null && outgoing.hasListener()) {
|
||||
final ServerPacket serverPacket = SendablePacket.extractServerPacket(packet);
|
||||
outgoing.call(new PlayerPacketOutEvent(player, serverPacket));
|
||||
}
|
||||
// Write packet
|
||||
if (packet instanceof ServerPacket serverPacket) {
|
||||
writeServerPacketSync(serverPacket, compressed);
|
||||
} else if (packet instanceof FramedPacket framedPacket) {
|
||||
writeFramedPacketSync(framedPacket);
|
||||
var buffer = framedPacket.body();
|
||||
writeBufferSync0(buffer, 0, buffer.limit());
|
||||
} else if (packet instanceof CachedPacket cachedPacket) {
|
||||
writeBufferSync(cachedPacket.body());
|
||||
var buffer = cachedPacket.body();
|
||||
writeBufferSync0(buffer, buffer.position(), buffer.remaining());
|
||||
} else if (packet instanceof LazyPacket lazyPacket) {
|
||||
writeServerPacketSync(lazyPacket.packet(), compressed);
|
||||
} else {
|
||||
|
@ -360,7 +373,6 @@ public class PlayerSocketConnection extends PlayerConnection {
|
|||
}
|
||||
|
||||
private void writeServerPacketSync(ServerPacket serverPacket, boolean compressed) {
|
||||
if (!shouldSendPacket(serverPacket)) return;
|
||||
final Player player = getPlayer();
|
||||
if (player != null) {
|
||||
if (MinestomAdventure.AUTOMATIC_COMPONENT_TRANSLATION && serverPacket instanceof ComponentHoldingServerPacket) {
|
||||
|
@ -368,15 +380,17 @@ public class PlayerSocketConnection extends PlayerConnection {
|
|||
GlobalTranslator.render(component, Objects.requireNonNullElseGet(player.getLocale(), MinestomAdventure::getDefaultLocale)));
|
||||
}
|
||||
}
|
||||
writeBufferSync(PacketUtils.createFramedPacket(serverPacket, compressed));
|
||||
var buffer = PacketUtils.createFramedPacket(serverPacket, compressed);
|
||||
writeBufferSync0(buffer, 0, buffer.limit());
|
||||
if (player == null) flushSync(); // Player is probably not logged yet
|
||||
}
|
||||
|
||||
private void writeFramedPacketSync(FramedPacket framedPacket) {
|
||||
writeBufferSync(framedPacket.body());
|
||||
private void writeBufferSync(@NotNull ByteBuffer buffer, int index, int length) {
|
||||
// TODO read buffer for outgoing event
|
||||
writeBufferSync0(buffer, index, length);
|
||||
}
|
||||
|
||||
private void writeBufferSync(@NotNull ByteBuffer buffer, int index, int length) {
|
||||
private void writeBufferSync0(@NotNull ByteBuffer buffer, int index, int length) {
|
||||
if (encrypted) { // Encryption support
|
||||
ByteBuffer output = PooledBuffers.tempBuffer();
|
||||
try {
|
||||
|
@ -405,10 +419,6 @@ public class PlayerSocketConnection extends PlayerConnection {
|
|||
}
|
||||
}
|
||||
|
||||
private void writeBufferSync(@NotNull ByteBuffer buffer) {
|
||||
writeBufferSync(buffer, buffer.position(), buffer.remaining());
|
||||
}
|
||||
|
||||
public void flushSync() {
|
||||
try {
|
||||
if (!channel.isConnected()) throw new ClosedChannelException();
|
||||
|
|
|
@ -104,7 +104,6 @@ public final class PacketUtils {
|
|||
public static void sendGroupedPacket(@NotNull Collection<Player> players, @NotNull ServerPacket packet,
|
||||
@NotNull Predicate<Player> predicate) {
|
||||
if (players.isEmpty()) return;
|
||||
if (!MinecraftServer.getPacketListenerManager().processServerPacket(packet, players)) return;
|
||||
// work out if the packet needs to be sent individually due to server-side translating
|
||||
final SendablePacket sendablePacket = GROUPED_PACKET ? new CachedPacket(packet) : packet;
|
||||
players.forEach(player -> {
|
||||
|
|
Loading…
Reference in New Issue