Compare commits

...
39 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
retrooper c9d58e08c9 1.7.8 release 2020-11-17 15:34:56 +01:00
retrooper 24eda2b3a5 1.7.8 release
* Official 1.16.4 support
ClientVersion.v_1_16_4, ServerVersion.v_1_16_4 created
* Unfortunately PacketEvents.getSettings().useProtocolLibIfAvailable(boolean) setting most likely won't be coming back
* Bungee client version resolving bug fixed
* Recommended to have ViaVersion, ProtocolSupport or ProtocolLib on your spigot server, as PacketEvents makes use of them to resolve client version ONLY if they are available.
They are required on the spigot server ONLY if you have a bungee network.
* Interruption of PacketEvents.stop() protected
2020-11-17 15:32:37 +01:00
retrooper 38c4f3234d Merge pull request #66 from retrooper/dev
1.7.7 release
2020-11-16 17:55:11 +01:00
retrooper e94b6f24dc 1.7.7 release
* Accessing Entity by ID on servers with more than one world ERROR FIX
* In the WrappedPacketOutChat(String, ChatPosition, UUID) constructor, the String(=message) shouldn't be passed in JSON string format, it can be passed in as an ordinary string message!
Example:
WrappedPacketOutChat packet = new WrappedPacketOutChat("Hello", ChatPosition.CHAT, uuid);
2020-11-16 17:52:37 +01:00
retrooper 85dab8eb7a 1.7.6 release
1.7.6 release
2020-11-15 12:48:42 +01:00
retrooper 5fb8634880 * PacketEventsNMSCachedEntityNotFoundException exception created and is thrown when the cached nms entity isn't found.
WrappedPacketOutBlockChange wrapper TODO
2020-11-15 12:08:42 +01:00
retrooper e551421867 Reverted to old legacy event manager code
* Lower event priorities aren't called before higher ones on the legacy event system.
* PacketEvents.getSettings().useProtocolLibIfAvailable temporarily removed, currently unsupported so has been removed.
It is recommended to slowly update to the new event system, the current might get cut off soon!
2020-11-15 11:27:19 +01:00
retrooper 3dfb1ce0b5 * EventManagerLegacy isn't working, about to revert to the old event manager code, keeping this just incase.
When joining the server I instantly get kicked for "Disconnected".
2020-11-15 11:08:25 +01:00
retrooper aca321c332 Small bug fix for event systems
* Using MONITOR event priority now works
2020-11-15 10:36:21 +01:00
retrooper e0f4891a72 * Legacy and Dynamic event system ATTEMPT
API wise working, contains debugs, but UNTESTED!!!
The legacy(last event listener system) has been deprecated!
2020-11-15 10:27:31 +01:00
retrooper 08b207d80a Cleaner errors with PacketEvents
* PacketEventsLoadFailureException exception thrown if PacketEvents fails to load.
* PacketEventsMethodAccessException exception thrown if PacketEvents fails to access a method of a PacketListener for invoking.
* PacketEventsMethodInvokeException exception thrown if an exception is thrown from the invoked method in the PacketListener.
2020-11-15 08:43:29 +01:00
Retrooper 6121349a6f bug fixes
* resolving clientversion on bungee servers issue fixed
* read me cleaned up
* Via and ProtocolSupport utils removed
2020-11-15 15:09:46 +08:00
Retrooper 2b58a9ad97 small bug fixes
* Bungee channel name changed from "packetevents" to "packetevents:channel"
* NPE when accessing player version with viaversion onJoin sometimes
2020-11-14 00:44:55 +08:00
Retrooper 8e922a7676 Merge branch 'dev' of https://github.com/retrooper/packetevents
 Conflicts:
	src/main/java/io/github/retrooper/packetevents/example/MainExample.java
2020-11-13 23:45:49 +08:00
Retrooper 7967b6851f a 2020-11-13 23:42:55 +08:00
retrooper 18b37abf5b Merge pull request #64 from LIWKK/patch-13
Return 0 instead of -1 in blockplace wrapper 1.9
2020-11-11 22:25:49 +01:00
retrooper 53b713f574 Merge pull request #63 from LIWKK/patch-12
Return 0 instead of -1 in blockplace wrapper 1.8
2020-11-11 22:24:58 +01:00
Johannes 655f162272 Return 0 instead of -1 to not fuckup (1.9) 2020-11-11 23:22:01 +02:00
Johannes 686c50a7bb Return 0 instead of -1 to not fuckup other things. 2020-11-11 23:21:14 +02:00
50 changed files with 889 additions and 746 deletions

No files matched your search

+2 -8
View File
@@ -1,14 +1,10 @@
# packetevents
A Spigot packet API with some nice utlities.
A spigot Packet API with some nice utlities.
## About
This packetlistener is **only** supported on Spigot servers and has been tested to work on these Spigot forks: PaperMC, Tuinity
* No dependencies
* Licensed under the MIT license
This API is **only** supported on Spigot servers and has been tested to work on these Spigot forks: Paper, Tuinity, Purpur
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
@@ -16,5 +12,3 @@ Our discord server: https://discord.me/packetevents
[![](https://jitpack.io/v/retrooper/packetevents.svg)](https://jitpack.io/#retrooper/packetevents)
[![](https://jitci.com/gh/retrooper/packetevents/svg)](https://jitci.com/gh/retrooper/packetevents)
+2 -2
View File
@@ -6,7 +6,7 @@
<groupId>io.github.retrooper</groupId>
<artifactId>packetevents</artifactId>
<version>1.7.5</version>
<version>1.7.9</version>
<!-- You can build the project with this: "mvn clean compile assembly:single" -->
<build>
@@ -133,7 +133,7 @@
<dependency>
<groupId>com.github.ProtocolSupport</groupId>
<artifactId>ProtocolSupport</artifactId>
<version>4fdd683</version>
<version>3d24efeda6</version>
<scope>provided</scope>
</dependency>
@@ -24,10 +24,10 @@
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.packetmanager.netty.NettyPacketManager;
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.settings.PacketEventsSettings;
@@ -38,9 +38,11 @@ import io.github.retrooper.packetevents.utils.player.ClientVersion;
import io.github.retrooper.packetevents.utils.server.PEVersion;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import io.github.retrooper.packetevents.utils.versionlookup.VersionLookupUtils;
import io.github.retrooper.packetevents.utils.versionlookup.v_1_7_10.ProtocolVersionAccessor_v_1_7;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerLoginEvent;
@@ -50,19 +52,18 @@ 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 loaded, initialized;
private static final PEVersion version = new PEVersion(1, 7, 5);
private static boolean loading, loaded, initialized, initializing, uninitializing;
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.
/**
* General executor service, basically for anything that the packet executor service doesn't do.
*/
public static ExecutorService generalExecutorService = Executors.newCachedThreadPool();
public static ExecutorService generalExecutorService = Executors.newSingleThreadExecutor();
//Executor used for player injecting/ejecting and for packet processing/event calling
public static ExecutorService packetHandlingExecutorService = Executors.newSingleThreadExecutor();
@@ -86,7 +87,8 @@ public final class PacketEvents implements Listener {
* All PacketEvents' wrappers are setup and do all loading they need to do.
*/
public static void load() {
if (!loaded) {
if (!loaded && !loading) {
loading = true;
ServerVersion version = ServerVersion.getVersion();
WrappedPacket.version = version;
PacketEvent.version = version;
@@ -105,9 +107,11 @@ public final class PacketEvents implements Listener {
WrappedPacket.loadAllWrappers();
} catch (Exception ex) {
throw new IllegalStateException("PacketEvents failed to successfully load...", ex);
loading = false;
throw new PacketEventsLoadFailureException(ex);
}
loaded = true;
loading = false;
}
}
@@ -133,14 +137,14 @@ public final class PacketEvents implements Listener {
*/
public static void init(final Plugin pl, PacketEventsSettings packetEventsSettings) {
load();
if (!initialized) {
if (!initialized && !initializing) {
initializing = true;
settings = packetEventsSettings;
int packetHandlingThreadCount = settings.getPacketHandlingThreadCount();
//if the count is 1 or is invalid
if(packetHandlingThreadCount == 1 || packetHandlingThreadCount < 0) {
if (packetHandlingThreadCount == 1 || packetHandlingThreadCount < 0) {
packetHandlingExecutorService = Executors.newSingleThreadExecutor();
}
else {
} else {
packetHandlingExecutorService = Executors.newFixedThreadPool(packetHandlingThreadCount);
}
plugins.add(pl);
@@ -150,19 +154,24 @@ public final class PacketEvents implements Listener {
PacketEvents.getAPI().packetManager = new PacketManager(plugins.get(0), settings.shouldInjectEarly());
for (final Player p : Bukkit.getOnlinePlayers()) {
getAPI().getPlayerUtils().injectPlayer(p);
try {
getAPI().getPlayerUtils().injectPlayer(p);
} catch (Exception ex) {
p.kickPlayer("Failed to inject you, please rejoin the server!");
}
}
if (settings.shouldCheckForUpdates()) {
PacketEvents.generalExecutorService.execute(() -> 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;
}
}
@@ -170,7 +179,8 @@ public final class PacketEvents implements Listener {
*
*/
public static void stop() {
if (initialized) {
if (initialized && !uninitializing) {
uninitializing = true;
for (Player player : Bukkit.getOnlinePlayers()) {
PacketEvents.getAPI().packetManager.ejectPlayer(player);
}
@@ -178,10 +188,12 @@ 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();
initialized = false;
uninitializing = true;
}
}
@@ -189,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;
}
@@ -214,44 +238,48 @@ public final class PacketEvents implements Listener {
return version;
}
@EventHandler
@EventHandler(priority = EventPriority.LOW)
public void onLogin(PlayerLoginEvent e) {
if (PacketEvents.getSettings().shouldInjectEarly()) {
assert getAPI().packetManager.tinyProtocol != null;
try {
if (getAPI().packetManager.canInject(e.getPlayer())) {
getAPI().packetManager.injectPlayer(e.getPlayer());
}
getAPI().packetManager.injectPlayer(e.getPlayer());
} catch (Exception ex) {
e.disallow(PlayerLoginEvent.Result.KICK_OTHER, "We are unable to inject you. Please try again!");
}
}
}
@EventHandler
@EventHandler(priority = EventPriority.HIGH)
public void onJoin(final PlayerJoinEvent e) {
if (!VersionLookupUtils.hasHandledLoadedDependencies()) {
VersionLookupUtils.handleLoadedDependencies();
}
Object channel = NMSUtils.getChannel(e.getPlayer());
//Waiting for the BungeeCord server to send their plugin message with your version,
//So we leave bungee alone
if (!PacketEvents.getAPI().getServerUtils().isBungeeCordEnabled()) {
if (VersionLookupUtils.isDependencyAvailable()) {
ClientVersion version = ClientVersion.getClientVersion(VersionLookupUtils.getProtocolVersion(e.getPlayer()));
PacketEvents.getAPI().getPlayerUtils().clientVersionsMap.put(channel, version);
}
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()) {
int protocolVersion = VersionLookupUtils.getProtocolVersion(e.getPlayer());
ClientVersion version = ClientVersion.getClientVersion(protocolVersion);
PacketEvents.getAPI().getPlayerUtils().clientVersionsMap.put(channel, version);
}
if (!PacketEvents.getSettings().shouldInjectEarly()) {
if (getAPI().packetManager.canInject(e.getPlayer())) {
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()));
}
}
@EventHandler
@EventHandler(priority = EventPriority.HIGHEST)
public void onQuit(final PlayerQuitEvent e) {
PacketEvents.getAPI().getPlayerUtils().clientVersionsMap.remove(e.getPlayer().getUniqueId());
Object channel = NMSUtils.getChannelNoCache(e.getPlayer());
PacketEvents.getAPI().getPlayerUtils().clientVersionsMap.remove(channel);
}
}
}
@@ -28,5 +28,6 @@ package io.github.retrooper.packetevents.event;
* A Packet listener.
* Implement this interface in your listeners.
*/
@Deprecated
public interface PacketListener {
}
@@ -0,0 +1,65 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.event;
import io.github.retrooper.packetevents.event.impl.*;
public abstract class PacketListenerDynamic {
private final byte priority;
public PacketListenerDynamic(final byte priority) {
this.priority = priority;
}
public final byte getPriority() {
return priority;
}
public void onPacketStatus(PacketStatusEvent event) {
}
public void onPacketLogin(PacketLoginEvent event) {
}
public void onPacketReceive(PacketReceiveEvent event) {
}
public void onPacketSend(PacketSendEvent event) {
}
public void onPostPacketReceive(PostPacketReceiveEvent event) {
}
public void onPostPacketSend(PostPacketSendEvent event) {
}
public void onPlayerInject(PlayerInjectEvent event) {
}
public void onPlayerEject(PlayerEjectEvent event) {
}
public void onPacketEvent(PacketEvent event) {
}
}
@@ -26,14 +26,10 @@ package io.github.retrooper.packetevents.event.annotation;
import io.github.retrooper.packetevents.event.priority.PacketEventPriority;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface PacketHandler {
byte priority() default PacketEventPriority.NORMAL;
}
@@ -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";
@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());
}
}
@@ -24,99 +24,57 @@
package io.github.retrooper.packetevents.event.manager;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.event.PacketListener;
import io.github.retrooper.packetevents.event.annotation.PacketHandler;
import io.github.retrooper.packetevents.event.eventtypes.CancellableEvent;
import io.github.retrooper.packetevents.event.impl.*;
import io.github.retrooper.packetevents.event.priority.PacketEventPriority;
import io.github.retrooper.packetevents.utils.protocollib.ProtocolLibAPIListener;
import io.github.retrooper.packetevents.utils.protocollib.ProtocolLibUtils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
public final class EventManager {
private final Map<PacketListener, List<Method>> staticRegisteredMethods = new HashMap<>();
public void callEvent(final PacketEvent e) {
//STATIC LISTENERS
for (final PacketListener listener : staticRegisteredMethods.keySet()) {
List<Method> methods = staticRegisteredMethods.get(listener);
final boolean[] isCancelled = {false};
final byte[] eventPriority = {PacketEventPriority.LOWEST};
for (Method method : methods) {
Class<?> parameterType = method.getParameterTypes()[0];
if (parameterType.equals(PacketEvent.class)
|| parameterType.isInstance(e)) {
private final EventManagerLegacy legacyEventManager = new EventManagerLegacy();
private final EventManagerDynamic dynamicEventManager = new EventManagerDynamic();
PacketHandler annotation = method.getAnnotation(PacketHandler.class);
try {
method.invoke(listener, e);
} catch (IllegalAccessException | InvocationTargetException ex) {
ex.printStackTrace();
}
if (e instanceof CancellableEvent) {
CancellableEvent ce = (CancellableEvent) e;
if (annotation.priority() >= eventPriority[0]) {
eventPriority[0] = annotation.priority();
isCancelled[0] = ce.isCancelled();
}
}
}
}
}
public void callEvent(PacketEvent event) {
dynamicEventManager.callEvent(event);
legacyEventManager.callEvent(event);
}
public void registerListener(final PacketListener listener) {
final List<Method> methods = new ArrayList<>();
for (final Method m : listener.getClass().getDeclaredMethods()) {
if (!m.isAccessible()) {
m.setAccessible(true);
}
if (m.isAnnotationPresent(PacketHandler.class)
&& m.getParameterTypes().length == 1) {
methods.add(m);
}
}
if (!methods.isEmpty()) {
if (ProtocolLibUtils.isAvailable()
&& PacketEvents.getSettings().shouldUseProtocolLibIfAvailable()) {
ProtocolLibAPIListener.registerProtocolLibListener(listener, methods);
} else {
staticRegisteredMethods.put(listener, methods);
}
}
@Deprecated
public void registerListener(PacketListener listener) {
legacyEventManager.registerListener(listener);
}
public void registerListeners(final PacketListener... listeners) {
for (final PacketListener listener : listeners) {
registerListener(listener);
}
@Deprecated
public void registerListeners(PacketListener... listeners) {
legacyEventManager.registerListeners(listeners);
}
public void unregisterListener(final PacketListener e) {
staticRegisteredMethods.remove(e);
@Deprecated
public void unregisterListener(PacketListener listener) {
legacyEventManager.unregisterListener(listener);
}
public void unregisterListeners(final PacketListener... listeners) {
for (final PacketListener listener : listeners) {
unregisterListener(listener);
}
@Deprecated
public void unregisterListeners(PacketListener... listeners) {
legacyEventManager.unregisterListeners(listeners);
}
public void registerListener(PacketListenerDynamic listener) {
dynamicEventManager.registerListener(listener);
}
public void registerListeners(PacketListenerDynamic... listeners) {
dynamicEventManager.registerListeners(listeners);
}
public void unregisterListener(PacketListenerDynamic listener) {
dynamicEventManager.unregisterListener(listener);
}
public void unregisterListeners(PacketListenerDynamic... listeners) {
dynamicEventManager.unregisterListeners(listeners);
}
public void unregisterAllListeners() {
staticRegisteredMethods.clear();
}
public boolean isRegistered(final PacketListener listener) {
return staticRegisteredMethods.containsKey(listener);
dynamicEventManager.unregisterAllListeners();
legacyEventManager.unregisterAllListeners();
}
}
@@ -0,0 +1,117 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.event.manager;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
import io.github.retrooper.packetevents.event.eventtypes.CancellableEvent;
import io.github.retrooper.packetevents.event.impl.*;
import io.github.retrooper.packetevents.event.priority.PacketEventPriority;
import io.github.retrooper.packetevents.exceptions.PacketEventsMethodInvokeException;
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
class EventManagerDynamic {
private final Map<Byte, List<PacketListenerDynamic>> map = new HashMap<>();
public void callEvent(PacketEvent event) {
boolean isCancelled = false;
for (byte i = PacketEventPriority.LOWEST; i <= PacketEventPriority.MONITOR; i++) {
if (map.get(i) != null) {
for (PacketListenerDynamic listener : map.get(i)) {
try {
listener.onPacketEvent(event);
if (event instanceof PacketStatusEvent) {
listener.onPacketStatus((PacketStatusEvent) event);
} else if (event instanceof PacketLoginEvent) {
listener.onPacketLogin((PacketLoginEvent) event);
} else if (event instanceof PacketReceiveEvent) {
listener.onPacketReceive((PacketReceiveEvent) event);
} else if (event instanceof PacketSendEvent) {
listener.onPacketSend((PacketSendEvent) event);
} else if (event instanceof PostPacketReceiveEvent) {
listener.onPostPacketReceive((PostPacketReceiveEvent) event);
} else if (event instanceof PostPacketSendEvent) {
listener.onPostPacketSend((PostPacketSendEvent) event);
} else if (event instanceof PlayerInjectEvent) {
listener.onPlayerInject((PlayerInjectEvent) event);
} else if (event instanceof PlayerEjectEvent) {
listener.onPlayerEject((PlayerEjectEvent) event);
}
} catch (Exception ex) {
ex.printStackTrace();
}
if (event instanceof CancellableEvent) {
CancellableEvent ce = (CancellableEvent) event;
isCancelled = ce.isCancelled();
}
}
}
}
if (event instanceof CancellableEvent) {
CancellableEvent ce = (CancellableEvent) event;
ce.setCancelled(isCancelled);
}
}
public void registerListener(PacketListenerDynamic listener) {
List<PacketListenerDynamic> listeners = map.get(listener.getPriority());
if (listeners == null) {
map.put(listener.getPriority(), new ArrayList<>());
listeners = map.get(listener.getPriority());
}
listeners.add(listener);
}
public void registerListeners(PacketListenerDynamic... listeners) {
for (PacketListenerDynamic listener : listeners) {
registerListener(listener);
}
}
public void unregisterListener(PacketListenerDynamic listener) {
List<PacketListenerDynamic> listeners = map.get(listener.getPriority());
if (listeners == null) {
return;
}
listeners.remove(listener);
}
public void unregisterListeners(PacketListenerDynamic... listeners) {
for (PacketListenerDynamic listener : listeners) {
unregisterListener(listener);
}
}
public void unregisterAllListeners() {
map.clear();
}
}
@@ -0,0 +1,112 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.event.manager;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.event.PacketListener;
import io.github.retrooper.packetevents.event.annotation.PacketHandler;
import io.github.retrooper.packetevents.event.eventtypes.CancellableEvent;
import io.github.retrooper.packetevents.event.priority.PacketEventPriority;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
class EventManagerLegacy {
private final Map<PacketListener, List<Method>> staticRegisteredMethods = new HashMap<>();
public void callEvent(final PacketEvent e) {
boolean isCancelled = false;
byte eventPriority = PacketEventPriority.LOWEST;
//STATIC LISTENERS
for (final PacketListener listener : staticRegisteredMethods.keySet()) {
List<Method> methods = staticRegisteredMethods.get(listener);
for (Method method : methods) {
Class<?> parameterType = method.getParameterTypes()[0];
if (parameterType.equals(PacketEvent.class)
|| parameterType.isInstance(e)) {
PacketHandler annotation = method.getAnnotation(PacketHandler.class);
try {
method.invoke(listener, e);
} catch (IllegalAccessException | InvocationTargetException ex) {
ex.printStackTrace();
}
if (e instanceof CancellableEvent) {
CancellableEvent ce = (CancellableEvent) e;
if (annotation.priority() >= eventPriority) {
eventPriority = annotation.priority();
isCancelled = ce.isCancelled();
}
}
}
}
}
if(e instanceof CancellableEvent) {
CancellableEvent ce = (CancellableEvent)e;
ce.setCancelled(isCancelled);
}
}
public void registerListener(final PacketListener listener) {
final List<Method> methods = new ArrayList<>();
for (final Method m : listener.getClass().getDeclaredMethods()) {
if (!m.isAccessible()) {
m.setAccessible(true);
}
if (m.isAnnotationPresent(PacketHandler.class)
&& m.getParameterTypes().length == 1) {
methods.add(m);
}
}
if (!methods.isEmpty()) {
staticRegisteredMethods.put(listener, methods);
}
}
public void registerListeners(final PacketListener... listeners) {
for (final PacketListener listener : listeners) {
registerListener(listener);
}
}
public void unregisterListener(final PacketListener e) {
staticRegisteredMethods.remove(e);
}
public void unregisterListeners(final PacketListener... listeners) {
for (final PacketListener listener : listeners) {
unregisterListener(listener);
}
}
public void unregisterAllListeners() {
staticRegisteredMethods.clear();
}
}
@@ -25,20 +25,16 @@
package io.github.retrooper.packetevents.example;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.event.PacketListener;
import io.github.retrooper.packetevents.event.annotation.PacketHandler;
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
import io.github.retrooper.packetevents.event.impl.PacketReceiveEvent;
import io.github.retrooper.packetevents.event.impl.PlayerEjectEvent;
import io.github.retrooper.packetevents.event.impl.PlayerInjectEvent;
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.packetwrappers.out.helditemslot.WrappedPacketOutHeldItemSlot;
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.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
public class MainExample extends JavaPlugin implements PacketListener {
public class MainExample extends JavaPlugin {
@Override
public void onLoad() {
PacketEvents.load();
@@ -46,10 +42,10 @@ public class MainExample extends JavaPlugin implements PacketListener {
@Override
public void onEnable() {
PacketEvents.getSettings().injectAsync(true).ejectAsync(true).
backupServerVersion(ServerVersion.v_1_7_10).useProtocolLibIfAvailable(true).
checkForUpdates(true).injectEarly(true).packetHandlingThreadCount(1);
PacketEvents.getAPI().getEventManager().registerListener(this);
PacketEvents.getSettings().injectAsync(true)
.ejectAsync(true).backupServerVersion(ServerVersion.v_1_7_10)
.checkForUpdates(true).injectEarly(true)
.packetHandlingThreadCount(1);
PacketEvents.init(this);
}
@@ -0,0 +1,43 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.exceptions;
public class PacketEventsLoadFailureException extends RuntimeException {
public PacketEventsLoadFailureException(String message) {
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);
}
}
@@ -0,0 +1,41 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.exceptions;
import io.github.retrooper.packetevents.event.PacketListener;
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
import java.lang.reflect.Method;
public class PacketEventsMethodAccessException extends RuntimeException {
public PacketEventsMethodAccessException(String message) {
super(message);
}
public PacketEventsMethodAccessException(Method method, PacketListener listener) {
this("PacketEvents failed to access the "
+ method.getName() + " method in " + ClassUtil.getClassSimpleName(listener.getClass()));
}
}
@@ -0,0 +1,50 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.exceptions;
import io.github.retrooper.packetevents.event.PacketListener;
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
import java.lang.reflect.Method;
public class PacketEventsMethodInvokeException extends RuntimeException {
public PacketEventsMethodInvokeException(String message) {
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);
}
}
@@ -30,22 +30,17 @@ import io.github.retrooper.packetevents.packetmanager.netty.NettyPacketManager;
import io.github.retrooper.packetevents.packetmanager.tinyprotocol.TinyProtocol;
import io.github.retrooper.packetevents.packettype.PacketType;
import io.github.retrooper.packetevents.packetwrappers.login.in.WrappedPacketLoginHandshake;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.player.ClientVersion;
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
import io.github.retrooper.packetevents.utils.versionlookup.VersionLookupUtils;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import java.util.HashMap;
import java.util.UUID;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
public class PacketManager {
private static final AtomicInteger handlerID = new AtomicInteger();
private final int handlerNumber = handlerID.getAndIncrement();
private final Plugin plugin;
private final boolean tinyProtocolMode;
public final TinyProtocol tinyProtocol;
@@ -59,8 +54,8 @@ public class PacketManager {
tinyProtocol = new TinyProtocol(plugin);
nettyProtocol = null;
} else {
tinyProtocol = null;
nettyProtocol = new NettyPacketManager(plugin);
tinyProtocol = null;
}
}
@@ -97,8 +92,10 @@ public class PacketManager {
PacketEvents.getAPI().getEventManager().callEvent(injectEvent);
if (!injectEvent.isCancelled()) {
if (tinyProtocolMode) {
assert tinyProtocol != null;
tinyProtocol.injectPlayerAsync(player);
} else {
assert nettyProtocol != null;
nettyProtocol.injectPlayerAsync(player);
}
}
@@ -162,12 +159,8 @@ public class PacketManager {
}
}
public boolean canInject(Player player) {
return true;
}
public String getNettyHandlerName() {
return "pe-" + plugin.getName() + "-" + handlerNumber;
return "pe-" + plugin.getName();
}
public Object read(Player player, Object channel, Object packet) {
@@ -269,7 +262,7 @@ public class PacketManager {
long timestamp = keepAliveMap.getOrDefault(uuid, event.getTimestamp());
long currentTime = event.getTimestamp();
long ping = currentTime - timestamp;
long smoothedPing = ((PacketEvents.getAPI().getPlayerUtils().getSmoothedPing(event.getPlayer()) * 3) + ping) / 4;
long smoothedPing = (PacketEvents.getAPI().getPlayerUtils().getSmoothedPing(event.getPlayer()) * 3 + ping) / 4;
PacketEvents.getAPI().getPlayerUtils().playerPingMap.put(uuid, (short) ping);
PacketEvents.getAPI().getPlayerUtils().playerSmoothedPingMap.put(uuid, (short) smoothedPing);
}
@@ -282,13 +275,13 @@ public class PacketManager {
}
private void interceptLogin(PacketLoginEvent event) {
if (event.getPacketId() == PacketType.Login.HANDSHAKE) {
if (!VersionLookupUtils.isDependencyAvailable()) {
WrappedPacketLoginHandshake handshake = new WrappedPacketLoginHandshake(event.getNMSPacket());
int protocolVersion = handshake.getProtocolVersion();
ClientVersion version = ClientVersion.getClientVersion(protocolVersion);
PacketEvents.getAPI().getPlayerUtils().clientVersionsMap.put(event.getChannel(), version);
}
if (event.getPacketId() == PacketType.Login.HANDSHAKE
&& PacketEvents.getAPI().getServerUtils().getVersion() != ServerVersion.v_1_7_10
&& !PacketEvents.getAPI().getServerUtils().isBungeeCordEnabled()) {
WrappedPacketLoginHandshake handshake = new WrappedPacketLoginHandshake(event.getNMSPacket());
int protocolVersion = handshake.getProtocolVersion();
ClientVersion version = ClientVersion.getClientVersion(protocolVersion);
PacketEvents.getAPI().getPlayerUtils().clientVersionsMap.put(event.getChannel(), version);
}
}
@@ -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();
}
}
}
@@ -1,21 +1,22 @@
package io.github.retrooper.packetevents.packetmanager.tinyprotocol;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.packetmanager.netty.NettyPacketManager;
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;
import net.minecraft.util.io.netty.channel.*;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.*;
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;
@@ -62,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;
@@ -196,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);
@@ -356,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);
}
}
});
}
@@ -403,11 +419,11 @@ public class TinyProtocol7 {
}
public void ejectChannelSync(Object ch) {
uninjectChannel((Channel)ch);
uninjectChannel((Channel) ch);
}
public void ejectChannelAsync(Object ch) {
uninjectChannelAsync((Channel)ch);
uninjectChannelAsync((Channel) ch);
}
/**
@@ -471,11 +487,7 @@ public class TinyProtocol7 {
final Channel channel = ctx.channel();
handleLoginStart(channel, msg);
try {
msg = onPacketInAsync(player, channel, msg);
} catch (Exception e) {
plugin.getLogger().log(Level.SEVERE, "Error in onPacketInAsync().", e);
}
msg = onPacketInAsync(player, channel, msg);
if (msg != null) {
super.channelRead(ctx, msg);
@@ -485,12 +497,7 @@ public class TinyProtocol7 {
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
try {
msg = onPacketOutAsync(player, ctx.channel(), msg);
} catch (Exception e) {
plugin.getLogger().log(Level.SEVERE, "Error in onPacketOutAsync().", e);
}
msg = onPacketOutAsync(player, ctx.channel(), msg);
if (msg != null) {
super.write(ctx, msg, promise);
PacketEvents.getAPI().packetManager.postWrite(player, msg);
@@ -4,9 +4,9 @@ import com.google.common.collect.Lists;
import com.google.common.collect.MapMaker;
import com.mojang.authlib.GameProfile;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.packetmanager.netty.NettyPacketManager;
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;
@@ -17,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;
@@ -72,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;
@@ -165,9 +168,9 @@ public class TinyProtocol8 {
boolean looking = true;
// We need to synchronize against this list
if(getNetworkMarkers != null) {
networkManagers = (List<Object>) getNetworkMarkers.invoke(null, serverConnection);}
else {
if (getNetworkMarkers != null) {
networkManagers = (List<Object>) getNetworkMarkers.invoke(null, serverConnection);
} else {
networkManagers = new ArrayList<>();
}
createServerChannelHandler();
@@ -373,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);
}
}
});
}
@@ -487,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.
*
@@ -502,11 +519,7 @@ public class TinyProtocol8 {
final Channel channel = ctx.channel();
handleLoginStart(channel, msg);
try {
msg = onPacketInAsync(player, channel, msg);
} catch (Exception e) {
plugin.getLogger().log(Level.SEVERE, "Error in onPacketInAsync().", e);
}
msg = onPacketInAsync(player, channel, msg);
if (msg != null) {
super.channelRead(ctx, msg);
@@ -516,11 +529,7 @@ public class TinyProtocol8 {
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
try {
msg = onPacketOutAsync(player, ctx.channel(), msg);
} catch (Exception e) {
plugin.getLogger().log(Level.SEVERE, "Error in onPacketOutAsync().", e);
}
msg = onPacketOutAsync(player, ctx.channel(), msg);
if (msg != null) {
super.write(ctx, msg, promise);
@@ -39,11 +39,12 @@ public class PacketType {
packetIds.put(PacketTypeClasses.Status.SERVER_INFO, SERVER_INFO);
}
}
public static class Login {
public static final Map<Class<?>, Byte> packetIds = new HashMap<>();
public static final byte HANDSHAKE = 0,
IN_CUSTOM_PAYLOAD = 1, OUT_CUSTOM_PAYLOAD = 2,IN_START = 3, IN_ENCRYPTION_BEGIN = 4,
DISCONNECT = 5, OUT_ENCRYPTION_BEGIN = 6, OUT_SUCCESS = 7;
IN_CUSTOM_PAYLOAD = 1, OUT_CUSTOM_PAYLOAD = 2, IN_START = 3, IN_ENCRYPTION_BEGIN = 4,
DISCONNECT = 5, OUT_ENCRYPTION_BEGIN = 6, OUT_SUCCESS = 7;
public static void init() {
packetIds.put(PacketTypeClasses.Login.HANDSHAKE, HANDSHAKE);
@@ -39,9 +39,10 @@ public class PacketTypeClasses {
PacketType.Status.init();
}
}
public static class Login {
public static Class<?> HANDSHAKE,
IN_CUSTOM_PAYLOAD, OUT_CUSTOM_PAYLOAD,IN_START, IN_ENCRYPTION_BEGIN,
public static Class<?> HANDSHAKE,
IN_CUSTOM_PAYLOAD, OUT_CUSTOM_PAYLOAD, IN_START, IN_ENCRYPTION_BEGIN,
DISCONNECT, OUT_ENCRYPTION_BEGIN, OUT_SUCCESS;
public static void load() {
@@ -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);
@@ -47,7 +47,7 @@ final class WrappedPacketInBlockPlace_1_8 extends WrappedPacket {
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return -1;
return 0;
}
@@ -60,7 +60,7 @@ final class WrappedPacketInBlockPlace_1_8 extends WrappedPacket {
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return -1;
return 0;
}
public int getZ() {
@@ -72,7 +72,7 @@ final class WrappedPacketInBlockPlace_1_8 extends WrappedPacket {
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return -1;
return 0;
}
public ItemStack getItemStack() {
@@ -58,7 +58,7 @@ final class WrappedPacketInBlockPlace_1_9 extends WrappedPacket {
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return -1;
return 0;
}
public int getY() {
@@ -76,7 +76,7 @@ final class WrappedPacketInBlockPlace_1_9 extends WrappedPacket {
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return -1;
return 0;
}
public int getZ() {
@@ -94,7 +94,7 @@ final class WrappedPacketInBlockPlace_1_9 extends WrappedPacket {
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return -1;
return 0;
}
public Object getEnumDirectionObject() {
@@ -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) {
@@ -38,15 +39,13 @@ public final class WrappedPacketInUseEntity extends WrappedPacket {
}
public static void load() {
//System.out.println("USE ENTITY HAS BEEN LOADED BROOOIOII");
Class<?> useEntityClass = NMSUtils.getNMSClassWithoutException("PacketPlayInUseEntity");
/*if(useEntityClass == null) {
System.out.println("failed to init use entity wtfffff");
}*/
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 = 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);
}
}
@@ -25,13 +25,11 @@
package io.github.retrooper.packetevents.settings;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import net.minecraft.server.v1_8_R3.Packet;
public class PacketEventsSettings {
private ServerVersion backupServerVersion = ServerVersion.v_1_7_10;
private boolean injectAsync = true;
private boolean ejectAsync = true;
private boolean useProtocolLibIfAvailable;
private boolean checkForUpdates = true;
private boolean injectEarly = true;
private int packetHandlingThreadCount = 1;
@@ -52,11 +50,6 @@ public class PacketEventsSettings {
return this;
}
public PacketEventsSettings useProtocolLibIfAvailable(boolean useProtocolLibIfAvailable) {
this.useProtocolLibIfAvailable = useProtocolLibIfAvailable;
return this;
}
public PacketEventsSettings checkForUpdates(boolean checkForUpdates) {
this.checkForUpdates = checkForUpdates;
return this;
@@ -85,10 +78,6 @@ public class PacketEventsSettings {
return ejectAsync;
}
public boolean shouldUseProtocolLibIfAvailable() {
return useProtocolLibIfAvailable;
}
public boolean shouldCheckForUpdates() {
return checkForUpdates;
}
@@ -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;
}
}
@@ -1,42 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.utils;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.util.BlockIterator;
public class BlockIteratorUtils {
public static Block getBlockLookingAt(final Player player, final int distance) {
final Location location = player.getEyeLocation();
final BlockIterator blocksToAdd = new BlockIterator(location, 0.0D, distance);
Block block = null;
while (blocksToAdd.hasNext()) {
block = blocksToAdd.next();
}
return block;
}
}
@@ -35,7 +35,6 @@ 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;
@@ -47,7 +46,6 @@ public final class EntityFinderUtils {
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");
@@ -57,7 +55,8 @@ public final class EntityFinderUtils {
}
try {
getEntityByIdMethod = worldServerClass.getMethod(getEntityByIDMethodName(), int.class);
getEntityByIdMethod = worldServerClass.getMethod((version.getProtocolVersion() == (short) 47)
? "a" : "getEntity", int.class);
craftWorldGetHandle = craftWorldClass.getMethod("getHandle");
getBukkitEntity = entityClass.getMethod("getBukkitEntity");
} catch (NoSuchMethodException e) {
@@ -65,36 +64,33 @@ public final class EntityFinderUtils {
}
}
public static Object getNMSEntityById(final int id) {
for (final World world : Bukkit.getWorlds()) {
final Object entity = getNMSEntityByIdWithWorld(world, id);
if (entity != null) {
return entity;
}
}
return null;
}
/**
* Get an entity by their ID.
*
* @param id
* @return Entity
*/
public static Entity getEntityById(final int id) {
Object nmsEntity = getNMSEntityById(id);
try {
return (Entity) getBukkitEntity.invoke(nmsEntity);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
for (final World world : Bukkit.getWorlds()) {
final Entity entity = getEntityByIdWithWorld(world, id);
if (entity != null) {
return entity;
}
}
return null;
return null;
}
public static Object getNMSEntityByIdWithWorld(final World world, final int id) {
/**
* 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) {
if (world == null) {
return null;
} else if (craftWorldClass == null) {
}
else if(craftWorldClass == null) {
throw new IllegalStateException("PacketEvents failed to locate the CraftWorld class.");
}
Object craftWorld = craftWorldClass.cast(world);
@@ -112,19 +108,6 @@ public final class EntityFinderUtils {
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return nmsEntity;
}
/**
* 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);
if (nmsEntity == null) {
return null;
}
@@ -135,17 +118,4 @@ public final class EntityFinderUtils {
}
return null;
}
/**
* This is the name of the method that returns the NMS entity when you pass in its ID.
* On 1.8-1.8.8 the function name is called 'a', on 1.7.10 and 1.9 and above the name is called 'getEntity'.
*
* @return entity by ID method name
*/
public static String getEntityByIDMethodName() {
if (isServerVersion_v_1_8_x) {
return "a";
}
return "getEntity";
}
}
@@ -55,6 +55,7 @@ public final class NMSUtils {
private static Method getCraftPlayerHandle;
private static Method getCraftEntityHandle;
private static Method asBukkitCopy;
private static Method getBukkitEntity;
private static Field entityPlayerPingField, playerConnectionField;
public static final HashMap<UUID, Object> channelCache = new HashMap<>();
@@ -102,6 +103,7 @@ public final class NMSUtils {
getCraftEntityHandle = craftEntityClass.getMethod("getHandle");
asBukkitCopy = craftItemStack.getMethod("asBukkitCopy", nmsItemStackClass);
craftWorldGetHandle = craftWorldClass.getMethod("getHandle");
getBukkitEntity = nmsEntityClass.getMethod("getBukkitEntity");
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
@@ -168,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);
@@ -196,6 +190,15 @@ public final class NMSUtils {
return null;
}
public static Entity getBukkitEntity(final Object nmsEntity) {
try {
return (Entity) getBukkitEntity.invoke(nmsEntity);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
public static Object getCraftPlayer(final Player player) {
return craftPlayerClass.cast(player);
}
@@ -22,12 +22,9 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.utils.protocollib;
package io.github.retrooper.packetevents.utils.player;
import org.bukkit.Bukkit;
public class ProtocolLibUtils {
public static boolean isAvailable() {
return Bukkit.getPluginManager().isPluginEnabled("ProtocolLib");
}
public enum ClientHand {
MAIN_HAND,
OFF_HAND;
}
@@ -53,7 +53,8 @@ public enum ClientVersion {
v_1_16_1(736),
v_1_16_2(751),
v_1_16_3(753),
HIGHER_THAN_SUPPORTED_VERSIONS(754),
v_1_16_4(754),
HIGHER_THAN_SUPPORTED_VERSIONS(755),
/**
* Pre releases just aren't supported, we would end up with so many enum constants.
*/
@@ -63,8 +64,9 @@ 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;
}
@@ -94,27 +96,22 @@ public enum ClientVersion {
}
public static ClientVersion getClientVersion(int protocolVersion) {
if(protocolVersion == -1) {
return ClientVersion.UNRESOLVED;
if (protocolVersion == -1) {
return ClientVersion.UNRESOLVED;
}
for(ClientVersion version : ClientVersion.values()) {
if(version.protocolVersion > protocolVersion) {
for (ClientVersion version : ClientVersion.values()) {
if (version.protocolVersion > protocolVersion) {
break;
}
else if(version.protocolVersion == protocolVersion) {
} else if (version.protocolVersion == protocolVersion) {
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;
}
}
@@ -1,144 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.utils.protocollib;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketEvent;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.event.PacketListener;
import io.github.retrooper.packetevents.event.annotation.PacketHandler;
import io.github.retrooper.packetevents.event.impl.PacketReceiveEvent;
import io.github.retrooper.packetevents.event.impl.PacketSendEvent;
import io.github.retrooper.packetevents.event.priority.PacketEventPriority;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
public class ProtocolLibAPIListener {
public static void registerProtocolLibListener(PacketListener listener, List<Method> methods) {
if (ProtocolLibUtils.isAvailable()) {
for (Method m : methods) {
if (m.getParameterTypes()[0].equals(PacketReceiveEvent.class)) {
PacketHandler annotation = m.getAnnotation(PacketHandler.class);
ListenerPriority priority;
switch (annotation.priority()) {
case PacketEventPriority.LOWEST:
priority = ListenerPriority.LOWEST;
break;
case PacketEventPriority.LOW:
priority = ListenerPriority.LOW;
break;
case PacketEventPriority.HIGH:
priority = ListenerPriority.HIGH;
break;
case PacketEventPriority.HIGHEST:
priority = ListenerPriority.HIGHEST;
break;
case PacketEventPriority.MONITOR:
priority = ListenerPriority.MONITOR;
break;
default:
priority = ListenerPriority.NORMAL;
break;
}
Set<PacketType> clientValues = new HashSet<>();
for(PacketType type : PacketType.Play.Client.getInstance().values()) {
if(type.isSupported()) {
clientValues.add(type);
}
}
ProtocolLibrary.getProtocolManager().
addPacketListener(new PacketAdapter(PacketEvents.getPlugins().get(0),
priority, clientValues) {
@Override
public void onPacketReceiving(PacketEvent event) {
event.setReadOnly(false);
PacketReceiveEvent receiveEvent = new PacketReceiveEvent(event.getPlayer(), event.getPacket().getHandle());
try {
m.invoke(listener, receiveEvent);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
event.setCancelled(receiveEvent.isCancelled());
}
});
} else if (m.getParameterTypes()[0].equals(PacketSendEvent.class)) {
PacketHandler annotation = m.getAnnotation(PacketHandler.class);
ListenerPriority priority;
switch (annotation.priority()) {
case PacketEventPriority.LOWEST:
priority = ListenerPriority.LOWEST;
break;
case PacketEventPriority.LOW:
priority = ListenerPriority.LOW;
break;
case PacketEventPriority.HIGH:
priority = ListenerPriority.HIGH;
break;
case PacketEventPriority.HIGHEST:
priority = ListenerPriority.HIGHEST;
break;
case PacketEventPriority.MONITOR:
priority = ListenerPriority.MONITOR;
break;
default:
priority = ListenerPriority.NORMAL;
break;
}
Set<PacketType> serverValues = new HashSet<>();
for(PacketType serverType : PacketType.Play.Server.getInstance().values()) {
if(serverType.isSupported()) {
serverValues.add(serverType);
}
}
ProtocolLibrary.getProtocolManager().
addPacketListener(new PacketAdapter(PacketEvents.getPlugins().get(0),
priority, serverValues) {
@Override
public void onPacketSending(PacketEvent event) {
event.setReadOnly(false);
PacketSendEvent sendEvent = new PacketSendEvent(event.getPlayer(), event.getPacket().getHandle());
try {
m.invoke(listener, sendEvent);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
event.setCancelled(sendEvent.isCancelled());
}
});
}
}
}
}
}
@@ -1,34 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.utils.protocolsupport;
import org.bukkit.entity.Player;
import protocolsupport.api.ProtocolSupportAPI;
class ProtocolSupportAPIAccessor {
public static int getProtocolVersion(final Player player) {
return ProtocolSupportAPI.getProtocolVersion(player).getId();
}
}
@@ -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);
@@ -38,7 +38,7 @@ public enum ServerVersion {
v_1_11_2((short) 316), v_1_12((short) 335), v_1_12_1((short) 338), v_1_12_2((short) 340), v_1_13((short) 393),
v_1_13_1((short) 401), v_1_13_2((short) 404), v_1_14((short) 477), v_1_14_1((short) 480), v_1_14_2((short) 485),
v_1_14_3((short) 490), v_1_14_4((short) 498), v_1_15((short) 573), v_1_15_1((short) 575), v_1_15_2((short) 578),
v_1_16((short) 735), v_1_16_1((short) 736), v_1_16_2((short) 751), v_1_16_3((short) 753), ERROR((short) -1), EMPTY((short) -1);
v_1_16((short) 735), v_1_16_1((short) 736), v_1_16_2((short) 751), v_1_16_3((short) 753), v_1_16_4((short)754),ERROR((short) -1);
private static final String nmsVersionSuffix = Bukkit.getServer().getClass().getPackage().getName()
.replace(".", ",").split(",")[3];
@@ -58,6 +58,9 @@ public enum ServerVersion {
if (reversedValues[0] == null) {
reversedValues = ServerVersion.reverse(values());
}
if(reversedValues == null) {
throw new IllegalStateException("Failed to reverse the ServerVersion enum constant values.");
}
for (final ServerVersion val : reversedValues) {
String valName = val.name().substring(2).replace("_", ".");
if (Bukkit.getBukkitVersion().contains(valName)) {
@@ -125,7 +128,7 @@ public enum ServerVersion {
* @return True if the supplied version is lower or equal, false if it is higher
* than the server's version.
*/
public boolean isAtLeast(final ServerVersion version) {
public boolean isHigherThanOrEquals(final ServerVersion version) {
return protocolId >= version.protocolId;
}
@@ -149,7 +152,7 @@ public enum ServerVersion {
* @return True if the supplied version is higher or equal, false if it is lower
* than the server's version.
*/
public boolean isAtMost(final ServerVersion version) {
public boolean isLowerThanOrEquals(final ServerVersion version) {
return version.protocolId >= protocolId;
}
}
@@ -24,53 +24,26 @@
package io.github.retrooper.packetevents.utils.versionlookup;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.utils.protocolsupport.ProtocolSupportUtils;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import io.github.retrooper.packetevents.utils.v_1_7_10.ProtocolVersionAccessor_v_1_7;
import io.github.retrooper.packetevents.utils.viaversion.ViaUtils;
import io.github.retrooper.packetevents.utils.versionlookup.protocollib.ProtocolLibVersionLookupUtils;
import io.github.retrooper.packetevents.utils.versionlookup.protocolsupport.ProtocolSupportVersionLookupUtils;
import io.github.retrooper.packetevents.utils.versionlookup.viaversion.ViaVersionLookupUtils;
import org.bukkit.entity.Player;
public class VersionLookupUtils {
private static byte protocolAccessMode = -2;
public static void handleLoadedDependencies() {
protocolAccessMode = (byte) (ViaUtils.isAvailable() ?
0 : ProtocolSupportUtils.isAvailable() ?
1 : PacketEvents.getAPI().getServerUtils().getVersion() == ServerVersion.v_1_7_10 ?
2 : -1);
}
public static boolean hasHandledLoadedDependencies() {
return protocolAccessMode != -2;
}
public static boolean isDependencyAvailable() {
return ViaUtils.isAvailable()
|| ProtocolSupportUtils.isAvailable();
return ViaVersionLookupUtils.isAvailable()
|| ProtocolLibVersionLookupUtils.isAvailable()
|| ProtocolSupportVersionLookupUtils.isAvailable();
}
/**
* If ViaVersion is present, we get the protocol version with the ViaVersion API.
* If ProtocolSupport is present, we get the protocol version with the ProtocolSupport API.
* If ProtocolLib is present, we get the protocol version with the ProtocolLib API.
* Otherwise return -1
*
* @param player target player
* @return protocol version of the player if ViaVersion or ProtocolSupport or ProtocolLib is present. Otherwise -1
*/
public static int getProtocolVersion(final Player player) {
switch (protocolAccessMode) {
case 0:
return ViaUtils.getProtocolVersion(player);
case 1:
return ProtocolSupportUtils.getProtocolVersion(player);
case 2:
return ProtocolVersionAccessor_v_1_7.getProtocolVersion(player);
default:
return -1;
public static int getProtocolVersion(Player player) {
if (ViaVersionLookupUtils.isAvailable()) {
return ViaVersionLookupUtils.getProtocolVersion(player);
} else if (ProtocolLibVersionLookupUtils.isAvailable()) {
return ProtocolLibVersionLookupUtils.getProtocolVersion(player);
} else if (ProtocolSupportVersionLookupUtils.isAvailable()) {
return ProtocolSupportVersionLookupUtils.getProtocolVersion(player);
}
return -1;
}
}
@@ -22,19 +22,18 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.utils.viaversion;
package io.github.retrooper.packetevents.utils.versionlookup.protocollib;
import com.comphenix.protocol.ProtocolLibrary;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import us.myles.ViaVersion.api.Via;
import java.util.UUID;
class ViaAPIAccessor {
public static int getProtocolVersion(final Player player) {
return getProtocolVersion(player.getUniqueId());
public class ProtocolLibVersionLookupUtils {
public static boolean isAvailable() {
return Bukkit.getPluginManager().isPluginEnabled("ProtocolLib");
}
public static int getProtocolVersion(final UUID uuid) {
return Via.getAPI().getPlayerVersion(uuid);
public static int getProtocolVersion(Player player) {
return ProtocolLibrary.getProtocolManager().getProtocolVersion(player);
}
}
@@ -22,17 +22,18 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.utils.protocolsupport;
package io.github.retrooper.packetevents.utils.versionlookup.protocolsupport;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import protocolsupport.api.ProtocolSupportAPI;
public class ProtocolSupportUtils {
public class ProtocolSupportVersionLookupUtils {
public static boolean isAvailable() {
return Bukkit.getPluginManager().isPluginEnabled("ProtocolSupport");
}
public static int getProtocolVersion(final Player player) {
return ProtocolSupportAPIAccessor.getProtocolVersion(player);
public static int getProtocolVersion(Player player) {
return ProtocolSupportAPI.getProtocolVersion(player).getId();
}
}
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.utils.v_1_7_10;
package io.github.retrooper.packetevents.utils.versionlookup.v_1_7_10;
import org.bukkit.entity.Player;
@@ -22,18 +22,18 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.utils.viaversion;
package io.github.retrooper.packetevents.utils.versionlookup.viaversion;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import us.myles.ViaVersion.api.Via;
public class ViaUtils {
public static int getProtocolVersion(final Player player) {
return ViaAPIAccessor.getProtocolVersion(player);
}
public class ViaVersionLookupUtils {
public static boolean isAvailable() {
return Bukkit.getPluginManager().isPluginEnabled("ViaVersion");
}
public static int getProtocolVersion(Player player) {
return Via.getAPI().getPlayerVersion(player.getUniqueId());
}
}