Making some helpers in our api module so we don't duplicate lots of code in our implementations(modules)

Added UserConnectEvent & UserDisconnectEvent

threadSafe in PacketListeners removed.
This commit is contained in:
retrooper committed 2022-03-18 18:26:33 +01:00
1 parent 747a1a73c4
commit b89ad2e128
30 files changed
+390 -187

No files matched your search

@@ -22,7 +22,8 @@ public final class PacketEvents {
private static PacketEventsAPI<?> API;
//Put these variable names anywhere else, they are really only for the injectors
public static String IDENTIFIER, ENCODER_NAME, DECODER_NAME, CONNECTION_HANDLER_NAME, SERVER_CHANNEL_HANDLER_NAME;
public static String IDENTIFIER, ENCODER_NAME, DECODER_NAME, CONNECTION_HANDLER_NAME, SERVER_CHANNEL_HANDLER_NAME,
TIMEOUT_HANDLER_NAME;
public static PacketEventsAPI<?> getAPI() {
return API;
@@ -55,13 +55,7 @@ public class EventManager {
lastUsedWrapper = ((ProtocolPacketEvent<?>) event).getLastUsedWrapper();
}
try {
if (isPacketEvent && listener.isThreadSafe()) {
//Pass a "cloned" event to this listener.
((ProtocolPacketEvent<?>)event).clone().call(listener);
}
else {
event.call(listener);
}
event.call(listener);
} catch (Throwable t) {
PacketEvents.getAPI().getLogger().log(Level.WARNING, "PacketEvents caught an unhandled exception while calling your listener.", t);
}
@@ -76,13 +70,13 @@ public class EventManager {
}
}
public PacketListenerCommon registerListener(PacketListener listener, PacketListenerPriority priority, boolean readOnly, boolean threadSafe) {
PacketListenerCommon packetListenerAbstract = listener.asAbstract(priority, readOnly, threadSafe);
public PacketListenerCommon registerListener(PacketListener listener, PacketListenerPriority priority, boolean readOnly) {
PacketListenerCommon packetListenerAbstract = listener.asAbstract(priority, readOnly);
return registerListener(packetListenerAbstract);
}
public PacketListenerCommon registerListener(PacketListenerReflect listener, PacketListenerPriority priority, boolean readOnly, boolean threadSafe) {
PacketListenerCommon packetListenerAbstract = listener.asAbstract(priority, readOnly, threadSafe);
public PacketListenerCommon registerListener(PacketListenerReflect listener, PacketListenerPriority priority, boolean readOnly) {
PacketListenerCommon packetListenerAbstract = listener.asAbstract(priority, readOnly);
return registerListener(packetListenerAbstract);
}
@@ -19,8 +19,8 @@
package com.github.retrooper.packetevents.event;
public interface PacketListener {
default PacketListenerAbstract asAbstract(PacketListenerPriority priority, boolean readOnly, boolean threadSafe) {
return new PacketListenerAbstract(priority, readOnly, threadSafe) {
default PacketListenerAbstract asAbstract(PacketListenerPriority priority, boolean readOnly) {
return new PacketListenerAbstract(priority, readOnly) {
@Override
public void onPlayerInject(PlayerInjectEvent event) {
PacketListener.this.onPlayerInject(event);
@@ -32,8 +32,13 @@ public interface PacketListener {
}
@Override
public void onPlayerEject(PlayerEjectEvent event) {
PacketListener.this.onPlayerEject(event);
public void onUserConnect(UserConnectEvent event) {
PacketListener.this.onUserConnect(event);
}
@Override
public void onUserDisconnect(UserDisconnectEvent event) {
PacketListener.this.onUserDisconnect(event);
}
@Override
@@ -59,9 +64,11 @@ public interface PacketListener {
default void onPostPlayerInject(PostPlayerInjectEvent event) {
}
default void onPlayerEject(PlayerEjectEvent event) {
default void onUserConnect(UserConnectEvent event) {
}
default void onUserDisconnect(UserDisconnectEvent event) {
}
default void onPacketReceive(PacketReceiveEvent event) {
}
@@ -27,16 +27,16 @@ public abstract class PacketListenerAbstract extends PacketListenerCommon {
super(priority);
}
public PacketListenerAbstract(PacketListenerPriority priority, boolean readOnly, boolean threadSafe) {
super(priority, readOnly, threadSafe);
public PacketListenerAbstract(PacketListenerPriority priority, boolean readOnly) {
super(priority, readOnly);
}
public PacketListenerAbstract(PacketListenerPriority priority, Map<Byte, List<Method>> methods) {
super(priority, methods);
}
public PacketListenerAbstract(PacketListenerPriority priority, Map<Byte, List<Method>> methods, boolean readOnly, boolean threadSafe) {
super(priority, methods, readOnly, threadSafe);
public PacketListenerAbstract(PacketListenerPriority priority, Map<Byte, List<Method>> methods, boolean readOnly) {
super(priority, methods, readOnly);
}
public PacketListenerAbstract() {
@@ -31,17 +31,16 @@ import java.util.Map;
public abstract class PacketListenerCommon {
protected final Map<Byte, List<Method>> methods;
private final PacketListenerPriority priority;
private boolean readOnly, threadSafe;
private boolean readOnly;
public PacketListenerCommon(PacketListenerPriority priority) {
this.priority = priority;
this.methods = null;
}
public PacketListenerCommon(PacketListenerPriority priority, boolean readOnly, boolean threadSafe) {
public PacketListenerCommon(PacketListenerPriority priority, boolean readOnly) {
this.priority = priority;
this.methods = null;
this.readOnly = readOnly;
this.threadSafe = threadSafe;
}
public PacketListenerCommon(PacketListenerPriority priority, Map<Byte, List<Method>> methods) {
@@ -49,11 +48,10 @@ public abstract class PacketListenerCommon {
this.methods = methods;
}
public PacketListenerCommon(PacketListenerPriority priority, Map<Byte, List<Method>> methods, boolean readOnly, boolean threadSafe) {
public PacketListenerCommon(PacketListenerPriority priority, Map<Byte, List<Method>> methods, boolean readOnly) {
this.priority = priority;
this.methods = methods;
this.readOnly = readOnly;
this.threadSafe = threadSafe;
}
public PacketListenerCommon() {
@@ -73,21 +71,16 @@ public abstract class PacketListenerCommon {
this.readOnly = readOnly;
}
public boolean isThreadSafe() {
return threadSafe;
}
public void setThreadSafe(boolean threadSafe) {
this.threadSafe = threadSafe;
}
public void onPlayerInject(PlayerInjectEvent event) {
}
public void onPostPlayerInject(PostPlayerInjectEvent event) {
}
public void onPlayerEject(PlayerEjectEvent event) {
public void onUserConnect(UserConnectEvent event) {
}
public void onUserDisconnect(UserDisconnectEvent event) {
}
void onPacketReceive(PacketReceiveEvent event) {
@@ -21,9 +21,9 @@ package com.github.retrooper.packetevents.event;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
@Deprecated
public interface PacketListenerReflect {
default PacketListenerAbstract asAbstract(PacketListenerPriority priority, boolean readOnly, boolean threadSafe) {
default PacketListenerAbstract asAbstract(PacketListenerPriority priority, boolean readOnly) {
Map<Byte, List<Method>> methods = new HashMap<>();
for (byte i = 0; i < 6; i++) {
methods.put(i, new ArrayList<>());
@@ -40,33 +40,40 @@ public interface PacketListenerReflect {
List<Method> eventMethods = methods.get((byte) 1);
eventMethods.add(method);
methods.put((byte) 1, eventMethods);
} else if (parameterType.equals(PlayerEjectEvent.class)) {
}
else if (parameterType.equals(UserConnectEvent.class)) {
List<Method> eventMethods = methods.get((byte) 2);
eventMethods.add(method);
methods.put((byte) 2, eventMethods);
} else if (parameterType.equals(PacketReceiveEvent.class)) {
}
else if (parameterType.equals(UserDisconnectEvent.class)) {
List<Method> eventMethods = methods.get((byte) 3);
eventMethods.add(method);
methods.put((byte) 3, eventMethods);
} else if (parameterType.equals(PacketSendEvent.class)) {
}
else if (parameterType.equals(PacketReceiveEvent.class)) {
List<Method> eventMethods = methods.get((byte) 4);
eventMethods.add(method);
methods.put((byte) 4, eventMethods);
} else if (parameterType.equals(PacketSendEvent.class)) {
List<Method> eventMethods = methods.get((byte) 5);
eventMethods.add(method);
methods.put((byte) 5, eventMethods);
} else if (parameterType.equals(PacketEvent.class)) {
//Add to all
for (byte i = 0; i < 6; i++) {
for (byte i = 0; i < 7; i++) {
List<Method> eventMethods = methods.get(i);
eventMethods.add(method);
methods.put(i, eventMethods);
}
} else {
List<Method> eventMethods = methods.get((byte) 5);
List<Method> eventMethods = methods.get((byte) 6);
eventMethods.add(method);
methods.put((byte) 5, eventMethods);
methods.put((byte) 6, eventMethods);
}
}
}
return new PacketListenerAbstract(priority, methods, readOnly, threadSafe) {
return new PacketListenerAbstract(priority, methods, readOnly) {
private void callEventByIndex(byte index, PacketEvent event) {
if (methods != null) {
List<Method> targets = methods.get(index);
@@ -91,24 +98,29 @@ public interface PacketListenerReflect {
}
@Override
public void onPlayerEject(PlayerEjectEvent event) {
callEventByIndex((byte) 2, event);
public void onUserConnect(UserConnectEvent event) {
callEventByIndex((byte)2, event);
}
@Override
public void onUserDisconnect(UserDisconnectEvent event) {
callEventByIndex((byte)3, event);
}
@Override
public void onPacketReceive(PacketReceiveEvent event) {
callEventByIndex((byte) 3, event);
}
@Override
public void onPacketSend(PacketSendEvent event) {
callEventByIndex((byte) 4, event);
}
@Override
public void onPacketEventExternal(PacketEvent event) {
public void onPacketSend(PacketSendEvent event) {
callEventByIndex((byte) 5, event);
}
@Override
public void onPacketEventExternal(PacketEvent event) {
callEventByIndex((byte) 6, event);
}
};
}
}
@@ -37,7 +37,7 @@ import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
public abstract class ProtocolPacketEvent<T> extends PacketEvent implements PlayerEvent<T>, CancellableEvent {
public abstract class ProtocolPacketEvent<T> extends PacketEvent implements PlayerEvent<T>, CancellableEvent, UserEvent {
private final Object channel;
private final ConnectionState connectionState;
private final User user;
@@ -98,7 +98,7 @@ public abstract class ProtocolPacketEvent<T> extends PacketEvent implements Play
return (InetSocketAddress) ChannelHelper.remoteAddress(channel);
}
@NotNull
@Override
public User getUser() {
return user;
}
@@ -29,14 +29,13 @@ public abstract class SimplePacketListenerAbstract extends PacketListenerCommon
super(priority);
}
public SimplePacketListenerAbstract(PacketListenerPriority priority, boolean readOnly, boolean threadSafe) {
super(priority, readOnly, threadSafe);
public SimplePacketListenerAbstract(PacketListenerPriority priority, boolean readOnly) {
super(priority, readOnly);
}
public SimplePacketListenerAbstract(PacketListenerPriority priority, Map<Byte, List<Method>> methods,
boolean readOnly,
boolean threadSafe) {
super(priority, methods, readOnly, threadSafe);
boolean readOnly) {
super(priority, methods, readOnly);
}
public SimplePacketListenerAbstract() {
@@ -18,22 +18,19 @@
package com.github.retrooper.packetevents.event;
import org.jetbrains.annotations.NotNull;
import com.github.retrooper.packetevents.protocol.player.User;
/**
* The {@code PlayerEjectEvent} event is fired whenever a player is ejected.
* This class implements {@link CancellableEvent} and {@link PlayerEvent}.
*
* @author retrooper
* @since 1.6.9
*/
//TODO Remove as its never called
public final class PlayerEjectEvent extends PacketEvent implements CancellableEvent, PlayerEvent<Object> {
private final Object player;
public class UserConnectEvent extends PacketEvent implements CancellableEvent, UserEvent{
private final User user;
private boolean cancelled;
public PlayerEjectEvent(Object player) {
this.player = player;
public UserConnectEvent(User user) {
this.user = user;
}
@Override
public User getUser() {
return user;
}
@Override
@@ -42,25 +39,13 @@ public final class PlayerEjectEvent extends PacketEvent implements CancellableEv
}
@Override
public void setCancelled(boolean value) {
cancelled = value;
}
/**
* This method returns the bukkit player object of the player being ejected.
* The player object is guaranteed to NOT be null.
*
* @return Ejected player.
*/
@NotNull
@Override
public Object getPlayer() {
return player;
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
@Override
public void call(PacketListenerCommon listener) {
listener.onPlayerEject(this);
listener.onUserConnect(this);
}
@Override
@@ -0,0 +1,39 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2021 retrooper and contributors
*
* 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 3 of the License, or
* (at your option) any later version.
*
* 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.event;
import com.github.retrooper.packetevents.protocol.player.User;
public class UserDisconnectEvent extends PacketEvent implements UserEvent {
private final User user;
public UserDisconnectEvent(User user) {
this.user = user;
}
@Override
public User getUser() {
return user;
}
@Override
public void call(PacketListenerCommon listener) {
listener.onUserDisconnect(this);
}
}
@@ -0,0 +1,31 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2021 retrooper and contributors
*
* 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 3 of the License, or
* (at your option) any later version.
*
* 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.event;
import com.github.retrooper.packetevents.protocol.player.User;
/**
* Event that involves users.
*
* @author retrooper
* @since 2.0.0
*/
public interface UserEvent {
User getUser();
}
@@ -46,7 +46,7 @@ public class InternalPacketListener extends PacketListenerAbstract {
}
public InternalPacketListener(PacketListenerPriority priority) {
super(priority, true, false);
super(priority, true);
}
@Override
@@ -0,0 +1,94 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2021 retrooper and contributors
*
* 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 3 of the License, or
* (at your option) any later version.
*
* 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.util;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.event.UserDisconnectEvent;
import com.github.retrooper.packetevents.exception.PacketProcessException;
import com.github.retrooper.packetevents.manager.protocol.ProtocolManager;
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
import com.github.retrooper.packetevents.protocol.player.User;
import org.jetbrains.annotations.Nullable;
public class PacketEventsImplHelper {
public static void handleClientBoundPacket(Object channel, User user, Object player, Object buffer) throws PacketProcessException {
int preProcessIndex = ByteBufHelper.readerIndex(buffer);
PacketSendEvent packetSendEvent = EventCreationUtil.createSendEvent(channel, user, player, buffer);
int processIndex = ByteBufHelper.readerIndex(buffer);
PacketEvents.getAPI().getEventManager().callEvent(packetSendEvent, () -> {
ByteBufHelper.readerIndex(buffer, processIndex);
});
if (!packetSendEvent.isCancelled()) {
if (packetSendEvent.getLastUsedWrapper() != null) {
ByteBufHelper.clear(packetSendEvent.getByteBuf());
packetSendEvent.getLastUsedWrapper().writeVarInt(packetSendEvent.getPacketId());
packetSendEvent.getLastUsedWrapper().write();
}
ByteBufHelper.readerIndex(buffer, preProcessIndex);
} else {
//Make the buffer unreadable for the next handlers
ByteBufHelper.clear(buffer);
}
if (packetSendEvent.hasPostTasks()) {
for (Runnable task : packetSendEvent.getPostTasks()) {
task.run();
}
}
}
public static void handleServerBoundPacket(Object channel, User user, Object player, Object buffer) throws PacketProcessException {
int preProcessIndex = ByteBufHelper.readerIndex(buffer);
PacketReceiveEvent packetReceiveEvent = EventCreationUtil.createReceiveEvent(channel, user, player, buffer);
int processIndex = ByteBufHelper.readerIndex(buffer);
PacketEvents.getAPI().getEventManager().callEvent(packetReceiveEvent, () -> {
ByteBufHelper.readerIndex(buffer, processIndex);
});
if (!packetReceiveEvent.isCancelled()) {
if (packetReceiveEvent.getLastUsedWrapper() != null) {
ByteBufHelper.clear(packetReceiveEvent.getByteBuf());
packetReceiveEvent.getLastUsedWrapper().writeVarInt(packetReceiveEvent.getPacketId());
packetReceiveEvent.getLastUsedWrapper().write();
}
ByteBufHelper.readerIndex(buffer, preProcessIndex);
} else {
//Make the buffer unreadable for the next handlers
ByteBufHelper.clear(buffer);
}
if (packetReceiveEvent.hasPostTasks()) {
for (Runnable task : packetReceiveEvent.getPostTasks()) {
task.run();
}
}
}
public static void handleDisconnection(Object channel, @Nullable String username) {
User user = ProtocolManager.USERS.get(channel);
if (user != null) {
UserDisconnectEvent disconnectEvent = new UserDisconnectEvent(user);
PacketEvents.getAPI().getEventManager().callEvent(disconnectEvent);
ProtocolManager.USERS.remove(user.getChannel());
}
if (username != null) {
ProtocolManager.CHANNELS.remove(username);
}
}
}
@@ -143,6 +143,7 @@ public class BungeePacketEventsBuilder {
PacketEvents.DECODER_NAME = "pe-decoder-" + id;
PacketEvents.CONNECTION_HANDLER_NAME = "pe-connection-handler-" + id;
PacketEvents.SERVER_CHANNEL_HANDLER_NAME = "pe-connection-initializer-" + id;
PacketEvents.TIMEOUT_HANDLER_NAME = "pe-timeout-handler-" + id;
injector.inject();
@@ -23,11 +23,13 @@ import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.util.EventCreationUtil;
import io.github.retrooper.packetevents.injector.ServerConnectionInitializer;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@ChannelHandler.Sharable
@@ -78,4 +80,10 @@ public class PacketDecoder extends MessageToMessageDecoder<ByteBuf> {
super.exceptionCaught(ctx, cause);
//}
}
@Override
public void channelInactive(@NotNull ChannelHandlerContext ctx) throws Exception {
ServerConnectionInitializer.destroyChannel(ctx.channel());
super.channelInactive(ctx);
}
}
@@ -19,6 +19,9 @@
package io.github.retrooper.packetevents.injector;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.event.UserConnectEvent;
import com.github.retrooper.packetevents.event.UserDisconnectEvent;
import com.github.retrooper.packetevents.manager.protocol.ProtocolManager;
import com.github.retrooper.packetevents.protocol.ConnectionState;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.protocol.player.UserProfile;
@@ -27,19 +30,30 @@ import io.github.retrooper.packetevents.handlers.PacketEncoder;
import io.netty.channel.Channel;
public class ServerConnectionInitializer {
public static void initChannel(Channel channel, PacketDecoder decoder, PacketEncoder encoder) {
//This can be called on connection refactors. Not specifically on channel initialization,
public static void prepareChannel(Channel channel, PacketDecoder decoder, PacketEncoder encoder) {
channel.pipeline().addBefore("packet-decoder", PacketEvents.DECODER_NAME, decoder);
channel.pipeline().addBefore("packet-encoder", PacketEvents.ENCODER_NAME, encoder);
}
//This is ONLY called whenever the connection starts.
public static void initChannel(Channel channel, ConnectionState state) {
User user = new User(channel, state, null, new UserProfile(null, null));
UserConnectEvent connectEvent = new UserConnectEvent(user);
PacketEvents.getAPI().getEventManager().callEvent(connectEvent);
if (connectEvent.isCancelled()) {
channel.unsafe().closeForcibly();
return;
}
PacketDecoder decoder = new PacketDecoder(user);
PacketEncoder encoder = new PacketEncoder(user);
initChannel(channel, decoder, encoder);
prepareChannel(channel, decoder, encoder);
}
public static void destroyChannel(Channel channel) {
User user = ProtocolManager.USERS.get(channel);
UserDisconnectEvent disconnectEvent = new UserDisconnectEvent(user);
PacketEvents.getAPI().getEventManager().callEvent(disconnectEvent);
channel.pipeline().remove(PacketEvents.DECODER_NAME);
channel.pipeline().remove(PacketEvents.ENCODER_NAME);
}
@@ -47,6 +61,6 @@ public class ServerConnectionInitializer {
public static void reloadChannel(Channel channel) {
PacketDecoder decoder = (PacketDecoder) channel.pipeline().remove(PacketEvents.DECODER_NAME);
PacketEncoder encoder = (PacketEncoder) channel.pipeline().remove(PacketEvents.ENCODER_NAME);
initChannel(channel, decoder, encoder);
prepareChannel(channel, decoder, encoder);
}
}
@@ -90,6 +90,7 @@ public class NettyPacketEventsBuilder {
PacketEvents.DECODER_NAME = "pe-decoder-" + data.getName().toLowerCase();
PacketEvents.CONNECTION_HANDLER_NAME = "pe-connection-handler-" + data.getName().toLowerCase();
PacketEvents.SERVER_CHANNEL_HANDLER_NAME = "pe-connection-initializer-" + data.getName().toLowerCase();
PacketEvents.TIMEOUT_HANDLER_NAME = "pe-timeout-handler-" + data.getName().toLowerCase();
injector.inject();
loaded = true;
@@ -21,6 +21,8 @@ package io.github.retrooper.packetevents;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.event.PacketListenerPriority;
import com.github.retrooper.packetevents.event.SimplePacketListenerAbstract;
import com.github.retrooper.packetevents.event.UserConnectEvent;
import com.github.retrooper.packetevents.event.UserDisconnectEvent;
import com.github.retrooper.packetevents.event.simple.PacketPlayReceiveEvent;
import com.github.retrooper.packetevents.event.simple.PacketPlaySendEvent;
import com.github.retrooper.packetevents.netty.channel.ChannelHelper;
@@ -68,7 +70,7 @@ public class PacketEventsPlugin extends JavaPlugin {
PacketEvents.getAPI().getSettings().debug(false).bStats(true).checkForUpdates(false);
PacketEvents.getAPI().init();
SimplePacketListenerAbstract listener = new SimplePacketListenerAbstract(PacketListenerPriority.HIGH,
true, false) {
true) {
@Override
public void onPacketPlayReceive(PacketPlayReceiveEvent event) {
User user = event.getUser();
@@ -77,6 +79,7 @@ public class PacketEventsPlugin extends JavaPlugin {
System.out.println("Running 10 seconds later");
WrapperPlayClientChatMessage chatMessage = new WrapperPlayClientChatMessage(event);
if (chatMessage.getMessage().equalsIgnoreCase("mrmcyeet")) {
event.setCancelled(true);
Particle particle = new Particle(ParticleTypes.ANGRY_VILLAGER);
Vector3d position = SpigotDataHelper
.fromBukkitLocation(((Player) event.getPlayer()).getLocation())
@@ -183,6 +186,16 @@ public class PacketEventsPlugin extends JavaPlugin {
System.out.println("Delayed " + chatMessage.getChatComponentJson());
}
}
@Override
public void onUserConnect(UserConnectEvent event) {
System.out.println("User: (host-name) " + event.getUser().getAddress().getHostString() + " connected...");
}
@Override
public void onUserDisconnect(UserDisconnectEvent event) {
System.out.println("User: (host-name) " + event.getUser().getAddress().getHostString() + " disconnected...");
}
};
//PacketEvents.getAPI().getEventManager().registerListener(listener);
}
@@ -23,6 +23,7 @@ import com.github.retrooper.packetevents.event.PostPlayerInjectEvent;
import com.github.retrooper.packetevents.manager.protocol.ProtocolManager;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.util.PacketEventsImplHelper;
import io.github.retrooper.packetevents.injector.SpigotChannelInjector;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -37,10 +38,13 @@ public class InternalBukkitListener implements Listener {
Player player = e.getPlayer();
SpigotChannelInjector injector = (SpigotChannelInjector) PacketEvents.getAPI().getInjector();
//By accessing user with the player object, we ensure that a valid user is cached.
//In the spigot PlayerManager impl, if there was no user cached,
//we will create one with help of the Player object.
User user = PacketEvents.getAPI().getPlayerManager().getUser(player);
//By accessing the client version with the player object, we should ensure the client version is valid.
//In the spigot PlayerManager impl, we ask protocol translation dependencies for the version
//if we failed to catch it.(shouldn't ever happen really)
//TODO With Via we might have to run this a tick AFTER join event (atleast when via & viabackwards & rewind are present)
//TODO Confirm this.
ClientVersion version = PacketEvents.getAPI().getPlayerManager().getClientVersion(player);
injector.updatePlayer(player);
@@ -54,6 +58,6 @@ public class InternalBukkitListener implements Listener {
Object channel = PacketEvents.getAPI().getPlayerManager().getChannel(player);
//When we receive LOGIN_SUCCESS, we cache username with their channel.
//Here we clean that up.
ProtocolManager.CHANNELS.remove(player.getName());
PacketEventsImplHelper.handleDisconnection(channel, player.getName());
}
}
@@ -88,11 +88,13 @@ public class SpigotPacketEventsBuilder {
public void load() {
if (!loaded) {
//Resolve server version and cache
PacketEvents.IDENTIFIER = "pe-" + plugin.getName().toLowerCase();
PacketEvents.ENCODER_NAME = "pe-encoder-" + plugin.getName().toLowerCase();
PacketEvents.DECODER_NAME = "pe-decoder-" + plugin.getName().toLowerCase();
PacketEvents.CONNECTION_HANDLER_NAME = "pe-connection-handler-" + plugin.getName().toLowerCase();
PacketEvents.SERVER_CHANNEL_HANDLER_NAME = "pe-connection-initializer-" + plugin.getName().toLowerCase();
String id = plugin.getName().toLowerCase();
PacketEvents.IDENTIFIER = "pe-" + id;
PacketEvents.ENCODER_NAME = "pe-encoder-" + id;
PacketEvents.DECODER_NAME = "pe-decoder-" + id;
PacketEvents.CONNECTION_HANDLER_NAME = "pe-connection-handler-" + id;
PacketEvents.SERVER_CHANNEL_HANDLER_NAME = "pe-connection-initializer-" + id;
PacketEvents.TIMEOUT_HANDLER_NAME = "pe-timeout-handler-" + id;
try {
SpigotReflectionUtil.init();
CustomPipelineUtil.init();
@@ -138,7 +138,7 @@ public class SpigotChannelInjectorLatest implements ChannelInjector {
else if (pipeline.get("floodgate-init") != null) {
pipeline.addAfter("floodgate-init", PacketEvents.CONNECTION_HANDLER_NAME, new ServerChannelHandlerLatest());
}
//Otherwise, we just don't care and make sure we are last.
//Otherwise, make sure we are first.
else {
pipeline.addFirst(PacketEvents.CONNECTION_HANDLER_NAME, new ServerChannelHandlerLatest());
}
@@ -19,6 +19,8 @@
package io.github.retrooper.packetevents.injector.latest.connection;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.event.UserConnectEvent;
import com.github.retrooper.packetevents.event.UserDisconnectEvent;
import com.github.retrooper.packetevents.manager.protocol.ProtocolManager;
import com.github.retrooper.packetevents.netty.channel.ChannelHelper;
import com.github.retrooper.packetevents.protocol.ConnectionState;
@@ -49,6 +51,12 @@ public class ServerConnectionInitializerLatest {
return;
}
User user = new User(channel, connectionState, null, new UserProfile(null, null));
UserConnectEvent connectEvent = new UserConnectEvent(user);
PacketEvents.getAPI().getEventManager().callEvent(connectEvent);
if (connectEvent.isCancelled()) {
channel.unsafe().closeForcibly();
return;
}
ProtocolManager.USERS.put(channel, user);
try {
channel.pipeline().addAfter("splitter", PacketEvents.DECODER_NAME, new PacketDecoderLatest(user));
@@ -75,6 +83,12 @@ public class ServerConnectionInitializerLatest {
!(channel instanceof NioSocketChannel)) {
return;
}
User user = ProtocolManager.USERS.get(channel);
if (user == null) {
return;
}
UserDisconnectEvent disconnectEvent = new UserDisconnectEvent(user);
PacketEvents.getAPI().getEventManager().callEvent(disconnectEvent);
ChannelHandler viaDecoder = channel.pipeline().get("decoder");
if (ViaVersionUtil.isAvailable() && ViaVersionUtil.getBukkitDecodeHandlerClass().equals(viaDecoder.getClass())) {
ReflectionObject reflectViaDecoder = new ReflectionObject(viaDecoder);
@@ -104,7 +118,7 @@ public class ServerConnectionInitializerLatest {
reflectViaDecoder.write(ByteToMessageDecoder.class, 0, newDecoderModern);
}
} else if (ClassUtil.getClassSimpleName(decoder.getClass()).equals("PacketDecoderLatest")
|| ClassUtil.getClassSimpleName(decoder.getClass()).equals("PacketDecoderModern")) {
|| ClassUtil.getClassSimpleName(decoder.getClass()).equals("PacketDecoderModern")) {
//Possibly another instance of packetevents has already injected into ViaVersion.
//Let us try to remove our own decoder without breaking the other instance.
ReflectionObject reflectDecoder = new ReflectionObject(decoder);
@@ -19,15 +19,12 @@
package io.github.retrooper.packetevents.injector.latest.handlers;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.exception.PacketProcessException;
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
import com.github.retrooper.packetevents.protocol.ConnectionState;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.util.EventCreationUtil;
import com.github.retrooper.packetevents.util.ExceptionUtil;
import com.github.retrooper.packetevents.util.PacketEventsImplHelper;
import io.github.retrooper.packetevents.injector.PacketCompressionUtil;
import io.github.retrooper.packetevents.injector.latest.connection.ServerConnectionInitializerLatest;
import io.github.retrooper.packetevents.util.SpigotReflectionUtil;
import io.github.retrooper.packetevents.util.viaversion.CustomPipelineUtil;
import io.netty.buffer.ByteBuf;
@@ -60,40 +57,29 @@ public class PacketDecoderLatest extends ByteToMessageDecoder {
skipDoubleTransform = decoder.skipDoubleTransform;
}
public void read(ChannelHandlerContext ctx, ByteBuf input, List<Object> output) throws Exception {
if (skipDoubleTransform) {
skipDoubleTransform = false;
output.add(input.retain());
}
public void read(ChannelHandlerContext ctx, ByteBuf input, List<Object> out) throws Exception {
ByteBuf transformed = ctx.alloc().buffer().writeBytes(input);
try {
if (skipDoubleTransform) {
skipDoubleTransform = false;
out.add(transformed.retain());
}
boolean doRecompression =
handleCompressionOrder(ctx, transformed);
int preProcessIndex = transformed.readerIndex();
PacketReceiveEvent packetReceiveEvent = EventCreationUtil.createReceiveEvent(ctx.channel(), user, player, transformed);
int processIndex = transformed.readerIndex();
PacketEvents.getAPI().getEventManager().callEvent(packetReceiveEvent, () -> {
transformed.readerIndex(processIndex);
});
if (!packetReceiveEvent.isCancelled()) {
if (packetReceiveEvent.getLastUsedWrapper() != null) {
ByteBufHelper.clear(packetReceiveEvent.getByteBuf());
packetReceiveEvent.getLastUsedWrapper().writeVarInt(packetReceiveEvent.getPacketId());
packetReceiveEvent.getLastUsedWrapper().write();
}
transformed.readerIndex(preProcessIndex);
PacketEventsImplHelper.handleServerBoundPacket(ctx.channel(), user, player, transformed);
if (transformed.isReadable()) {
if (doRecompression) {
PacketCompressionUtil.recompress(ctx, transformed);
skipDoubleTransform = true;
}
output.add(transformed.retain());
out.add(transformed.retain());
}
if (packetReceiveEvent.hasPostTasks()) {
for (Runnable task : packetReceiveEvent.getPostTasks()) {
task.run();
}
if (doRecompression && transformed.isReadable()) {
PacketCompressionUtil.recompress(ctx, transformed);
skipDoubleTransform = true;
}
} finally {
}
finally {
transformed.release();
}
}
@@ -138,12 +124,6 @@ public class PacketDecoderLatest extends ByteToMessageDecoder {
}
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
ServerConnectionInitializerLatest.destroyChannel(ctx.channel());
super.channelInactive(ctx);
}
private boolean handleCompressionOrder(ChannelHandlerContext ctx, ByteBuf buffer) {
if (handledCompression) return false;
@@ -18,25 +18,20 @@
package io.github.retrooper.packetevents.injector.latest.handlers;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.exception.PacketProcessException;
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
import com.github.retrooper.packetevents.protocol.ConnectionState;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.util.EventCreationUtil;
import com.github.retrooper.packetevents.util.ExceptionUtil;
import com.github.retrooper.packetevents.util.PacketEventsImplHelper;
import io.github.retrooper.packetevents.util.SpigotReflectionUtil;
import io.github.retrooper.packetevents.util.viaversion.CustomPipelineUtil;
import io.github.retrooper.packetevents.util.viaversion.ViaVersionUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.handler.codec.MessageToByteEncoder;
import org.bukkit.entity.Player;
import java.lang.reflect.InvocationTargetException;
@ChannelHandler.Sharable
public class PacketEncoderLatest extends MessageToByteEncoder<Object> {
public User user;
@@ -47,52 +42,31 @@ public class PacketEncoderLatest extends MessageToByteEncoder<Object> {
this.user = user;
}
public void read(ChannelHandlerContext ctx, ByteBuf buffer) throws Exception {
int preProcessIndex = buffer.readerIndex();
PacketSendEvent packetSendEvent = EventCreationUtil.createSendEvent(ctx.channel(), user, player, buffer);
int processIndex = buffer.readerIndex();
PacketEvents.getAPI().getEventManager().callEvent(packetSendEvent, () -> {
buffer.readerIndex(processIndex);
});
if (!packetSendEvent.isCancelled()) {
if (packetSendEvent.getLastUsedWrapper() != null) {
ByteBufHelper.clear(packetSendEvent.getByteBuf());
packetSendEvent.getLastUsedWrapper().writeVarInt(packetSendEvent.getPacketId());
packetSendEvent.getLastUsedWrapper().write();
}
buffer.readerIndex(preProcessIndex);
} else {
//Make the buffer unreadable for the next handlers
buffer.clear();
}
if (packetSendEvent.hasPostTasks()) {
for (Runnable task : packetSendEvent.getPostTasks()) {
task.run();
}
}
}
@Override
protected void encode(ChannelHandlerContext ctx, Object o, ByteBuf out) throws Exception {
if (!(o instanceof ByteBuf)) {
//Convert NMS object to bytes, so we can process it right away.
if (vanillaEncoder == null) return;
CustomPipelineUtil.callEncode(vanillaEncoder, ctx, o, out);
//Failed to translate it into ByteBuf form (which we can process)
if (!out.isReadable()) return;
} else {
ByteBuf in = (ByteBuf) o;
//Empty packets?
if (!in.isReadable()) return;
out.writeBytes(in);
}
read(ctx, out);
PacketEventsImplHelper.handleClientBoundPacket(ctx.channel(), user, player, out);
}
@Override
public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
PacketEventsImplHelper.handleDisconnection(ctx.channel(), null);
super.close(ctx, promise);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if (ViaVersionUtil.isAvailable()
&& ExceptionUtil.isException(cause, InvocationTargetException.class)) {
return;
}
super.exceptionCaught(ctx, cause);
//Check if the minecraft server will already print our exception for us.
if (ExceptionUtil.isException(cause, PacketProcessException.class)
@@ -19,6 +19,8 @@
package io.github.retrooper.packetevents.injector.legacy.connection;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.event.UserConnectEvent;
import com.github.retrooper.packetevents.event.UserDisconnectEvent;
import com.github.retrooper.packetevents.manager.protocol.ProtocolManager;
import com.github.retrooper.packetevents.netty.channel.ChannelHelper;
import com.github.retrooper.packetevents.protocol.ConnectionState;
@@ -34,10 +36,17 @@ import java.util.NoSuchElementException;
public class ServerConnectionInitializerLegacy {
public static void initChannel(Object ch, ConnectionState connectionState) {
Channel channel = (Channel) ch;
if (!(channel instanceof NioSocketChannel)) {
//1.7 has no EpollSocketChannel
if (!(channel instanceof NioSocketChannel)) {
return;
}
User user = new User(channel, connectionState, null, new UserProfile(null, null));
UserConnectEvent connectEvent = new UserConnectEvent(user);
PacketEvents.getAPI().getEventManager().callEvent(connectEvent);
if (connectEvent.isCancelled()) {
channel.unsafe().closeForcibly();
return;
}
ProtocolManager.USERS.put(channel, user);
try {
channel.pipeline().addAfter("splitter", PacketEvents.DECODER_NAME, new PacketDecoderLegacy(user));
@@ -51,9 +60,13 @@ public class ServerConnectionInitializerLegacy {
public static void destroyChannel(Object ch) {
Channel channel = (Channel) ch;
//1.7 has no EpollSocketChannel
if (!(channel instanceof NioSocketChannel)) {
return;
}
User user = ProtocolManager.USERS.get(channel);
UserDisconnectEvent disconnectEvent = new UserDisconnectEvent(user);
PacketEvents.getAPI().getEventManager().callEvent(disconnectEvent);
channel.pipeline().remove(PacketEvents.DECODER_NAME);
channel.pipeline().remove(PacketEvents.ENCODER_NAME);
ProtocolManager.USERS.remove(channel);
@@ -114,12 +114,6 @@ public class PacketDecoderLegacy extends MessageToMessageDecoder<ByteBuf> {
}
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
ServerConnectionInitializerLegacy.destroyChannel(ctx.channel());
super.channelInactive(ctx);
}
private boolean handleCompressionOrder(ChannelHandlerContext ctx, ByteBuf buffer) {
if (handledCompression) return false;
int decoderIndex = ctx.pipeline().names().indexOf("decompress");
@@ -20,17 +20,21 @@ package io.github.retrooper.packetevents.injector.legacy.handlers;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.event.UserDisconnectEvent;
import com.github.retrooper.packetevents.exception.PacketProcessException;
import com.github.retrooper.packetevents.manager.protocol.ProtocolManager;
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
import com.github.retrooper.packetevents.protocol.ConnectionState;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.util.EventCreationUtil;
import com.github.retrooper.packetevents.util.ExceptionUtil;
import com.github.retrooper.packetevents.util.PacketEventsImplHelper;
import io.github.retrooper.packetevents.injector.PacketCompressionUtil;
import io.github.retrooper.packetevents.util.SpigotReflectionUtil;
import net.minecraft.util.io.netty.buffer.ByteBuf;
import net.minecraft.util.io.netty.channel.ChannelHandler;
import net.minecraft.util.io.netty.channel.ChannelHandlerContext;
import net.minecraft.util.io.netty.channel.ChannelPromise;
import net.minecraft.util.io.netty.handler.codec.MessageToByteEncoder;
import org.bukkit.entity.Player;
@@ -60,18 +64,19 @@ public class PacketEncoderLegacy extends MessageToByteEncoder<ByteBuf> {
packetSendEvent.getLastUsedWrapper().write();
}
buffer.readerIndex(preProcessIndex);
if (doCompression) {
PacketCompressionUtil.recompress(ctx, buffer);
}
} else {
//Make the buffer unreadable for the next handlers
buffer.clear();
doCompression = false;
}
if (packetSendEvent.hasPostTasks()) {
for (Runnable task : packetSendEvent.getPostTasks()) {
task.run();
}
}
if (doCompression) {
PacketCompressionUtil.recompress(ctx, buffer);
}
}
@Override
@@ -96,9 +101,14 @@ public class PacketEncoderLegacy extends MessageToByteEncoder<ByteBuf> {
return false;
}
@Override
public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
PacketEventsImplHelper.handleDisconnection(ctx.channel(), null);
super.close(ctx, promise);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
//if (!ExceptionUtil.isExceptionContainedIn(cause, PacketEvents.getAPI().getNettyManager().getChannelOperator().getIgnoredHandlerExceptions())) {
super.exceptionCaught(ctx, cause);
//}
//Check if the minecraft server will already print our exception for us.
@@ -24,10 +24,12 @@ import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.util.EventCreationUtil;
import com.velocitypowered.api.proxy.Player;
import io.github.retrooper.packetevents.injector.ServerConnectionInitializer;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@@ -78,4 +80,10 @@ public class PacketDecoder extends MessageToMessageDecoder<ByteBuf> {
super.exceptionCaught(ctx, cause);
//}
}
@Override
public void channelInactive(@NotNull ChannelHandlerContext ctx) throws Exception {
ServerConnectionInitializer.destroyChannel(ctx.channel());
super.channelInactive(ctx);
}
}
@@ -19,6 +19,9 @@
package io.github.retrooper.packetevents.injector;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.event.UserConnectEvent;
import com.github.retrooper.packetevents.event.UserDisconnectEvent;
import com.github.retrooper.packetevents.manager.protocol.ProtocolManager;
import com.github.retrooper.packetevents.protocol.ConnectionState;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.protocol.player.UserProfile;
@@ -27,19 +30,28 @@ import io.github.retrooper.packetevents.handlers.PacketEncoder;
import io.netty.channel.Channel;
public class ServerConnectionInitializer {
public static void initChannel(Channel channel, PacketDecoder decoder, PacketEncoder encoder) {
public static void prepareChannel(Channel channel, PacketDecoder decoder, PacketEncoder encoder) {
channel.pipeline().addBefore("minecraft-decoder", PacketEvents.DECODER_NAME, decoder);
channel.pipeline().addBefore("minecraft-encoder", PacketEvents.ENCODER_NAME, encoder);
}
public static void initChannel(Channel channel, ConnectionState state) {
User user = new User(channel, state, null, new UserProfile(null, null));
UserConnectEvent connectEvent = new UserConnectEvent(user);
PacketEvents.getAPI().getEventManager().callEvent(connectEvent);
if (connectEvent.isCancelled()) {
channel.unsafe().closeForcibly();
return;
}
PacketDecoder decoder = new PacketDecoder(user);
PacketEncoder encoder = new PacketEncoder(user);
initChannel(channel, decoder, encoder);
prepareChannel(channel, decoder, encoder);
}
public static void destroyChannel(Channel channel) {
User user = ProtocolManager.USERS.get(channel);
UserDisconnectEvent disconnectEvent = new UserDisconnectEvent(user);
PacketEvents.getAPI().getEventManager().callEvent(disconnectEvent);
channel.pipeline().remove(PacketEvents.DECODER_NAME);
channel.pipeline().remove(PacketEvents.ENCODER_NAME);
}
@@ -47,6 +59,6 @@ public class ServerConnectionInitializer {
public static void reloadChannel(Channel channel) {
PacketDecoder decoder = (PacketDecoder) channel.pipeline().remove(PacketEvents.DECODER_NAME);
PacketEncoder encoder = (PacketEncoder) channel.pipeline().remove(PacketEvents.ENCODER_NAME);
initChannel(channel, decoder, encoder);
prepareChannel(channel, decoder, encoder);
}
}
@@ -129,7 +129,7 @@ public class VelocityPacketEventsBuilder {
PacketEvents.DECODER_NAME = "pe-decoder-" + id;
PacketEvents.CONNECTION_HANDLER_NAME = "pe-connection-handler-" + id;
PacketEvents.SERVER_CHANNEL_HANDLER_NAME = "pe-connection-initializer-" + id;
PacketEvents.TIMEOUT_HANDLER_NAME = "pe-timeout-handler-" + id;
injector.inject();
loaded = true;