Compare commits

..
24 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
36 changed files with 522 additions and 329 deletions

No files matched your search

+16 -1
View File
@@ -6,7 +6,7 @@
<groupId>io.github.retrooper</groupId>
<artifactId>packetevents</artifactId>
<version>1.7.6</version>
<version>1.7.9</version>
<!-- You can build the project with this: "mvn clean compile assembly:single" -->
<build>
@@ -122,6 +122,21 @@
<version>4.5.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>us.myles</groupId>
<artifactId>viaversion</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.ProtocolSupport</groupId>
<artifactId>ProtocolSupport</artifactId>
<version>3d24efeda6</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
@@ -24,8 +24,8 @@
package io.github.retrooper.packetevents;
import io.github.retrooper.packetevents.bungee.BungeePluginMessageListener;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.event.impl.PostPlayerInjectEvent;
import io.github.retrooper.packetevents.exceptions.PacketEventsLoadFailureException;
import io.github.retrooper.packetevents.packetmanager.PacketManager;
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
@@ -37,7 +37,8 @@ import io.github.retrooper.packetevents.utils.nms.NMSUtils;
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.v_1_7_10.ProtocolVersionAccessor_v_1_7;
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;
@@ -51,15 +52,13 @@ import org.bukkit.plugin.Plugin;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public final class PacketEvents implements Listener {
private static final PacketEventsAPI packetEventsAPI = new PacketEventsAPI();
private static final PacketEvents instance = new PacketEvents();
private static final ArrayList<Plugin> plugins = new ArrayList<>(1);
private static boolean loaded, initialized;
private static final PEVersion version = new PEVersion(1, 7, 6);
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.
@@ -88,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;
@@ -107,9 +107,11 @@ public final class PacketEvents implements Listener {
WrappedPacket.loadAllWrappers();
} catch (Exception ex) {
throw new PacketEventsLoadFailureException();
loading = false;
throw new PacketEventsLoadFailureException(ex);
}
loaded = true;
loading = false;
}
}
@@ -135,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);
@@ -152,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;
}
}
@@ -172,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);
}
@@ -180,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;
}
}
@@ -191,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;
}
@@ -221,33 +243,43 @@ public final class PacketEvents implements Listener {
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(priority = EventPriority.LOW)
@EventHandler(priority = EventPriority.HIGH)
public void onJoin(final PlayerJoinEvent e) {
if(PacketEvents.getAPI().getServerUtils().getVersion() == ServerVersion.v_1_7_10) {
Object channel = NMSUtils.getChannel(e.getPlayer());
Object channel = NMSUtils.getChannel(e.getPlayer());
if (PacketEvents.getAPI().getServerUtils().getVersion() == ServerVersion.v_1_7_10) {
ClientVersion version = ClientVersion.getClientVersion(ProtocolVersionAccessor_v_1_7.getProtocolVersion(e.getPlayer()));
PacketEvents.getAPI().getPlayerUtils().clientVersionsMap.put(channel, version);
}
//Waiting for the BungeeCord server to send their plugin message with your 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(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);
}
}
}
@@ -24,8 +24,8 @@
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.eventtypes.CancellableEvent;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.event.eventtypes.CancellableEvent;
import io.github.retrooper.packetevents.event.eventtypes.PlayerEvent;
import io.github.retrooper.packetevents.packettype.PacketType;
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
@@ -38,6 +38,7 @@ public final class PacketReceiveEvent extends PacketEvent implements Cancellable
private final Player player;
private final Object packet;
private boolean cancelled;
private byte packetID = -1;
public PacketReceiveEvent(final Player player, final Object packet) {
this.player = player;
@@ -46,6 +47,7 @@ public final class PacketReceiveEvent extends PacketEvent implements Cancellable
/**
* Get the packet sender
*
* @return player
*/
@Override
@@ -56,6 +58,7 @@ public final class PacketReceiveEvent extends PacketEvent implements Cancellable
/**
* Get the packet's name (NMS packet class simple name).
* The class simple name is cached.
*
* @return Name of the packet
*/
public String getPacketName() {
@@ -64,6 +67,7 @@ public final class PacketReceiveEvent extends PacketEvent implements Cancellable
/**
* Get the raw packet object
*
* @return packet object
*/
public Object getNMSPacket() {
@@ -72,10 +76,14 @@ public final class PacketReceiveEvent extends PacketEvent implements Cancellable
/**
* Get the ID of the packet
*
* @return packet id
*/
public byte getPacketId() {
return PacketType.Client.packetIds.getOrDefault(packet.getClass(), (byte) -1);
if (packetID == -1) {
packetID = PacketType.Client.packetIds.getOrDefault(packet.getClass(), (byte) -1);
}
return packetID;
}
@Override
@@ -38,6 +38,7 @@ public final class PacketSendEvent extends PacketEvent implements CancellableEve
private final Player player;
private final Object packet;
private boolean cancelled;
private byte packetID = -1;
public PacketSendEvent(final Player player, final Object packet) {
this.player = player;
@@ -65,7 +66,10 @@ public final class PacketSendEvent extends PacketEvent implements CancellableEve
* @return packet id
*/
public byte getPacketId() {
return PacketType.Server.packetIds.getOrDefault(packet.getClass(), (byte) -1);
if(packetID == -1) {
packetID = PacketType.Server.packetIds.getOrDefault(packet.getClass(), (byte) -1);
}
return packetID;
}
/**
@@ -33,6 +33,7 @@ public class PacketStatusEvent extends PacketEvent implements CancellableEvent {
private final Object channel;
private final Object packet;
private boolean cancelled;
private byte packetID = -1;
public PacketStatusEvent(final Object channel, final Object packet) {
this.channel = channel;
@@ -68,7 +69,10 @@ public class PacketStatusEvent extends PacketEvent implements CancellableEvent {
* @return packet id
*/
public byte getPacketId() {
return PacketType.Status.packetIds.getOrDefault(packet.getClass(), (byte) -1);
if (packetID == -1) {
packetID = PacketType.Status.packetIds.getOrDefault(packet.getClass(), (byte) -1);
}
return packetID;
}
@Override
@@ -33,7 +33,7 @@ import org.bukkit.entity.Player;
public class PostPacketReceiveEvent extends PacketEvent implements PlayerEvent {
private final Player player;
private final Object packet;
private byte packetID = -1;
public PostPacketReceiveEvent(final Player player, final Object packet) {
this.player = player;
this.packet = packet;
@@ -70,6 +70,9 @@ public class PostPacketReceiveEvent extends PacketEvent implements PlayerEvent {
* @return packet id
*/
public byte getPacketId() {
return PacketType.Client.packetIds.getOrDefault(packet.getClass(), (byte) -1);
if(packetID == -1) {
packetID = PacketType.Client.packetIds.getOrDefault(packet.getClass(), (byte) -1);
}
return packetID;
}
}
@@ -33,6 +33,7 @@ import org.bukkit.entity.Player;
public class PostPacketSendEvent extends PacketEvent implements PlayerEvent {
private final Player player;
private final Object packet;
private byte packetID = -1;
public PostPacketSendEvent(final Player player, final Object packet) {
this.player = player;
@@ -41,6 +42,7 @@ public class PostPacketSendEvent extends PacketEvent implements PlayerEvent {
/**
* Get the packet sender
*
* @return player
*/
@Override
@@ -51,6 +53,7 @@ public class PostPacketSendEvent extends PacketEvent implements PlayerEvent {
/**
* Get the packet's name (NMS packet class simple name).
* The class simple name is cached.
*
* @return Name of the packet
*/
public String getPacketName() {
@@ -59,6 +62,7 @@ public class PostPacketSendEvent extends PacketEvent implements PlayerEvent {
/**
* Get the raw packet object
*
* @return packet object
*/
public Object getNMSPacket() {
@@ -67,9 +71,13 @@ public class PostPacketSendEvent extends PacketEvent implements PlayerEvent {
/**
* Get the ID of the packet
*
* @return packet id
*/
public byte getPacketId() {
return PacketType.Server.packetIds.getOrDefault(packet.getClass(), (byte) -1);
if (packetID == -1) {
packetID = PacketType.Server.packetIds.getOrDefault(packet.getClass(), (byte) -1);
}
return packetID;
}
}
@@ -22,34 +22,31 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.bungee;
package io.github.retrooper.packetevents.event.impl;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteStreams;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.event.eventtypes.PlayerEvent;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.player.ClientVersion;
import org.bukkit.entity.Player;
import org.bukkit.plugin.messaging.PluginMessageListener;
import java.util.UUID;
public class BungeePluginMessageListener implements PluginMessageListener {
public static String tagName = "packetevents:channel";
@Override
public void onPluginMessageReceived(String tag, Player player, byte[] bytes) {
if (tag.equals(tagName)) {
ByteArrayDataInput in = ByteStreams.newDataInput(bytes);
if (in.readUTF().equals("version")) {
String uuidString = in.readUTF();
Object channel = NMSUtils.getChannel(player);
short protocolVersion = in.readShort();
ClientVersion version = ClientVersion.getClientVersion(protocolVersion);
PacketEvents.getAPI().getPlayerUtils().clientVersionsMap.put(channel, version);
}
}
public class PostPlayerInjectEvent extends PacketEvent implements PlayerEvent {
private final Player player;
public PostPlayerInjectEvent(Player player) {
this.player = player;
}
@Override
public Player getPlayer() {
return player;
}
public Object getChannel() {
return NMSUtils.getChannel(player);
}
public ClientVersion getClientVersion() {
return PacketEvents.getAPI().getPlayerUtils().clientVersionsMap.get(getChannel());
}
}
@@ -66,10 +66,7 @@ class EventManagerDynamic {
}
} catch (Exception ex) {
throw new PacketEventsMethodInvokeException("PacketEvents " +
"failed to call an event method in the " +
"dynamic packet listener. Event type: "
+ ClassUtil.getClassSimpleName(event.getClass()));
ex.printStackTrace();
}
if (event instanceof CancellableEvent) {
@@ -25,11 +25,16 @@
package io.github.retrooper.packetevents.example;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
import io.github.retrooper.packetevents.event.impl.PacketReceiveEvent;
import io.github.retrooper.packetevents.event.priority.PacketEventPriority;
import io.github.retrooper.packetevents.packettype.PacketType;
import io.github.retrooper.packetevents.packetwrappers.in.useentity.WrappedPacketInUseEntity;
import io.github.retrooper.packetevents.utils.player.ClientHand;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import org.bukkit.plugin.java.JavaPlugin;
public class MainExample extends JavaPlugin {
@Override
public void onLoad() {
PacketEvents.load();
@@ -37,9 +42,10 @@ public class MainExample extends JavaPlugin {
@Override
public void onEnable() {
PacketEvents.getSettings().injectAsync(true).ejectAsync(true)
.backupServerVersion(ServerVersion.v_1_7_10).checkForUpdates(true).injectEarly(true).
packetHandlingThreadCount(1);
PacketEvents.getSettings().injectAsync(true)
.ejectAsync(true).backupServerVersion(ServerVersion.v_1_7_10)
.checkForUpdates(true).injectEarly(true)
.packetHandlingThreadCount(1);
PacketEvents.init(this);
}
@@ -29,7 +29,15 @@ public class PacketEventsLoadFailureException extends RuntimeException {
super(message);
}
public PacketEventsLoadFailureException(String message, Throwable cause) {
super(message, cause);
}
public PacketEventsLoadFailureException() {
this("PacketEvents failed to successfully load...");
}
public PacketEventsLoadFailureException(Throwable cause) {
this("PacketEvents failed to successfully load...", cause);
}
}
@@ -34,8 +34,17 @@ public class PacketEventsMethodInvokeException extends RuntimeException {
super(message);
}
public PacketEventsMethodInvokeException(String message, Throwable cause) {
super(message, cause);
}
public PacketEventsMethodInvokeException(Method method, PacketListener listener) {
this("PacketEvents failed to call the " + method.getName() + " method in "
+ ClassUtil.getClassSimpleName(listener.getClass()));
}
public PacketEventsMethodInvokeException(Method method, PacketListener listener, Throwable cause) {
this("PacketEvents failed to call the " + method.getName() + " method in "
+ ClassUtil.getClassSimpleName(listener.getClass()), cause);
}
}
@@ -41,9 +41,6 @@ import java.util.UUID;
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;
@@ -57,8 +54,8 @@ public class PacketManager {
tinyProtocol = new TinyProtocol(plugin);
nettyProtocol = null;
} else {
tinyProtocol = null;
nettyProtocol = new NettyPacketManager(plugin);
tinyProtocol = null;
}
}
@@ -95,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);
}
}
@@ -160,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) {
@@ -280,12 +275,13 @@ public class PacketManager {
}
private void interceptLogin(PacketLoginEvent event) {
if (event.getPacketId() == PacketType.Login.HANDSHAKE &&
PacketEvents.getAPI().getServerUtils().getVersion() != ServerVersion.v_1_7_10) {
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();
}
}
}
@@ -3,6 +3,7 @@ package io.github.retrooper.packetevents.packetmanager.tinyprotocol;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.packetmanager.tinyprotocol.Reflection.FieldAccessor;
import io.github.retrooper.packetevents.packetmanager.tinyprotocol.Reflection.MethodInvoker;
import io.github.retrooper.packetevents.packetwrappers.out.kickdisconnect.WrappedPacketOutKickDisconnect;
import net.minecraft.util.com.google.common.collect.Lists;
import net.minecraft.util.com.google.common.collect.MapMaker;
import net.minecraft.util.com.mojang.authlib.GameProfile;
@@ -15,6 +16,7 @@ import org.bukkit.scheduler.BukkitRunnable;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
@@ -61,6 +63,8 @@ public class TinyProtocol7 {
private ChannelInitializer<Channel> beginInitProtocol;
private ChannelInitializer<Channel> endInitProtocol;
public final ConcurrentLinkedQueue<Channel> queueingChannelKicks = new ConcurrentLinkedQueue<>();
// Current handler name
private final String handlerName;
@@ -195,6 +199,13 @@ public class TinyProtocol7 {
}
}
public void handleQueuedKicks() {
for (Channel channel : queueingChannelKicks) {
Object packet = new WrappedPacketOutKickDisconnect("We failed to inject you. Please try rejoining!").asNMSPacket();
sendPacket(channel, packet);
}
}
private void registerPlayers(Plugin plugin) {
for (Player player : plugin.getServer().getOnlinePlayers()) {
injectPlayer(player);
@@ -355,7 +366,13 @@ public class TinyProtocol7 {
PacketEvents.packetHandlingExecutorService.execute(new Runnable() {
@Override
public void run() {
channel.pipeline().addBefore("packet_handler", handlerName, pi);
try {
channel.pipeline().addBefore("packet_handler", handlerName, pi);
} catch (Exception ex) {
//kick them
Object packet = new WrappedPacketOutKickDisconnect("We unfortunately failed to inject you. Please try rejoining!").asNMSPacket();
sendPacket(channel, packet);
}
}
});
}
@@ -6,6 +6,7 @@ import com.mojang.authlib.GameProfile;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.packetmanager.tinyprotocol.Reflection.FieldAccessor;
import io.github.retrooper.packetevents.packetmanager.tinyprotocol.Reflection.MethodInvoker;
import io.github.retrooper.packetevents.packetwrappers.out.kickdisconnect.WrappedPacketOutKickDisconnect;
import io.netty.channel.*;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@@ -16,6 +17,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
@@ -71,6 +73,8 @@ public class TinyProtocol8 {
private ChannelInitializer<Channel> beginInitProtocol;
private ChannelInitializer<Channel> endInitProtocol;
public final ConcurrentLinkedQueue<Channel> queueingChannelKicks = new ConcurrentLinkedQueue<>();
// Current handler name
private final String handlerName;
@@ -372,7 +376,14 @@ public class TinyProtocol8 {
PacketEvents.packetHandlingExecutorService.execute(new Runnable() {
@Override
public void run() {
channel.pipeline().addBefore("packet_handler", handlerName, pi);
try {
channel.pipeline().addBefore("packet_handler", handlerName, pi);
}
catch(Exception ex) {
//kick them
Object packet = new WrappedPacketOutKickDisconnect("We unfortunately failed to inject you. Please try rejoining!").asNMSPacket();
sendPacket(channel, packet);
}
}
});
}
@@ -486,6 +497,13 @@ public class TinyProtocol8 {
}
}
public void handleQueuedKicks() {
for(Channel channel : queueingChannelKicks) {
Object packet = new WrappedPacketOutKickDisconnect("We failed to inject you. Please try rejoining!").asNMSPacket();
sendPacket(channel, packet);
}
}
/**
* Channel handler that is inserted into the player's channel pipeline, allowing us to intercept sent and received packets.
*
@@ -94,99 +94,42 @@ public class WrappedPacket implements WrapperPacketReader, WrapperPacketWriter {
List<Field> byteFields = getFields(byte.class, declaredFields);
List<Field> shortFields = getFields(short.class, declaredFields);
List<Field> intFields = getFields(int.class, declaredFields);
;
List<Field> longFields = getFields(long.class, declaredFields);
;
List<Field> floatFields = getFields(float.class, declaredFields);
;
List<Field> doubleFields = getFields(double.class, declaredFields);
;
List<Field> stringFields = getFields(String.class, declaredFields);
;
List<Field> boolArrayFields = getFields(boolean[].class, declaredFields);
;
List<Field> byteArrayFields = getFields(byte[].class, declaredFields);
;
List<Field> shortArrayFields = getFields(short[].class, declaredFields);
;
List<Field> intArrayFields = getFields(int[].class, declaredFields);
;
List<Field> longArrayFields = getFields(long[].class, declaredFields);
;
List<Field> floatArrayFields = getFields(float[].class, declaredFields);
;
List<Field> doubleArrayFields = getFields(double[].class, declaredFields);
;
List<Field> stringArrayFields = getFields(String[].class, declaredFields);
;
Field[] tmp = new Field[0];
Map<Class<?>, Field[]> map = new HashMap<>();
if (boolFields != null) {
map.put(boolean.class, boolFields.toArray(tmp));
}
if (byteFields != null) {
map.put(byte.class, byteFields.toArray(tmp));
}
map.put(boolean.class, boolFields.toArray(tmp));
map.put(byte.class, byteFields.toArray(tmp));
map.put(short.class, shortFields.toArray(tmp));
map.put(int.class, intFields.toArray(tmp));
map.put(long.class, longFields.toArray(tmp));
map.put(float.class, floatFields.toArray(tmp));
map.put(double.class, doubleFields.toArray(tmp));
if (shortFields != null) {
map.put(short.class, shortFields.toArray(tmp));
}
if (intFields != null) {
map.put(int.class, intFields.toArray(tmp));
}
if (longFields != null) {
map.put(long.class, longFields.toArray(tmp));
}
if (floatFields != null) {
map.put(float.class, floatFields.toArray(tmp));
}
if (doubleFields != null) {
map.put(double.class, doubleFields.toArray(tmp));
}
if (stringFields != null) {
map.put(String.class, stringFields.toArray(tmp));
}
if (boolArrayFields != null) {
map.put(boolean[].class, boolArrayFields.toArray(tmp));
}
if (byteArrayFields != null) {
map.put(byte[].class, byteArrayFields.toArray(tmp));
}
if (shortArrayFields != null) {
map.put(short[].class, shortArrayFields.toArray(tmp));
}
if (intArrayFields != null) {
map.put(int[].class, intArrayFields.toArray(tmp));
}
if (longArrayFields != null) {
map.put(long[].class, longArrayFields.toArray(tmp));
}
if (floatArrayFields != null) {
map.put(float[].class, floatArrayFields.toArray(tmp));
}
if (doubleArrayFields != null) {
map.put(double[].class, doubleArrayFields.toArray(tmp));
}
if (stringArrayFields != null) {
map.put(String[].class, stringArrayFields.toArray(tmp));
}
map.put(String.class, stringFields.toArray(tmp));
map.put(boolean[].class, boolArrayFields.toArray(tmp));
map.put(byte[].class, byteArrayFields.toArray(tmp));
map.put(short[].class, shortArrayFields.toArray(tmp));
map.put(int[].class, intArrayFields.toArray(tmp));
map.put(long[].class, longArrayFields.toArray(tmp));
map.put(float[].class, floatArrayFields.toArray(tmp));
map.put(double[].class, doubleArrayFields.toArray(tmp));
map.put(String[].class, stringArrayFields.toArray(tmp));
fieldCache.put(packetClass, map);
}
this.packet = packet;
@@ -503,8 +446,7 @@ public class WrappedPacket implements WrapperPacketReader, WrapperPacketWriter {
if (!typeFields.isEmpty()) {
cached.put(type, typeFields.toArray(new Field[0]));
cachedFields = cached.get(type);
}
else {
} else {
throw new WrapperFieldNotFoundException("The class you are trying to read fields from does not contain any fields!");
}
}
@@ -517,6 +459,32 @@ public class WrappedPacket implements WrapperPacketReader, WrapperPacketWriter {
throw new WrapperFieldNotFoundException(packetClass, type, index);
}
public boolean doesObjectExist(int index, Class<?> type) {
Map<Class<?>, Field[]> cached = fieldCache.get(packetClass);
if (cached != null) {
Field[] cachedFields = cached.get(type);
if (cachedFields == null) {
List<Field> typeFields = new ArrayList<>();
for (Field f : packetClass.getDeclaredFields()) {
f.setAccessible(true);
if (f.getType().equals(type)) {
typeFields.add(f);
}
}
if (!typeFields.isEmpty()) {
cached.put(type, typeFields.toArray(new Field[0]));
cachedFields = cached.get(type);
} else {
return false;
}
}
if (cachedFields == null) {
return false;
} else return index <= cachedFields.length + 1;
}
return false;
}
public Object[] readObjectArray(int index, Class<?> type) {
if (type.equals(String.class)) {
return readStringArray(index);
@@ -26,11 +26,12 @@ package io.github.retrooper.packetevents.packetwrappers.in.useentity;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.player.ClientHand;
import io.github.retrooper.packetevents.utils.reflection.SubclassUtil;
import org.bukkit.entity.Entity;
public final class WrappedPacketInUseEntity extends WrappedPacket {
private static Class<?> enumEntityUseActionClass;
private static Class<?> enumEntityUseActionClass, enumHandClass;
private Entity entity;
private int entityID = -1;
public WrappedPacketInUseEntity(final Object packet) {
@@ -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,7 +25,6 @@
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;
@@ -37,38 +37,43 @@ import java.net.URLConnection;
public class UpdateChecker {
public void handleUpdate() {
inform("Checking for an update, please wait...");
PEVersion localVersion = PacketEvents.getVersion();
inform("[PacketEvents] Checking for an update, please wait...");
String line;
try {
String line = readLatestVersion();
PEVersion newVersion = new PEVersion(line);
if (localVersion.isOlder(newVersion)) {
inform("There is an update available for the PacketEvents API! Your build: (" + localVersion.toString() + ") | Update: (" + newVersion.toString() + ")");
}
else if(localVersion.equals(newVersion)) {
inform("You are on the latest released version of PacketEvents. Your build: (" + newVersion.toString() + ")");
}
else if(localVersion.isNewer(newVersion)) {
inform("You are on a dev or pre released build of PacketEvents. Your build: (" + localVersion.toString() + ") | Last released build: (" + newVersion.toString() + ")");
}
line = readLatestVersion();
} catch (IOException exception) {
report("We failed to find the latest released version of PacketEvents. Your build: (" + localVersion.toString() + ")");
report("[PacketEvents] We failed to find the latest released version of PacketEvents. Your build: (" + localVersion.toString() + ")");
return;
}
PEVersion newVersion = new PEVersion(line);
if (localVersion.isOlder(newVersion)) {
inform("[PacketEvents] There is an update available for the PacketEvents API! Your build: (" + localVersion.toString() + ") | Latest released build: (" + newVersion.toString() + ")");
} else if (localVersion.isNewer(newVersion)) {
inform("[PacketEvents] You are on a dev or pre released build of PacketEvents. Your build: (" + localVersion.toString() + ") | Latest released build: (" + newVersion.toString() + ")");
}
else if (localVersion.equals(newVersion)) {
inform("[PacketEvents] You are on the latest released version of PacketEvents. (" + newVersion.toString() + ")");
}
else {
report("[PacketEvents] Something went wrong while checking for an update. Your build: (" + localVersion.toString() + ") | Latest released build: (" + newVersion.toString() + ")");
}
}
private void inform(String message) {
Bukkit.getLogger().info("[PacketEvents] " + message);
Bukkit.getLogger().info(message);
}
private void report(String message) {
Bukkit.getLogger().info(ChatColor.DARK_RED + "[PacketEvents] " + message);
Bukkit.getLogger().info(ChatColor.DARK_RED + message);
}
private String readLatestVersion() throws IOException {
URLConnection connection = new URL("https://api.spigotmc.org/legacy/update.php?resource=80279").openConnection();
connection.addRequestProperty("User-Agent", "Mozilla/4.0");
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
return reader.readLine();
String line = reader.readLine();
reader.close();
return line;
}
}
@@ -25,7 +25,6 @@
package io.github.retrooper.packetevents.utils.entityfinder;
import io.github.retrooper.packetevents.annotations.Nullable;
import io.github.retrooper.packetevents.exceptions.PacketEventsNMSCachedEntityNotFoundException;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import org.bukkit.Bukkit;
@@ -36,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;
@@ -48,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");
@@ -58,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) {
@@ -66,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;
}
}
throw new PacketEventsNMSCachedEntityNotFoundException(id);
}
/**
* 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;
}
}
throw new PacketEventsNMSCachedEntityNotFoundException(id);
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);
@@ -113,22 +108,6 @@ public final class EntityFinderUtils {
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
if(nmsEntity == null) {
throw new PacketEventsNMSCachedEntityNotFoundException(id);
}
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;
}
@@ -137,19 +116,6 @@ public final class EntityFinderUtils {
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
throw new PacketEventsNMSCachedEntityNotFoundException(id);
}
/**
* 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";
return null;
}
}
@@ -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,14 +22,9 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.exceptions;
package io.github.retrooper.packetevents.utils.player;
public class PacketEventsNMSCachedEntityNotFoundException extends RuntimeException {
public PacketEventsNMSCachedEntityNotFoundException(String message) {
super(message);
}
public PacketEventsNMSCachedEntityNotFoundException(int entityID) {
this("PacketEvents failed to find an entity with ID " + entityID + " in NMS' entity cache map!");
}
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;
}
}
@@ -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;
}
}
@@ -0,0 +1,49 @@
/*
* 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.versionlookup;
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 {
public static boolean isDependencyAvailable() {
return ViaVersionLookupUtils.isAvailable()
|| ProtocolLibVersionLookupUtils.isAvailable()
|| ProtocolSupportVersionLookupUtils.isAvailable();
}
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,32 +22,18 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.out.blockchange;
package io.github.retrooper.packetevents.utils.versionlookup.protocollib;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import com.comphenix.protocol.ProtocolLibrary;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
class WrappedPacketOutBlockChange extends WrappedPacket {
public WrappedPacketOutBlockChange(Object packet) {
super(packet);
public class ProtocolLibVersionLookupUtils {
public static boolean isAvailable() {
return Bukkit.getPluginManager().isPluginEnabled("ProtocolLib");
}
//to-do load
@Override
protected void setup() {
//1.7 - int, int, int, Block, int data
//1.8+ - BlockPosition, IBlockData
//Constructors
//1.7 - int, int, int, World
//1.8->~1.12.2(World, BlockPosition)
//~1.13->~1.14(IBlockAccess, BlockPosition)
//1.16+(BlockPosition, IBlockData)
net.minecraft.server.v1_7_R4.PacketPlayOutBlockChange bc;
net.minecraft.server.v1_8_R3.PacketPlayOutBlockChange bc1;
net.minecraft.server.v1_9_R1.PacketPlayOutBlockChange bc2;
net.minecraft.server.v1_12_R1.PacketPlayOutBlockChange bc3;
net.minecraft.server.v1_13_R2.PacketPlayOutBlockChange bc4;
net.minecraft.server.v1_16_R2.PacketPlayOutBlockChange bc5;
public static int getProtocolVersion(Player player) {
return ProtocolLibrary.getProtocolManager().getProtocolVersion(player);
}
}
@@ -0,0 +1,39 @@
/*
* 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.versionlookup.protocolsupport;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import protocolsupport.api.ProtocolSupportAPI;
public class ProtocolSupportVersionLookupUtils {
public static boolean isAvailable() {
return Bukkit.getPluginManager().isPluginEnabled("ProtocolSupport");
}
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;
@@ -0,0 +1,39 @@
/*
* 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.versionlookup.viaversion;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import us.myles.ViaVersion.api.Via;
public class ViaVersionLookupUtils {
public static boolean isAvailable() {
return Bukkit.getPluginManager().isPluginEnabled("ViaVersion");
}
public static int getProtocolVersion(Player player) {
return Via.getAPI().getPlayerVersion(player.getUniqueId());
}
}