Compare commits

..
20 Commits
Author SHA1 Message Date
retrooper bd1e4e7e6d 1.7.9 release
Update!
2020-11-23 13:00:47 +01:00
retrooper feda5b96b6 * PostPlayerInjectEvent added, called after successful injection 2020-11-23 12:58:54 +01:00
retrooper 809396ff21 1.7.9 release 2020-11-23 12:36:11 +01:00
retrooper 2428487eb1 * UpdateChecker bugs fixed, PEVersion#equals(PEVersion) now works 2020-11-23 08:41:20 +01:00
retrooper df0c769111 * VersionLookupUtils prioritization changed up, 1. ViaVersion, 2. ProtocolLib, 3. ProtocolSupport 2020-11-23 07:45:22 +01:00
retrooper 5e0cd75bb0 attempt to fix protoclsupport/viaversion erroring when asked for protocolversion, but not successful 2020-11-22 17:57:55 +01:00
retrooper b21e6b4a67 * PacketEvents injecting is done with event priority on LOW for late injections, and ClientVersion resolving with HIGH event priority 2020-11-22 17:46:56 +01:00
retrooper bfc3aa7ad8 * PacketEvents.onJoin priority set to HIGHEST 2020-11-22 17:27:19 +01:00
retrooper 72458ddfd2 * PacketEvents failing to inject you and doesn't call any events for your player (RARE BUG) fixed. This bug could only happened if you had injectEarly set to true. 2020-11-22 17:07:21 +01:00
retrooper a8a04b137b * ClientVersion unresolvable on 1.16.3 and 1.16.4 bug FIXED 2020-11-22 16:40:39 +01:00
retrooper 4e11df1fc7 Update EventManagerDynamic.java 2020-11-21 21:19:48 +01:00
Retrooper c3ab35bd6b * reverted to old entity finder util 2020-11-21 13:11:20 +08:00
retrooper af1025da1f caching entity ID im wrappedpacketoutentityteleport now 2020-11-21 04:54:16 +01:00
retrooper f2ce9eacb1 WrappedPacketOutEntityTeleport Entity ID always 0 2020-11-21 04:50:20 +01:00
retrooper 27307e034b Merge branch 'dev' of https://github.com/retrooper/packetevents into dev 2020-11-20 11:00:16 +01:00
retrooper 808357735f * PacketEventsLoadFailureException now includes the cause exception.
* VersionLookupUtils now prioritizes ProtocolSupport over ViaVersion
2020-11-20 10:59:02 +01:00
retrooper ece8b6d395 WrappedPacketOutEntity Entity ID 0 Bug fix 2020-11-20 04:12:22 +01:00
retrooper 8643e14900 WrappedPacketOutEntity Entity ID 0 bug fix 2020-11-20 04:10:49 +01:00
retrooper cbfd52d926 * PacketEvents-Bungee utilities removed and bungee server startup error fix.
* PacketEventsMethodInvokeException now actually includes the cause of the error.
* PacketEventsNMSCachedEntityNotFoundException.java renamed to PacketEventsEntityByIDNotFoundException.java.
* Reflection methods to do with fields DEPRECATED, use the WrappedPacket utility class.
* ClassUtil.getClassSimpleName(Class<?> cls) potential bug fix, if a class was named "null" it would have not cached  do to a string null check.
2020-11-19 17:47:27 +01:00
retrooper e266e43d19 * WrappedPacketOutChat constructor
* pom.xml stopped compiling ProtocolSupport
* All event classes now cache packet ID
2020-11-19 10:00:07 +01:00
29 changed files with 324 additions and 269 deletions

No files matched your search

+2 -1
View File
@@ -6,7 +6,7 @@
<groupId>io.github.retrooper</groupId>
<artifactId>packetevents</artifactId>
<version>1.7.8</version>
<version>1.7.9</version>
<!-- You can build the project with this: "mvn clean compile assembly:single" -->
<build>
@@ -134,6 +134,7 @@
<groupId>com.github.ProtocolSupport</groupId>
<artifactId>ProtocolSupport</artifactId>
<version>3d24efeda6</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -24,8 +24,8 @@
package io.github.retrooper.packetevents;
import io.github.retrooper.packetevents.bungee.BungeePluginMessageListener;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.event.impl.PostPlayerInjectEvent;
import io.github.retrooper.packetevents.exceptions.PacketEventsLoadFailureException;
import io.github.retrooper.packetevents.packetmanager.PacketManager;
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
@@ -52,14 +52,13 @@ import org.bukkit.plugin.Plugin;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public final class PacketEvents implements Listener {
private static final PacketEventsAPI packetEventsAPI = new PacketEventsAPI();
private static final PacketEvents instance = new PacketEvents();
private static final ArrayList<Plugin> plugins = new ArrayList<>(1);
private static boolean loading, loaded, initialized, initializing, uninitializing;
private static final PEVersion version = new PEVersion(1, 7, 8);
private static final PEVersion version = new PEVersion(1, 7, 9);
private static PacketEventsSettings settings = new PacketEventsSettings();
/**
* General executor service, basically for anything that the packet executor service doesn't do.
@@ -109,7 +108,7 @@ public final class PacketEvents implements Listener {
WrappedPacket.loadAllWrappers();
} catch (Exception ex) {
loading = false;
throw new PacketEventsLoadFailureException();
throw new PacketEventsLoadFailureException(ex);
}
loaded = true;
loading = false;
@@ -163,16 +162,14 @@ public final class PacketEvents implements Listener {
}
if (settings.shouldCheckForUpdates()) {
Future<?> future =
PacketEvents.generalExecutorService
.submit(() -> new UpdateChecker().handleUpdate());
}
PacketEvents.generalExecutorService.execute(new Runnable() {
@Override
public void run() {
new UpdateChecker().handleUpdate();
}
});
if (getAPI().getServerUtils().isBungeeCordEnabled()) {
Bukkit.getMessenger().registerOutgoingPluginChannel(plugins.get(0), "BungeeCord");
Bukkit.getServer().getMessenger().registerIncomingPluginChannel(plugins.get(0), BungeePluginMessageListener.tagName, new BungeePluginMessageListener());
}
initialized = true;
initializing = false;
}
@@ -191,6 +188,7 @@ public final class PacketEvents implements Listener {
if (PacketEvents.getAPI().packetManager.tinyProtocol != null) {
PacketEvents.getAPI().packetManager.tinyProtocol.unregisterChannelHandler();
}
getAPI().getEventManager().unregisterAllListeners();
PacketEvents.generalExecutorService.shutdownNow();
PacketEvents.packetHandlingExecutorService.shutdownNow();
@@ -203,6 +201,18 @@ public final class PacketEvents implements Listener {
return loaded;
}
public static boolean isLoading() {
return loading;
}
public static boolean isInitializing() {
return initializing;
}
public static boolean isUninitializing() {
return uninitializing;
}
public static boolean isInitialized() {
return initialized;
}
@@ -240,25 +250,30 @@ public final class PacketEvents implements Listener {
}
}
@EventHandler(priority = EventPriority.LOW)
@EventHandler(priority = EventPriority.HIGH)
public void onJoin(final PlayerJoinEvent e) {
Object channel = NMSUtils.getChannel(e.getPlayer());
if (PacketEvents.getAPI().getServerUtils().getVersion() == ServerVersion.v_1_7_10) {
ClientVersion version = ClientVersion.getClientVersion(ProtocolVersionAccessor_v_1_7.getProtocolVersion(e.getPlayer()));
PacketEvents.getAPI().getPlayerUtils().clientVersionsMap.put(channel, version);
} else if (VersionLookupUtils.isDependencyAvailable()) {
}
else if(VersionLookupUtils.isDependencyAvailable()) {
int protocolVersion = VersionLookupUtils.getProtocolVersion(e.getPlayer());
ClientVersion version = ClientVersion.getClientVersion(protocolVersion);
PacketEvents.getAPI().getPlayerUtils().clientVersionsMap.put(channel, version);
}
//Waiting for the BungeeCord server to send their plugin message with your version,
if (!PacketEvents.getSettings().shouldInjectEarly()) {
try {
PacketEvents.getAPI().packetManager.injectPlayer(e.getPlayer());
PacketEvents.getAPI().getEventManager().callEvent(new PostPlayerInjectEvent(e.getPlayer()));
} catch (Exception ex) {
e.getPlayer().kickPlayer("There was an issue injecting you. Please try again!");
}
}
else {
PacketEvents.getAPI().getEventManager().callEvent(new PostPlayerInjectEvent(e.getPlayer()));
}
}
@@ -24,8 +24,8 @@
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.eventtypes.CancellableEvent;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.event.eventtypes.CancellableEvent;
import io.github.retrooper.packetevents.event.eventtypes.PlayerEvent;
import io.github.retrooper.packetevents.packettype.PacketType;
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
@@ -38,6 +38,7 @@ public final class PacketReceiveEvent extends PacketEvent implements Cancellable
private final Player player;
private final Object packet;
private boolean cancelled;
private byte packetID = -1;
public PacketReceiveEvent(final Player player, final Object packet) {
this.player = player;
@@ -46,6 +47,7 @@ public final class PacketReceiveEvent extends PacketEvent implements Cancellable
/**
* Get the packet sender
*
* @return player
*/
@Override
@@ -56,6 +58,7 @@ public final class PacketReceiveEvent extends PacketEvent implements Cancellable
/**
* Get the packet's name (NMS packet class simple name).
* The class simple name is cached.
*
* @return Name of the packet
*/
public String getPacketName() {
@@ -64,6 +67,7 @@ public final class PacketReceiveEvent extends PacketEvent implements Cancellable
/**
* Get the raw packet object
*
* @return packet object
*/
public Object getNMSPacket() {
@@ -72,10 +76,14 @@ public final class PacketReceiveEvent extends PacketEvent implements Cancellable
/**
* Get the ID of the packet
*
* @return packet id
*/
public byte getPacketId() {
return PacketType.Client.packetIds.getOrDefault(packet.getClass(), (byte) -1);
if (packetID == -1) {
packetID = PacketType.Client.packetIds.getOrDefault(packet.getClass(), (byte) -1);
}
return packetID;
}
@Override
@@ -38,6 +38,7 @@ public final class PacketSendEvent extends PacketEvent implements CancellableEve
private final Player player;
private final Object packet;
private boolean cancelled;
private byte packetID = -1;
public PacketSendEvent(final Player player, final Object packet) {
this.player = player;
@@ -65,7 +66,10 @@ public final class PacketSendEvent extends PacketEvent implements CancellableEve
* @return packet id
*/
public byte getPacketId() {
return PacketType.Server.packetIds.getOrDefault(packet.getClass(), (byte) -1);
if(packetID == -1) {
packetID = PacketType.Server.packetIds.getOrDefault(packet.getClass(), (byte) -1);
}
return packetID;
}
/**
@@ -33,6 +33,7 @@ public class PacketStatusEvent extends PacketEvent implements CancellableEvent {
private final Object channel;
private final Object packet;
private boolean cancelled;
private byte packetID = -1;
public PacketStatusEvent(final Object channel, final Object packet) {
this.channel = channel;
@@ -68,7 +69,10 @@ public class PacketStatusEvent extends PacketEvent implements CancellableEvent {
* @return packet id
*/
public byte getPacketId() {
return PacketType.Status.packetIds.getOrDefault(packet.getClass(), (byte) -1);
if (packetID == -1) {
packetID = PacketType.Status.packetIds.getOrDefault(packet.getClass(), (byte) -1);
}
return packetID;
}
@Override
@@ -33,7 +33,7 @@ import org.bukkit.entity.Player;
public class PostPacketReceiveEvent extends PacketEvent implements PlayerEvent {
private final Player player;
private final Object packet;
private byte packetID = -1;
public PostPacketReceiveEvent(final Player player, final Object packet) {
this.player = player;
this.packet = packet;
@@ -70,6 +70,9 @@ public class PostPacketReceiveEvent extends PacketEvent implements PlayerEvent {
* @return packet id
*/
public byte getPacketId() {
return PacketType.Client.packetIds.getOrDefault(packet.getClass(), (byte) -1);
if(packetID == -1) {
packetID = PacketType.Client.packetIds.getOrDefault(packet.getClass(), (byte) -1);
}
return packetID;
}
}
@@ -33,6 +33,7 @@ import org.bukkit.entity.Player;
public class PostPacketSendEvent extends PacketEvent implements PlayerEvent {
private final Player player;
private final Object packet;
private byte packetID = -1;
public PostPacketSendEvent(final Player player, final Object packet) {
this.player = player;
@@ -41,6 +42,7 @@ public class PostPacketSendEvent extends PacketEvent implements PlayerEvent {
/**
* Get the packet sender
*
* @return player
*/
@Override
@@ -51,6 +53,7 @@ public class PostPacketSendEvent extends PacketEvent implements PlayerEvent {
/**
* Get the packet's name (NMS packet class simple name).
* The class simple name is cached.
*
* @return Name of the packet
*/
public String getPacketName() {
@@ -59,6 +62,7 @@ public class PostPacketSendEvent extends PacketEvent implements PlayerEvent {
/**
* Get the raw packet object
*
* @return packet object
*/
public Object getNMSPacket() {
@@ -67,9 +71,13 @@ public class PostPacketSendEvent extends PacketEvent implements PlayerEvent {
/**
* Get the ID of the packet
*
* @return packet id
*/
public byte getPacketId() {
return PacketType.Server.packetIds.getOrDefault(packet.getClass(), (byte) -1);
if (packetID == -1) {
packetID = PacketType.Server.packetIds.getOrDefault(packet.getClass(), (byte) -1);
}
return packetID;
}
}
@@ -22,34 +22,31 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.bungee;
package io.github.retrooper.packetevents.event.impl;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteStreams;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.event.eventtypes.PlayerEvent;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.player.ClientVersion;
import org.bukkit.entity.Player;
import org.bukkit.plugin.messaging.PluginMessageListener;
import java.util.UUID;
public class BungeePluginMessageListener implements PluginMessageListener {
public static String tagName = "packetevents:channel";
@Override
public void onPluginMessageReceived(String tag, Player player, byte[] bytes) {
if (tag.equals(tagName)) {
ByteArrayDataInput in = ByteStreams.newDataInput(bytes);
if (in.readUTF().equals("version")) {
String uuidString = in.readUTF();
Object channel = NMSUtils.getChannel(player);
short protocolVersion = in.readShort();
ClientVersion version = ClientVersion.getClientVersion(protocolVersion);
PacketEvents.getAPI().getPlayerUtils().clientVersionsMap.put(channel, version);
}
}
public class PostPlayerInjectEvent extends PacketEvent implements PlayerEvent {
private final Player player;
public PostPlayerInjectEvent(Player player) {
this.player = player;
}
@Override
public Player getPlayer() {
return player;
}
public Object getChannel() {
return NMSUtils.getChannel(player);
}
public ClientVersion getClientVersion() {
return PacketEvents.getAPI().getPlayerUtils().clientVersionsMap.get(getChannel());
}
}
@@ -66,10 +66,7 @@ class EventManagerDynamic {
}
} catch (Exception ex) {
throw new PacketEventsMethodInvokeException("PacketEvents " +
"failed to call an event method in the " +
"dynamic packet listener. Event type: "
+ ClassUtil.getClassSimpleName(event.getClass()));
ex.printStackTrace();
}
if (event instanceof CancellableEvent) {
@@ -29,13 +29,12 @@ import io.github.retrooper.packetevents.event.PacketListenerDynamic;
import io.github.retrooper.packetevents.event.impl.PacketReceiveEvent;
import io.github.retrooper.packetevents.event.priority.PacketEventPriority;
import io.github.retrooper.packetevents.packettype.PacketType;
import io.github.retrooper.packetevents.packetwrappers.in.chat.WrappedPacketInChat;
import io.github.retrooper.packetevents.utils.player.ClientVersion;
import io.github.retrooper.packetevents.packetwrappers.in.useentity.WrappedPacketInUseEntity;
import io.github.retrooper.packetevents.utils.player.ClientHand;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import org.bukkit.plugin.java.JavaPlugin;
public class MainExample extends JavaPlugin {
@Override
public void onLoad() {
PacketEvents.load();
@@ -43,9 +42,10 @@ public class MainExample extends JavaPlugin {
@Override
public void onEnable() {
PacketEvents.getSettings().injectAsync(true).ejectAsync(true)
.backupServerVersion(ServerVersion.v_1_7_10).checkForUpdates(true).injectEarly(true).
packetHandlingThreadCount(1);
PacketEvents.getSettings().injectAsync(true)
.ejectAsync(true).backupServerVersion(ServerVersion.v_1_7_10)
.checkForUpdates(true).injectEarly(true)
.packetHandlingThreadCount(1);
PacketEvents.init(this);
}
@@ -29,7 +29,15 @@ public class PacketEventsLoadFailureException extends RuntimeException {
super(message);
}
public PacketEventsLoadFailureException(String message, Throwable cause) {
super(message, cause);
}
public PacketEventsLoadFailureException() {
this("PacketEvents failed to successfully load...");
}
public PacketEventsLoadFailureException(Throwable cause) {
this("PacketEvents failed to successfully load...", cause);
}
}
@@ -34,8 +34,17 @@ public class PacketEventsMethodInvokeException extends RuntimeException {
super(message);
}
public PacketEventsMethodInvokeException(String message, Throwable cause) {
super(message, cause);
}
public PacketEventsMethodInvokeException(Method method, PacketListener listener) {
this("PacketEvents failed to call the " + method.getName() + " method in "
+ ClassUtil.getClassSimpleName(listener.getClass()));
}
public PacketEventsMethodInvokeException(Method method, PacketListener listener, Throwable cause) {
this("PacketEvents failed to call the " + method.getName() + " method in "
+ ClassUtil.getClassSimpleName(listener.getClass()), cause);
}
}
@@ -122,4 +122,14 @@ public class TinyProtocol {
public void unregisterChannelHandler() {
}
public void handleQueuedKicks() {
if (NettyPacketManager.v1_7_nettyMode) {
TinyProtocol7 tp7 = (TinyProtocol7) tinyProt;
tp7.handleQueuedKicks();
} else {
TinyProtocol8 tp8 = (TinyProtocol8) tinyProt;
tp8.handleQueuedKicks();
}
}
}
@@ -3,6 +3,7 @@ package io.github.retrooper.packetevents.packetmanager.tinyprotocol;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.packetmanager.tinyprotocol.Reflection.FieldAccessor;
import io.github.retrooper.packetevents.packetmanager.tinyprotocol.Reflection.MethodInvoker;
import io.github.retrooper.packetevents.packetwrappers.out.kickdisconnect.WrappedPacketOutKickDisconnect;
import net.minecraft.util.com.google.common.collect.Lists;
import net.minecraft.util.com.google.common.collect.MapMaker;
import net.minecraft.util.com.mojang.authlib.GameProfile;
@@ -15,6 +16,7 @@ import org.bukkit.scheduler.BukkitRunnable;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
@@ -61,6 +63,8 @@ public class TinyProtocol7 {
private ChannelInitializer<Channel> beginInitProtocol;
private ChannelInitializer<Channel> endInitProtocol;
public final ConcurrentLinkedQueue<Channel> queueingChannelKicks = new ConcurrentLinkedQueue<>();
// Current handler name
private final String handlerName;
@@ -195,6 +199,13 @@ public class TinyProtocol7 {
}
}
public void handleQueuedKicks() {
for (Channel channel : queueingChannelKicks) {
Object packet = new WrappedPacketOutKickDisconnect("We failed to inject you. Please try rejoining!").asNMSPacket();
sendPacket(channel, packet);
}
}
private void registerPlayers(Plugin plugin) {
for (Player player : plugin.getServer().getOnlinePlayers()) {
injectPlayer(player);
@@ -355,7 +366,13 @@ public class TinyProtocol7 {
PacketEvents.packetHandlingExecutorService.execute(new Runnable() {
@Override
public void run() {
channel.pipeline().addBefore("packet_handler", handlerName, pi);
try {
channel.pipeline().addBefore("packet_handler", handlerName, pi);
} catch (Exception ex) {
//kick them
Object packet = new WrappedPacketOutKickDisconnect("We unfortunately failed to inject you. Please try rejoining!").asNMSPacket();
sendPacket(channel, packet);
}
}
});
}
@@ -6,6 +6,7 @@ import com.mojang.authlib.GameProfile;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.packetmanager.tinyprotocol.Reflection.FieldAccessor;
import io.github.retrooper.packetevents.packetmanager.tinyprotocol.Reflection.MethodInvoker;
import io.github.retrooper.packetevents.packetwrappers.out.kickdisconnect.WrappedPacketOutKickDisconnect;
import io.netty.channel.*;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@@ -16,6 +17,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
@@ -71,6 +73,8 @@ public class TinyProtocol8 {
private ChannelInitializer<Channel> beginInitProtocol;
private ChannelInitializer<Channel> endInitProtocol;
public final ConcurrentLinkedQueue<Channel> queueingChannelKicks = new ConcurrentLinkedQueue<>();
// Current handler name
private final String handlerName;
@@ -372,7 +376,14 @@ public class TinyProtocol8 {
PacketEvents.packetHandlingExecutorService.execute(new Runnable() {
@Override
public void run() {
channel.pipeline().addBefore("packet_handler", handlerName, pi);
try {
channel.pipeline().addBefore("packet_handler", handlerName, pi);
}
catch(Exception ex) {
//kick them
Object packet = new WrappedPacketOutKickDisconnect("We unfortunately failed to inject you. Please try rejoining!").asNMSPacket();
sendPacket(channel, packet);
}
}
});
}
@@ -486,6 +497,13 @@ public class TinyProtocol8 {
}
}
public void handleQueuedKicks() {
for(Channel channel : queueingChannelKicks) {
Object packet = new WrappedPacketOutKickDisconnect("We failed to inject you. Please try rejoining!").asNMSPacket();
sendPacket(channel, packet);
}
}
/**
* Channel handler that is inserted into the player's channel pipeline, allowing us to intercept sent and received packets.
*
@@ -94,99 +94,42 @@ public class WrappedPacket implements WrapperPacketReader, WrapperPacketWriter {
List<Field> byteFields = getFields(byte.class, declaredFields);
List<Field> shortFields = getFields(short.class, declaredFields);
List<Field> intFields = getFields(int.class, declaredFields);
;
List<Field> longFields = getFields(long.class, declaredFields);
;
List<Field> floatFields = getFields(float.class, declaredFields);
;
List<Field> doubleFields = getFields(double.class, declaredFields);
;
List<Field> stringFields = getFields(String.class, declaredFields);
;
List<Field> boolArrayFields = getFields(boolean[].class, declaredFields);
;
List<Field> byteArrayFields = getFields(byte[].class, declaredFields);
;
List<Field> shortArrayFields = getFields(short[].class, declaredFields);
;
List<Field> intArrayFields = getFields(int[].class, declaredFields);
;
List<Field> longArrayFields = getFields(long[].class, declaredFields);
;
List<Field> floatArrayFields = getFields(float[].class, declaredFields);
;
List<Field> doubleArrayFields = getFields(double[].class, declaredFields);
;
List<Field> stringArrayFields = getFields(String[].class, declaredFields);
;
Field[] tmp = new Field[0];
Map<Class<?>, Field[]> map = new HashMap<>();
if (boolFields != null) {
map.put(boolean.class, boolFields.toArray(tmp));
}
if (byteFields != null) {
map.put(byte.class, byteFields.toArray(tmp));
}
map.put(boolean.class, boolFields.toArray(tmp));
map.put(byte.class, byteFields.toArray(tmp));
map.put(short.class, shortFields.toArray(tmp));
map.put(int.class, intFields.toArray(tmp));
map.put(long.class, longFields.toArray(tmp));
map.put(float.class, floatFields.toArray(tmp));
map.put(double.class, doubleFields.toArray(tmp));
if (shortFields != null) {
map.put(short.class, shortFields.toArray(tmp));
}
if (intFields != null) {
map.put(int.class, intFields.toArray(tmp));
}
if (longFields != null) {
map.put(long.class, longFields.toArray(tmp));
}
if (floatFields != null) {
map.put(float.class, floatFields.toArray(tmp));
}
if (doubleFields != null) {
map.put(double.class, doubleFields.toArray(tmp));
}
if (stringFields != null) {
map.put(String.class, stringFields.toArray(tmp));
}
if (boolArrayFields != null) {
map.put(boolean[].class, boolArrayFields.toArray(tmp));
}
if (byteArrayFields != null) {
map.put(byte[].class, byteArrayFields.toArray(tmp));
}
if (shortArrayFields != null) {
map.put(short[].class, shortArrayFields.toArray(tmp));
}
if (intArrayFields != null) {
map.put(int[].class, intArrayFields.toArray(tmp));
}
if (longArrayFields != null) {
map.put(long[].class, longArrayFields.toArray(tmp));
}
if (floatArrayFields != null) {
map.put(float[].class, floatArrayFields.toArray(tmp));
}
if (doubleArrayFields != null) {
map.put(double[].class, doubleArrayFields.toArray(tmp));
}
if (stringArrayFields != null) {
map.put(String[].class, stringArrayFields.toArray(tmp));
}
map.put(String.class, stringFields.toArray(tmp));
map.put(boolean[].class, boolArrayFields.toArray(tmp));
map.put(byte[].class, byteArrayFields.toArray(tmp));
map.put(short[].class, shortArrayFields.toArray(tmp));
map.put(int[].class, intArrayFields.toArray(tmp));
map.put(long[].class, longArrayFields.toArray(tmp));
map.put(float[].class, floatArrayFields.toArray(tmp));
map.put(double[].class, doubleArrayFields.toArray(tmp));
map.put(String[].class, stringArrayFields.toArray(tmp));
fieldCache.put(packetClass, map);
}
this.packet = packet;
@@ -503,8 +446,7 @@ public class WrappedPacket implements WrapperPacketReader, WrapperPacketWriter {
if (!typeFields.isEmpty()) {
cached.put(type, typeFields.toArray(new Field[0]));
cachedFields = cached.get(type);
}
else {
} else {
throw new WrapperFieldNotFoundException("The class you are trying to read fields from does not contain any fields!");
}
}
@@ -517,6 +459,32 @@ public class WrappedPacket implements WrapperPacketReader, WrapperPacketWriter {
throw new WrapperFieldNotFoundException(packetClass, type, index);
}
public boolean doesObjectExist(int index, Class<?> type) {
Map<Class<?>, Field[]> cached = fieldCache.get(packetClass);
if (cached != null) {
Field[] cachedFields = cached.get(type);
if (cachedFields == null) {
List<Field> typeFields = new ArrayList<>();
for (Field f : packetClass.getDeclaredFields()) {
f.setAccessible(true);
if (f.getType().equals(type)) {
typeFields.add(f);
}
}
if (!typeFields.isEmpty()) {
cached.put(type, typeFields.toArray(new Field[0]));
cachedFields = cached.get(type);
} else {
return false;
}
}
if (cachedFields == null) {
return false;
} else return index <= cachedFields.length + 1;
}
return false;
}
public Object[] readObjectArray(int index, Class<?> type) {
if (type.equals(String.class)) {
return readStringArray(index);
@@ -26,11 +26,12 @@ package io.github.retrooper.packetevents.packetwrappers.in.useentity;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.player.ClientHand;
import io.github.retrooper.packetevents.utils.reflection.SubclassUtil;
import org.bukkit.entity.Entity;
public final class WrappedPacketInUseEntity extends WrappedPacket {
private static Class<?> enumEntityUseActionClass;
private static Class<?> enumEntityUseActionClass, enumHandClass;
private Entity entity;
private int entityID = -1;
public WrappedPacketInUseEntity(final Object packet) {
@@ -39,10 +40,12 @@ public final class WrappedPacketInUseEntity extends WrappedPacket {
public static void load() {
Class<?> useEntityClass = NMSUtils.getNMSClassWithoutException("PacketPlayInUseEntity");
enumHandClass = NMSUtils.getNMSClassWithoutException("EnumHand");
try {
enumEntityUseActionClass = NMSUtils.getNMSClass("EnumEntityUseAction");
} catch (ClassNotFoundException e) {
//That is fine, it is probably a subclass
assert useEntityClass != null;
enumEntityUseActionClass = SubclassUtil.getSubClass(useEntityClass, "EnumEntityUseAction");
}
}
@@ -65,7 +65,7 @@ public final class WrappedPacketOutChat extends WrappedPacket implements Sendabl
@Deprecated
public WrappedPacketOutChat(String message) {
this(message, null);
this(message, null, false);
}
public WrappedPacketOutChat(final Object packet) {
@@ -73,13 +73,13 @@ public final class WrappedPacketOutChat extends WrappedPacket implements Sendabl
isListening = true;
}
public WrappedPacketOutChat(String message, UUID uuid) {
this(message, ChatPosition.CHAT, uuid);
public WrappedPacketOutChat(String message, UUID uuid, boolean isJson) {
this(message, ChatPosition.CHAT, uuid, isJson);
}
public WrappedPacketOutChat(String message, ChatPosition chatPosition, UUID uuid) {
public WrappedPacketOutChat(String message, ChatPosition chatPosition, UUID uuid, boolean isJson) {
this.uuid = uuid;
this.message = fromStringToJSON(message);
this.message = isJson ? message : fromStringToJSON(message);
this.chatPosition = chatPosition;
}
@@ -44,7 +44,7 @@ public class WrappedPacketOutEntity extends WrappedPacket implements SendableWra
private Entity entity;
private boolean isListening;
private static Constructor<?> entityPacketConstructor;
private int entityID;
private int entityID = -1;
private double deltaX, deltaY, deltaZ;
private byte pitch, yaw;
private boolean onGround;
@@ -41,7 +41,7 @@ public class WrappedPacketOutEntityTeleport extends WrappedPacket implements Sen
private static final float rotationMultiplier = 256.0F / 360.0F;
private static Constructor<?> constructor;
private Entity entity = null;
private int entityID;
private int entityID = -1;
private double x, y, z;
private float yaw, pitch;
private boolean onGround;
@@ -97,14 +97,10 @@ public class WrappedPacketOutEntityTeleport extends WrappedPacket implements Sen
}
public int getEntityId() {
if (listeningMode) {
if (entityID != -1) {
return readInt(0);
} else {
return entityID = readInt(0);
}
} else {
if (entityID != -1) {
return entityID;
} else {
return entityID = readInt(0);
}
}
@@ -37,38 +37,43 @@ import java.net.URLConnection;
public class UpdateChecker {
public void handleUpdate() {
inform("Checking for an update, please wait...");
PEVersion localVersion = PacketEvents.getVersion();
inform("[PacketEvents] Checking for an update, please wait...");
String line;
try {
String line = readLatestVersion();
PEVersion newVersion = new PEVersion(line);
if (localVersion.isOlder(newVersion)) {
inform("There is an update available for the PacketEvents API! Your build: (" + localVersion.toString() + ") | Update: (" + newVersion.toString() + ")");
}
else if(localVersion.equals(newVersion)) {
inform("You are on the latest released version of PacketEvents. Your build: (" + newVersion.toString() + ")");
}
else if(localVersion.isNewer(newVersion)) {
inform("You are on a dev or pre released build of PacketEvents. Your build: (" + localVersion.toString() + ") | Last released build: (" + newVersion.toString() + ")");
}
line = readLatestVersion();
} catch (IOException exception) {
report("We failed to find the latest released version of PacketEvents. Your build: (" + localVersion.toString() + ")");
report("[PacketEvents] We failed to find the latest released version of PacketEvents. Your build: (" + localVersion.toString() + ")");
return;
}
PEVersion newVersion = new PEVersion(line);
if (localVersion.isOlder(newVersion)) {
inform("[PacketEvents] There is an update available for the PacketEvents API! Your build: (" + localVersion.toString() + ") | Latest released build: (" + newVersion.toString() + ")");
} else if (localVersion.isNewer(newVersion)) {
inform("[PacketEvents] You are on a dev or pre released build of PacketEvents. Your build: (" + localVersion.toString() + ") | Latest released build: (" + newVersion.toString() + ")");
}
else if (localVersion.equals(newVersion)) {
inform("[PacketEvents] You are on the latest released version of PacketEvents. (" + newVersion.toString() + ")");
}
else {
report("[PacketEvents] Something went wrong while checking for an update. Your build: (" + localVersion.toString() + ") | Latest released build: (" + newVersion.toString() + ")");
}
}
private void inform(String message) {
Bukkit.getLogger().info("[PacketEvents] " + message);
Bukkit.getLogger().info(message);
}
private void report(String message) {
Bukkit.getLogger().info(ChatColor.DARK_RED + "[PacketEvents] " + message);
Bukkit.getLogger().info(ChatColor.DARK_RED + message);
}
private String readLatestVersion() throws IOException {
URLConnection connection = new URL("https://api.spigotmc.org/legacy/update.php?resource=80279").openConnection();
connection.addRequestProperty("User-Agent", "Mozilla/4.0");
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
return reader.readLine();
String line = reader.readLine();
reader.close();
return line;
}
}
@@ -25,7 +25,6 @@
package io.github.retrooper.packetevents.utils.entityfinder;
import io.github.retrooper.packetevents.annotations.Nullable;
import io.github.retrooper.packetevents.exceptions.PacketEventsNMSCachedEntityNotFoundException;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import org.bukkit.Bukkit;
@@ -36,105 +35,87 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public final class EntityFinderUtils {
@Nullable
public static ServerVersion version;
private static Class<?> worldServerClass;
private static Class<?> craftWorldClass;
private static Class<?> entityClass;
private static Method getEntityByIdMethod;
private static Method craftWorldGetHandle;
private static Method getBukkitEntity;
private static boolean isServerVersion_v_1_8_x;
public static void load() {
isServerVersion_v_1_8_x = version.isHigherThan(ServerVersion.v_1_7_10) && version.isLowerThan(ServerVersion.v_1_9);
try {
worldServerClass = NMSUtils.getNMSClass("WorldServer");
craftWorldClass = NMSUtils.getOBCClass("CraftWorld");
entityClass = NMSUtils.getNMSClass("Entity");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
getEntityByIdMethod = worldServerClass.getMethod(isServerVersion_v_1_8_x ? "a" : "getEntity", int.class);
getEntityByIdMethod = worldServerClass.getMethod((version.getProtocolVersion() == (short) 47)
? "a" : "getEntity", int.class);
craftWorldGetHandle = craftWorldClass.getMethod("getHandle");
getBukkitEntity = entityClass.getMethod("getBukkitEntity");
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
public static Object getNMSEntityById(final int id) {
for (final World world : Bukkit.getWorlds()) {
final Object entity = getNMSEntityByIdWithWorld(world, id);
if (entity != null) {
return entity;
}
}
//Entity has not been found in the NMS entity cache map...
for(World world : Bukkit.getWorlds()) {
for(Entity entity : world.getEntities()) {
if(entity.getEntityId() == id) {
return NMSUtils.getNMSEntity(entity);
}
}
}
throw new PacketEventsNMSCachedEntityNotFoundException(id);
}
/**
* Get an entity by their ID.
*
* @param id
* @return Entity
*/
public static Entity getEntityById(final int id) {
for (final World world : Bukkit.getWorlds()) {
final Object entity = getNMSEntityByIdWithWorld(world, id);
final Entity entity = getEntityByIdWithWorld(world, id);
if (entity != null) {
return NMSUtils.getBukkitEntity(entity);
return entity;
}
}
//Entity has not been found in the NMS entity cache map...
for(World world : Bukkit.getWorlds()) {
for(Entity entity : world.getEntities()) {
if(entity.getEntityId() == id) {
return entity;
}
}
}
throw new PacketEventsNMSCachedEntityNotFoundException(id);
}
public static Object getNMSEntityByIdWithWorld(final World world, final int id) {
if (world == null) {
return null;
} else if (craftWorldClass == null) {
throw new IllegalStateException("PacketEvents failed to locate the CraftWorld class.");
}
Object worldServer = null;
try {
worldServer = craftWorldGetHandle.invoke(world);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
try {
return getEntityByIdMethod.invoke(worldServer, id);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
return null;
}
/**
* Get an entity by their ID, guaranteed to be in the specified world.
*
* @param world
* @param id
* @return Entity
*/
@Nullable
public static Entity getEntityByIdWithWorld(final World world, final int id) {
Object nmsEntity = getNMSEntityByIdWithWorld(world, id);
return NMSUtils.getBukkitEntity(nmsEntity);
if (world == null) {
return null;
}
else if(craftWorldClass == null) {
throw new IllegalStateException("PacketEvents failed to locate the CraftWorld class.");
}
Object craftWorld = craftWorldClass.cast(world);
Object worldServer = null;
try {
worldServer = craftWorldGetHandle.invoke(craftWorld);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
Object nmsEntity = null;
try {
nmsEntity = getEntityByIdMethod.invoke(worldServer, id);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
if (nmsEntity == null) {
return null;
}
try {
return (Entity) getBukkitEntity.invoke(nmsEntity);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}
@@ -170,14 +170,6 @@ public final class NMSUtils {
return "f";
}
public static Object getNMSEntityById(final int id) {
return EntityFinderUtils.getNMSEntityById(id);
}
public static Object getNMSEntityByIdWithWorld(final World world, final int id) {
return EntityFinderUtils.getNMSEntityByIdWithWorld(world, id);
}
@Nullable
public static Entity getEntityById(final int id) {
return EntityFinderUtils.getEntityById(id);
@@ -22,14 +22,9 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.exceptions;
package io.github.retrooper.packetevents.utils.player;
public class PacketEventsNMSCachedEntityNotFoundException extends RuntimeException {
public PacketEventsNMSCachedEntityNotFoundException(String message) {
super(message);
}
public PacketEventsNMSCachedEntityNotFoundException(int entityID) {
this("PacketEvents failed to find an entity with ID " + entityID + "!");
}
public enum ClientHand {
MAIN_HAND,
OFF_HAND;
}
@@ -64,8 +64,8 @@ public enum ClientVersion {
private final int protocolVersion;
private static final int lowestSupportedProtocolVersion = 5;
private static final int highestSupportedProtocolVersion = 753;
private static final int lowestSupportedProtocolVersion = LOWER_THAN_SUPPORTED_VERSIONS.protocolVersion;
private static final int highestSupportedProtocolVersion = HIGHER_THAN_SUPPORTED_VERSIONS.protocolVersion;
ClientVersion(int protocolVersion) {
this.protocolVersion = protocolVersion;
@@ -106,14 +106,12 @@ public enum ClientVersion {
return version;
}
}
if (protocolVersion < lowestSupportedProtocolVersion) {
if (protocolVersion <= lowestSupportedProtocolVersion) {
return LOWER_THAN_SUPPORTED_VERSIONS;
} else if (protocolVersion > highestSupportedProtocolVersion) {
} else if (protocolVersion >= highestSupportedProtocolVersion) {
return HIGHER_THAN_SUPPORTED_VERSIONS;
} else if (protocolVersion > lowestSupportedProtocolVersion
&& protocolVersion < highestSupportedProtocolVersion) {
} else {
return ANY_PRE_RELEASE_VERSION;
}
return UNRESOLVED;
}
}
@@ -31,10 +31,12 @@ public class ClassUtil {
private static final Map<String, String> classSimpleNameCache = new HashMap<>();
public static String getClassSimpleName(Class<?> cls) {
String simpleClassName = classSimpleNameCache.get(cls.getName());
if(simpleClassName == null) {
String name = simpleClassName = cls.getSimpleName();
classSimpleNameCache.put(cls.getName(), name);
final String className = cls.getName();
final String simpleClassName;
if (!classSimpleNameCache.containsKey(className)) {
classSimpleNameCache.put(className, simpleClassName = cls.getSimpleName());
} else {
simpleClassName = classSimpleNameCache.get(className);
}
return simpleClassName;
}
@@ -32,6 +32,7 @@ import java.util.Arrays;
public final class Reflection {
//FIELDS
@Deprecated
public static Field[] getFields(Class<?> cls) {
Field[] declaredFields = cls.getDeclaredFields();
for (Field f : declaredFields) {
@@ -40,6 +41,7 @@ public final class Reflection {
return declaredFields;
}
@Deprecated
public static Field getField(final Class<?> cls, final String name) {
for (final Field f : getFields(cls)) {
if (f.getName().equals(name)) {
@@ -49,6 +51,7 @@ public final class Reflection {
return null;
}
@Deprecated
public static Field getField(final Class<?> cls, final Class<?> dataType, final int index) {
int currentIndex = 0;
for (final Field f : getFields(cls)) {
@@ -61,6 +64,7 @@ public final class Reflection {
return null;
}
@Deprecated
public static Field getField(final Class<?> cls, final int index) {
return getFields(cls)[index];
}
@@ -24,6 +24,7 @@
package io.github.retrooper.packetevents.utils.server;
import java.util.Arrays;
import java.util.List;
@@ -67,44 +68,54 @@ public class PEVersion {
}
public boolean isNewer(PEVersion other) {
//Our equals check is quite cheap.
//If they are equal, then they aren't older nor newer
if (equals(other)) {
return false;
}
//The version length if guaranteed to be 4.
for (int i = 0; i < version.length; i++) {
if (version[i] > other.getVersionAsByteArray()[i]) {
if (version[i] > other.getVersion()[i]) {
return true;
} else if (version[i] < other.getVersionAsByteArray()[i]) {
} else if (version[i] < other.getVersion()[i]) {
return false;
}
}
//If they are equal, they aren't newer nor older.
return false;
}
public boolean equals(PEVersion version) {
return Arrays.equals(getVersion(), version.getVersion());
}
public boolean isOlder(PEVersion other) {
//Our equals check is quite cheap.
//If they are equal, then they aren't older nor newer
if (equals(other)) {
return false;
}
//The version length if guaranteed to be 4.
for (int i = 0; i < version.length; i++) {
if (version[i] < other.getVersionAsByteArray()[i]) {
if (version[i] < other.getVersion()[i]) {
return true;
} else if (version[i] > other.getVersionAsByteArray()[i]) {
} else if (version[i] > other.getVersion()[i]) {
return false;
}
}
//If they are equal, they aren't newer nor older.
return false;
}
// TODO: Remove "AsByteArray"
public final int[] getVersionAsByteArray() {
public final int[] getVersion() {
return version;
}
// TODO: Remove "AsByteArray"
public final int[] getVersionAsByteArrayShortened() {
public final int[] getVersionShortened() {
int length = 2;
if(version[2] != 0) {
length++;
if (version[2] != 0) {
length++;
}
if(version[3] != 0) {
length++;
if (version[3] != 0) {
length++;
}
int[] shortened = new int[length];
System.arraycopy(version, 0, shortened, 0, length);
@@ -121,7 +132,7 @@ public class PEVersion {
@Override
public String toString() {
int[] shortenedVersion = getVersionAsByteArrayShortened();
int[] shortenedVersion = getVersionShortened();
StringBuilder text = new StringBuilder();
for (int v : shortenedVersion) {
text.append(".").append(v);
@@ -31,17 +31,18 @@ import org.bukkit.entity.Player;
public class VersionLookupUtils {
public static boolean isDependencyAvailable() {
return ViaVersionLookupUtils.isAvailable() || ProtocolSupportVersionLookupUtils.isAvailable()
|| ProtocolLibVersionLookupUtils.isAvailable();
return ViaVersionLookupUtils.isAvailable()
|| ProtocolLibVersionLookupUtils.isAvailable()
|| ProtocolSupportVersionLookupUtils.isAvailable();
}
public static int getProtocolVersion(Player player) {
if (ViaVersionLookupUtils.isAvailable()) {
return ViaVersionLookupUtils.getProtocolVersion(player);
} else if (ProtocolSupportVersionLookupUtils.isAvailable()) {
return ProtocolSupportVersionLookupUtils.getProtocolVersion(player);
} else if (ProtocolLibVersionLookupUtils.isAvailable()) {
return ProtocolLibVersionLookupUtils.getProtocolVersion(player);
} else if (ProtocolSupportVersionLookupUtils.isAvailable()) {
return ProtocolSupportVersionLookupUtils.getProtocolVersion(player);
}
return -1;
}