Compare commits
169
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f44a5b3599 | ||
|
|
8ae21853c9 | ||
|
|
bd5e8b8ed5 | ||
|
|
a0dc82aba4 | ||
|
|
bb0f70cb44 | ||
|
|
e680d2b8f7 | ||
|
|
9dacbe2f36 | ||
|
|
74dde71db1 | ||
|
|
f1bc3d6f4a | ||
|
|
0fa893f949 | ||
|
|
2699a1e8f9 | ||
|
|
78b2eb07f5 | ||
|
|
49c1287664 | ||
|
|
83b3a10069 | ||
|
|
8aed1fda53 | ||
|
|
5f40eec0d3 | ||
|
|
104b894f50 | ||
|
|
bcba33a7cb | ||
|
|
4275c39d8a | ||
|
|
ae3adefd82 | ||
|
|
6e28602b73 | ||
|
|
584d3edb13 | ||
|
|
978ce4629a | ||
|
|
33cfa93f84 | ||
|
|
d5a29365b4 | ||
|
|
e12870b542 | ||
|
|
75301b188a | ||
|
|
be91a955dc | ||
|
|
8eb6ae03eb | ||
|
|
7bf4c081b3 | ||
|
|
55b6f2cbce | ||
|
|
e97dcf2ae3 | ||
|
|
ddcb92d04c | ||
|
|
4413aca711 | ||
|
|
c4307fa777 | ||
|
|
f4ada314ba | ||
|
|
dbbc40879a | ||
|
|
8d3f86722c | ||
|
|
09466af902 | ||
|
|
851d19f57d | ||
|
|
a4ede8dfcf | ||
|
|
1c48790a03 | ||
|
|
26bc3274fe | ||
|
|
805e2ad335 | ||
|
|
8b6c6d7b35 | ||
|
|
7bec3ae062 | ||
|
|
defddefb48 | ||
|
|
5201b18fe7 | ||
|
|
c449e8ced1 | ||
|
|
f22d593173 | ||
|
|
5a3ce13d93 | ||
|
|
ecd0d63dc2 | ||
|
|
066791b283 | ||
|
|
f05bf26293 | ||
|
|
75391bebde | ||
|
|
d413f9e41b | ||
|
|
efdc66739f | ||
|
|
adf652978f | ||
|
|
29e8e9020d | ||
|
|
64da1a54fa | ||
|
|
37740d072f | ||
|
|
6496f1402a | ||
|
|
e661ee75d7 | ||
|
|
dbd9df8c71 | ||
|
|
bb8027bcaf | ||
|
|
c7096d8b35 | ||
|
|
36b80763e3 | ||
|
|
bc861089b0 | ||
|
|
e5a43a8826 | ||
|
|
1e1b609eb7 | ||
|
|
957c8876cc | ||
|
|
2902ef8ba4 | ||
|
|
de07adb46a | ||
|
|
f3dbb6dd4c | ||
|
|
b954e68f29 | ||
|
|
8e09c54143 | ||
|
|
5e88678c52 | ||
|
|
60ad9f476d | ||
|
|
5b4579c67c | ||
|
|
d502de76dd | ||
|
|
eb5e21eb1b | ||
|
|
d747974950 | ||
|
|
ef8fe9161f | ||
|
|
50ede8bf24 | ||
|
|
81f90a955c | ||
|
|
0252dbf1b8 | ||
|
|
cd230ca35d | ||
|
|
4852e4bfca | ||
|
|
0ed112b6fc | ||
|
|
3db6390efb | ||
|
|
57aa65cb76 | ||
|
|
746be8a0cf | ||
|
|
0ea484bdb1 | ||
|
|
072dbfbbb4 | ||
|
|
58faab9f54 | ||
|
|
16d9a0c6a6 | ||
|
|
c2f55aa048 | ||
|
|
bcb8d0e785 | ||
|
|
a881496e2b | ||
|
|
e4913cb841 | ||
|
|
781278a2c5 | ||
|
|
f1bbcd61ed | ||
|
|
42bdc1f1ca | ||
|
|
f826363d01 | ||
|
|
0710f214c5 | ||
|
|
3c4298dcea | ||
|
|
0aeff7cab8 | ||
|
|
be340a9812 | ||
|
|
7122f1194c | ||
|
|
e8df865b3c | ||
|
|
9e38883dcd | ||
|
|
1d955cac6e | ||
|
|
106b7c6d75 | ||
|
|
e70609bbc2 | ||
|
|
e1e0735688 | ||
|
|
51a417cebd | ||
|
|
c98c4e7d38 | ||
|
|
042b55af62 | ||
|
|
ab8885eb6e | ||
|
|
069980d567 | ||
|
|
e6e3835846 | ||
|
|
bdb83dfd86 | ||
|
|
628730d484 | ||
|
|
7aefa35623 | ||
|
|
8964a0ac5d | ||
|
|
128ff6c60b | ||
|
|
1bc2bbc905 | ||
|
|
3f9977fd1c | ||
|
|
6f5bc43179 | ||
|
|
89cba54262 | ||
|
|
081c2fece1 | ||
|
|
0b9f646650 | ||
|
|
07ca8ac282 | ||
|
|
cb798d6fd0 | ||
|
|
5b06f2005c | ||
|
|
c07960814c | ||
|
|
a1b75243f3 | ||
|
|
9f9ca79f90 | ||
|
|
241f5ed707 | ||
|
|
276653975d | ||
|
|
ff985e4eee | ||
|
|
65c28b4c90 | ||
|
|
e994c34689 | ||
|
|
0eed580e72 | ||
|
|
88ccbdbbe7 | ||
|
|
4604981e7d | ||
|
|
bf990c0a20 | ||
|
|
cfebc47853 | ||
|
|
4a72e70506 | ||
|
|
edc07a38ae | ||
|
|
a4daa60a7f | ||
|
|
e3f7b6888c | ||
|
|
62bb1a501b | ||
|
|
92fab840c5 | ||
|
|
515a4a4f8c | ||
|
|
7518b9335e | ||
|
|
6221ff0b8b | ||
|
|
bacc1cd878 | ||
|
|
5144bd6199 | ||
|
|
a80770b8f7 | ||
|
|
1caca9fd96 | ||
|
|
59aa347e4e | ||
|
|
a22ce57287 | ||
|
|
bac63c57e7 | ||
|
|
78171c583d | ||
|
|
3821c6e98a | ||
|
|
e0c71e7c86 | ||
|
|
d9d054c0cd | ||
|
|
82304e4f45 |
No files matched your search
@@ -1,82 +1,23 @@
|
||||
# packetevents
|
||||
|
||||
Some tasks require you to work at the packet level.
|
||||
It is very common for people to write their own packet system and event manager.
|
||||
PacketEvents is here to save you a ton of work.
|
||||
We provide high level packet-wrappers.
|
||||
The PacketEvents API focuses on providing you easy to use packet-wrappers supporting 1.7.10 spigots up to the current latest version!
|
||||
This API even comes with two event systems.
|
||||
The first one (currently deprecated) is extremely similar to Bukkit's event system making it really easy to use for
|
||||
experienced Bukkit plugin developers.
|
||||
The second one (recommended) prioritizes performance.
|
||||
PacketEvents listens to its community.
|
||||
Many users love shading the API into their plugin, so that their customers won't need to
|
||||
download the API as an external dependency.
|
||||
We have gone out of our way to support multiple plugins shading the API (resulting in duplicate PacketEvents APIs)
|
||||
and they all work together.
|
||||
[](https://github.com/retrooper/packetevents/blob/dev/LICENSE)
|
||||
[](https://jitpack.io/#retrooper/packetevents)
|
||||
|
||||
PacketEvents is an open-source Packet API. It has many cross-version packet-wrappers. You can process incoming and outgoing packets on the server. You can even send packets with our packet-wrappers. We are here to save you a ton of time.
|
||||
|
||||
### Resources
|
||||
* [Website](https://packetevents.github.io)
|
||||
* [SpigotMC](https://www.spigotmc.org/resources/packetevents-api.80279/)
|
||||
* [JavaDoc](https://retrooper.github.io/packetevents)
|
||||
|
||||
### Licensing
|
||||
[](https://opensource.org/licenses/MIT)\
|
||||
PacketEvents is licensed under the MIT License.
|
||||
We intentionally selected this license compared to stricter options.\
|
||||
[Summary of the license](https://tldrlegal.com/license/mit-license)
|
||||
|
||||
### Contributing
|
||||
[](CONTRIBUTOR_CODE_OF_CONDUCT.md)\
|
||||
PacketEvents is an open source project.
|
||||
We appreciate contributions.
|
||||
It is amazing that you want to take an extra step to contribute a change to the API that will
|
||||
hopefully benefit the majority of users.
|
||||
Before taking this step, please read the Contributor Code Of Conduct. (click on the badge above)
|
||||
Please also read [this](CONTRIBUTING.md) if you consider contributing.
|
||||
Our discord server has a role for contributors.\
|
||||
[Learn more about it in our discord server](https://discord.me/packetevents)
|
||||
|
||||
### Forking
|
||||
We also appreciate forks.
|
||||
It is always great news to us knowing someone is building their own API off of the PacketEvents API.
|
||||
If you are developing a feature that is only going to benefit you and not the majority of the community,
|
||||
please do not contribute!
|
||||
Make a fork instead!
|
||||
Our discord server has a discord role for forkers.\
|
||||
[Learn more about it in our discord server](https://discord.me/packetevents)
|
||||
|
||||
### Compilation
|
||||
PacketEvents is built with Maven and all past releases have always used maven.
|
||||
The majority of users (currently) in the Bukkit community use Maven.
|
||||
It should be easier for most people to contribute if we use Maven too.
|
||||
Just because PacketEvents is built with Maven doesn't mean you can't use other dependency managers to use the API.
|
||||
|
||||
### Setup
|
||||
You can either use the API with a dependency manager(like Maven or Gradle), depend on a pre-built build or compile it yourself with the source code.
|
||||
We recommend using a dependency manager.
|
||||
#### 1. Using a dependency manager
|
||||
[](https://jitpack.io/#retrooper/packetevents)
|
||||
[Learn more](https://github.com/retrooper/packetevents/wiki/1.-Setup)
|
||||
|
||||
#### 2. Using as an external pre-built dependency.
|
||||
* Download the [latest build from SpigotMC](https://www.spigotmc.org/resources/packetevents-api.80279/)
|
||||
* Add PacketEvents as a depend or soft-depend to your plugin.yml like this:
|
||||
```yml
|
||||
depend: [packetevents]
|
||||
```
|
||||
Your customers are now required to download this external pre-built dependency on their minecraft server.\
|
||||
It is an API and a Bukkit plugin at the same time.
|
||||
The version of the pre-built dependency is recommended to be the same as the version
|
||||
of the API you used in your plugin incase there have been API changes.
|
||||
### Discord
|
||||
[Learn more](https://discord.me/packetevents)
|
||||
|
||||
#### 3. Compiling source code.
|
||||
When compiling the source code yourself, you are required to use Maven. (unless you switch yourself)\
|
||||
We currently do not have a guide showing you how to do this, but it should be self explanatory if you know what you are doing.
|
||||
### Contributing/Forking
|
||||
[Learn more](https://github.com/retrooper/packetevents/wiki/2.-Contributing-and-Forking)\
|
||||
Our discord server has a role for contributors and forkers.
|
||||
|
||||
### Author
|
||||
PacketEvents was started by retrooper.
|
||||
This API was initially for his private anti-cheat he was developing just to test around with.
|
||||
He has quit anti-cheat development and is now prioritizing this API and a few other private projects.
|
||||
PacketEvents now has a handfull of contributors improving the API.
|
||||
Share the API, donate, contribute, fork.
|
||||
Thanks.
|
||||
### Sponsorships
|
||||
[](https://www.ej-technologies.com/products/jprofiler/overview.html)
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>io.github.retrooper</groupId>
|
||||
<artifactId>packetevents</artifactId>
|
||||
<version>1.8-PRE-2</version>
|
||||
<version>1.8-pre-13</version>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
@@ -36,20 +36,20 @@
|
||||
<target>8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!--
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
-->
|
||||
<!--
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
-->
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
@@ -83,10 +83,6 @@
|
||||
<id>viaversion-repo</id>
|
||||
<url>https://repo.viaversion.com</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>dmulloy2-repo</id>
|
||||
<url>https://repo.dmulloy2.net/nexus/repository/public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>sonotype</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/releases/</url>
|
||||
@@ -101,6 +97,7 @@
|
||||
<version>20.1.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.github.spigot</groupId>
|
||||
<artifactId>1.16.2</artifactId>
|
||||
@@ -115,6 +112,13 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.github.spigot</groupId>
|
||||
<artifactId>1.13</artifactId>
|
||||
<version>1.13</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.github.spigot</groupId>
|
||||
<artifactId>1.12.2</artifactId>
|
||||
@@ -122,6 +126,13 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.github.spigot</groupId>
|
||||
<artifactId>1.9.4</artifactId>
|
||||
<version>1.9.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.github.spigot</groupId>
|
||||
<artifactId>1.9</artifactId>
|
||||
@@ -143,13 +154,6 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.comphenix.protocol</groupId>
|
||||
<artifactId>ProtocolLib</artifactId>
|
||||
<version>4.5.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>us.myles</groupId>
|
||||
<artifactId>viaversion</artifactId>
|
||||
|
||||
@@ -28,9 +28,12 @@ import io.github.retrooper.packetevents.event.impl.PostPlayerInjectEvent;
|
||||
import io.github.retrooper.packetevents.event.manager.EventManager;
|
||||
import io.github.retrooper.packetevents.event.manager.PEEventManager;
|
||||
import io.github.retrooper.packetevents.exceptions.PacketEventsLoadFailureException;
|
||||
import io.github.retrooper.packetevents.handler.PacketHandlerInternal;
|
||||
import io.github.retrooper.packetevents.injector.GlobalChannelInjector;
|
||||
import io.github.retrooper.packetevents.packettype.PacketType;
|
||||
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.processor.BukkitEventProcessorInternal;
|
||||
import io.github.retrooper.packetevents.processor.PacketProcessorInternal;
|
||||
import io.github.retrooper.packetevents.settings.PacketEventsSettings;
|
||||
import io.github.retrooper.packetevents.updatechecker.UpdateChecker;
|
||||
import io.github.retrooper.packetevents.utils.entityfinder.EntityFinderUtils;
|
||||
@@ -38,61 +41,60 @@ import io.github.retrooper.packetevents.utils.netty.bytebuf.ByteBufUtil;
|
||||
import io.github.retrooper.packetevents.utils.netty.bytebuf.ByteBufUtil_7;
|
||||
import io.github.retrooper.packetevents.utils.netty.bytebuf.ByteBufUtil_8;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
import io.github.retrooper.packetevents.utils.player.ClientVersion;
|
||||
import io.github.retrooper.packetevents.utils.player.PlayerUtils;
|
||||
import io.github.retrooper.packetevents.utils.server.ServerUtils;
|
||||
import io.github.retrooper.packetevents.utils.server.ServerVersion;
|
||||
import io.github.retrooper.packetevents.utils.version.PEVersion;
|
||||
import io.github.retrooper.packetevents.utils.versionlookup.VersionLookupUtils;
|
||||
import io.github.retrooper.packetevents.utils.versionlookup.protocollib.ProtocolLibVersionLookupUtils;
|
||||
import io.github.retrooper.packetevents.utils.versionlookup.v_1_7_10.ProtocolVersionAccessor_v_1_7;
|
||||
import io.github.retrooper.packetevents.utils.versionlookup.viaversion.ViaVersionLookupUtils;
|
||||
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;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.ServicePriority;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public final class PacketEvents implements Listener, EventManager {
|
||||
public static String handlerName;
|
||||
//TODO finish unfinished wrappers
|
||||
private static PacketEvents instance;
|
||||
private final PEVersion version = new PEVersion(1, 7, 9, 1);
|
||||
private static Plugin plugin;
|
||||
private final PEVersion version = new PEVersion(1, 7, 9, 13);
|
||||
private final EventManager eventManager = new PEEventManager();
|
||||
private final PlayerUtils playerUtils = new PlayerUtils();
|
||||
private final ServerUtils serverUtils = new ServerUtils();
|
||||
private final UpdateChecker updateChecker = new UpdateChecker();
|
||||
private static Plugin plugin;
|
||||
public static String handlerName;
|
||||
|
||||
//Executor used for player injecting/ejecting.
|
||||
public ExecutorService injectAndEjectExecutorService;//Initiated in init method
|
||||
|
||||
public PacketHandlerInternal packetHandlerInternal;
|
||||
private boolean loading, loaded, initialized, initializing, terminating;
|
||||
public final PacketProcessorInternal packetProcessorInternal = new PacketProcessorInternal();
|
||||
public final BukkitEventProcessorInternal bukkitEventProcessorInternal = new BukkitEventProcessorInternal();
|
||||
public final GlobalChannelInjector injector = new GlobalChannelInjector();
|
||||
private volatile boolean loading, loaded;
|
||||
private final AtomicBoolean injectorReady = new AtomicBoolean(false);
|
||||
private boolean initialized, initializing, terminating;
|
||||
private PacketEventsSettings settings = new PacketEventsSettings();
|
||||
private final ByteBufUtil byteBufUtil = NMSUtils.legacyNettyImportMode ? new ByteBufUtil_7() : new ByteBufUtil_8();
|
||||
private ByteBufUtil byteBufUtil;
|
||||
|
||||
public static PacketEvents create(final Plugin plugin) {
|
||||
if (!Bukkit.getServicesManager().isProvidedFor(PacketEvents.class)) {
|
||||
instance = new PacketEvents();
|
||||
Bukkit.getServicesManager().register(PacketEvents.class, instance,
|
||||
plugin, ServicePriority.Normal);
|
||||
if (Bukkit.isPrimaryThread()) {
|
||||
//We are on the main thread
|
||||
if (!Bukkit.getServicesManager().isProvidedFor(PacketEvents.class)) {
|
||||
//We can register in the service manager.
|
||||
instance = new PacketEvents();
|
||||
Bukkit.getServicesManager().register(PacketEvents.class, instance,
|
||||
plugin, ServicePriority.Normal);
|
||||
PacketEvents.plugin = plugin;
|
||||
return instance;
|
||||
} else {
|
||||
//We have already registered. Let us load what was registered.
|
||||
return instance = Bukkit.getServicesManager().load(PacketEvents.class);
|
||||
}
|
||||
} else {
|
||||
//We are off thread, we cannot use the service manager.
|
||||
if (instance == null) {
|
||||
PacketEvents.plugin = plugin;
|
||||
instance = new PacketEvents();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
return instance = Bukkit.getServicesManager().load(PacketEvents.class);
|
||||
}
|
||||
|
||||
public static PacketEvents get() {
|
||||
@@ -101,7 +103,7 @@ public final class PacketEvents implements Listener, EventManager {
|
||||
|
||||
@Deprecated
|
||||
public static PacketEvents getAPI() {
|
||||
return get();
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
@@ -112,88 +114,103 @@ public final class PacketEvents implements Listener, EventManager {
|
||||
WrappedPacket.version = version;
|
||||
NMSUtils.version = version;
|
||||
EntityFinderUtils.version = version;
|
||||
|
||||
handlerName = "pe-" + plugin.getName();
|
||||
try {
|
||||
NMSUtils.load();
|
||||
|
||||
//Load all classes
|
||||
PacketTypeClasses.load();
|
||||
|
||||
PacketType.load();
|
||||
|
||||
EntityFinderUtils.load();
|
||||
} catch (Exception ex) {
|
||||
loading = false;
|
||||
throw new PacketEventsLoadFailureException(ex);
|
||||
}
|
||||
|
||||
byteBufUtil = NMSUtils.legacyNettyImportMode ? new ByteBufUtil_7() : new ByteBufUtil_8();
|
||||
|
||||
if (!injectorReady.get()) {
|
||||
injector.load();
|
||||
try {
|
||||
injector.inject();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
injectorReady.set(true);
|
||||
}
|
||||
|
||||
loaded = true;
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void loadAsyncNewThread() {
|
||||
new Thread(this::load).start();
|
||||
}
|
||||
|
||||
public void loadAsync(ExecutorService executorService) {
|
||||
executorService.execute(this::load);
|
||||
}
|
||||
|
||||
public void loadSettings(PacketEventsSettings settings) {
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
public void init(final Plugin plugin) {
|
||||
init(plugin, settings);
|
||||
public void init() {
|
||||
init(getSettings());
|
||||
}
|
||||
|
||||
public void init(final Plugin pl, PacketEventsSettings packetEventsSettings) {
|
||||
public void init(PacketEventsSettings packetEventsSettings) {
|
||||
//Load if we haven't loaded already
|
||||
load();
|
||||
if (!initialized && !initializing) {
|
||||
initializing = true;
|
||||
settings = packetEventsSettings;
|
||||
if (settings.getInjectAndEjectThreadCount() < 1) {
|
||||
settings.injectAndEjectThreadCount(1);
|
||||
}
|
||||
settings.lock();
|
||||
|
||||
int injectAndEjectThreadCount = settings.getInjectAndEjectThreadCount();
|
||||
injectAndEjectExecutorService = Executors.newFixedThreadPool(injectAndEjectThreadCount, new ThreadFactory() {
|
||||
if (settings.shouldCheckForUpdates()) {
|
||||
handleUpdateCheck();
|
||||
}
|
||||
|
||||
private final AtomicInteger id = new AtomicInteger();
|
||||
//We may not continue until the injector has been initialized!
|
||||
while (!injectorReady.get()) {
|
||||
;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Thread newThread(@NotNull Runnable r) {
|
||||
return new Thread(r, "PacketEvents-inject-eject #" + id.getAndIncrement());
|
||||
}
|
||||
});
|
||||
|
||||
//Register Bukkit listener
|
||||
plugin = pl;
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||
handlerName = "pe-" + plugin.getName();
|
||||
packetHandlerInternal = new PacketHandlerInternal();
|
||||
Bukkit.getPluginManager().registerEvents(bukkitEventProcessorInternal, plugin);
|
||||
for (final Player p : Bukkit.getOnlinePlayers()) {
|
||||
try {
|
||||
getPlayerUtils().injectPlayer(p);
|
||||
injector.injectPlayer(p);
|
||||
PacketEvents.get().getEventManager().callEvent(new PostPlayerInjectEvent(p, false));
|
||||
} catch (Exception ex) {
|
||||
p.kickPlayer(getSettings().getInjectionFailureMessage());
|
||||
p.kickPlayer("Failed to inject... Please rejoin!");
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.shouldCheckForUpdates()) {
|
||||
Thread thread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
UpdateChecker.UpdateCheckerStatus status = updateChecker.checkForUpdate();
|
||||
}
|
||||
}, "PacketEvents-update-check-thread");
|
||||
thread.start();
|
||||
}
|
||||
initialized = true;
|
||||
initializing = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void init(Plugin plugin) {
|
||||
init(plugin, settings);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void init(Plugin pl, PacketEventsSettings packetEventsSettings) {
|
||||
init(packetEventsSettings);
|
||||
}
|
||||
|
||||
public void terminate() {
|
||||
if (initialized && !terminating) {
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
packetHandlerInternal.ejectPlayer(player);
|
||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
||||
injector.ejectPlayer(p);
|
||||
}
|
||||
packetHandlerInternal.cleanup();
|
||||
injector.eject();
|
||||
|
||||
getEventManager().unregisterAllListeners();
|
||||
injectAndEjectExecutorService.shutdownNow();
|
||||
initialized = false;
|
||||
terminating = false;
|
||||
}
|
||||
@@ -201,6 +218,7 @@ public final class PacketEvents implements Listener, EventManager {
|
||||
|
||||
/**
|
||||
* Use {@link #terminate()}. This is deprecated
|
||||
*
|
||||
* @deprecated "Stop" might be misleading and "terminate" sounds better I guess...
|
||||
*/
|
||||
@Deprecated
|
||||
@@ -208,27 +226,27 @@ public final class PacketEvents implements Listener, EventManager {
|
||||
terminate();
|
||||
}
|
||||
|
||||
public boolean hasLoaded() {
|
||||
return loaded;
|
||||
}
|
||||
|
||||
public boolean isLoading() {
|
||||
return loading;
|
||||
}
|
||||
|
||||
public boolean isInitializing() {
|
||||
return initializing;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean isStopping() {
|
||||
return terminating;
|
||||
public boolean hasLoaded() {
|
||||
return loaded;
|
||||
}
|
||||
|
||||
public boolean isTerminating() {
|
||||
return terminating;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean isStopping() {
|
||||
return isTerminating();
|
||||
}
|
||||
|
||||
public boolean isInitializing() {
|
||||
return initializing;
|
||||
}
|
||||
|
||||
public boolean isInitialized() {
|
||||
return initialized;
|
||||
}
|
||||
@@ -270,72 +288,36 @@ public final class PacketEvents implements Listener, EventManager {
|
||||
return updateChecker;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onLogin(final PlayerLoginEvent e) {
|
||||
if (getSettings().shouldInjectEarly()) {
|
||||
try {
|
||||
packetHandlerInternal.injectPlayer(e.getPlayer());
|
||||
} catch (Exception ex) {
|
||||
e.disallow(PlayerLoginEvent.Result.KICK_OTHER, PacketEvents.get().getSettings().getInjectionFailureMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void onJoin(final PlayerJoinEvent e) {
|
||||
final InetSocketAddress address = e.getPlayer().getAddress();
|
||||
boolean viaAvailable = ViaVersionLookupUtils.isAvailable();
|
||||
PacketEvents.get().getPlayerUtils().loginTime.put(e.getPlayer().getUniqueId(), System.currentTimeMillis());
|
||||
if (viaAvailable) {
|
||||
PacketEvents.get().getPlayerUtils().clientVersionsMap.put(e.getPlayer().getAddress(), ClientVersion.TEMP_UNRESOLVED);
|
||||
Bukkit.getScheduler().runTaskLaterAsynchronously(getPlugin(), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int protocolVersion = VersionLookupUtils.getProtocolVersion(e.getPlayer());
|
||||
ClientVersion version = ClientVersion.getClientVersion(protocolVersion);
|
||||
PacketEvents.get().getPlayerUtils().clientVersionsMap.put(address, version);
|
||||
PacketEvents.get().getEventManager().callEvent(new PostPlayerInjectEvent(e.getPlayer(), true));
|
||||
}
|
||||
}, 1L);
|
||||
} else if (getServerUtils().getVersion() == ServerVersion.v_1_7_10) {
|
||||
ClientVersion version = ClientVersion.getClientVersion(ProtocolVersionAccessor_v_1_7.getProtocolVersion(e.getPlayer()));
|
||||
if (version == ClientVersion.UNRESOLVED) {
|
||||
version = getPlayerUtils().tempClientVersionMap.get(address);
|
||||
if (version == null) {
|
||||
version = ClientVersion.UNRESOLVED;
|
||||
}
|
||||
}
|
||||
getPlayerUtils().clientVersionsMap.put(address, version);
|
||||
}
|
||||
|
||||
if (!getSettings().shouldInjectEarly()) {
|
||||
try {
|
||||
packetHandlerInternal.injectPlayer(e.getPlayer());
|
||||
//Injection was successful as no exception was thrown...
|
||||
if (!viaAvailable) {
|
||||
if (ProtocolLibVersionLookupUtils.isAvailable()) {
|
||||
ClientVersion version = ClientVersion.getClientVersion(ProtocolLibVersionLookupUtils.getProtocolVersion(e.getPlayer()));
|
||||
PacketEvents.get().getPlayerUtils().clientVersionsMap.put(address, version);
|
||||
private void handleUpdateCheck() {
|
||||
Thread thread = new Thread(() -> {
|
||||
PacketEvents.get().getPlugin().getLogger().info("[PacketEvents] Checking for an update, please wait...");
|
||||
UpdateChecker.UpdateCheckerStatus status = updateChecker.checkForUpdate();
|
||||
int seconds = 5;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
if (status == UpdateChecker.UpdateCheckerStatus.FAILED) {
|
||||
PacketEvents.get().getPlugin().getLogger().severe("[PacketEvents] Checking for an update again in " + seconds + " seconds...");
|
||||
try {
|
||||
Thread.sleep(seconds * 1000L);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
PacketEvents.get().getEventManager().callEvent(new PostPlayerInjectEvent(e.getPlayer(), false));
|
||||
|
||||
seconds *= 2;
|
||||
|
||||
status = updateChecker.checkForUpdate();
|
||||
|
||||
if (i == 4) {
|
||||
PacketEvents.get().getPlugin().getLogger().severe("[PacketEvents] PacketEvents failed to check for an update. No longer retrying.");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
e.getPlayer().kickPlayer(getSettings().getInjectionFailureMessage());
|
||||
|
||||
}
|
||||
} else {
|
||||
if (!viaAvailable) {
|
||||
PacketEvents.get().getEventManager().callEvent(new PostPlayerInjectEvent(e.getPlayer(), false));
|
||||
}
|
||||
}
|
||||
|
||||
}, "PacketEvents-update-check-thread");
|
||||
thread.start();
|
||||
}
|
||||
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onQuit(final PlayerQuitEvent e) {
|
||||
UUID uuid = e.getPlayer().getUniqueId();
|
||||
packetHandlerInternal.ejectPlayer(e.getPlayer());
|
||||
PacketEvents.get().getPlayerUtils().loginTime.remove(uuid);
|
||||
PacketEvents.get().getPlayerUtils().playerPingMap.remove(uuid);
|
||||
PacketEvents.get().getPlayerUtils().playerSmoothedPingMap.remove(uuid);
|
||||
}
|
||||
}
|
||||
@@ -24,28 +24,31 @@
|
||||
|
||||
package io.github.retrooper.packetevents;
|
||||
|
||||
import io.github.retrooper.packetevents.settings.PacketEventsSettings;
|
||||
import io.github.retrooper.packetevents.utils.server.ServerVersion;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public class PacketEventsPlugin extends JavaPlugin {
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
|
||||
//Return value of create is your PacketEvents instance.
|
||||
PacketEvents instance = PacketEvents.create(this);
|
||||
PacketEventsSettings settings = instance.getSettings();
|
||||
settings
|
||||
.fallbackServerVersion(ServerVersion.v_1_7_10)
|
||||
.compatInjector(false)
|
||||
.checkForUpdates(false);
|
||||
PacketEvents.get().loadAsyncNewThread();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
if (PacketEvents.get() == null) {
|
||||
PacketEvents.create(this);
|
||||
PacketEvents.get().load();
|
||||
PacketEvents.get().init(this);
|
||||
}
|
||||
//Other way to access your instance...
|
||||
PacketEvents.get().init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
if (PacketEvents.get() != null) {
|
||||
PacketEvents.get().terminate();
|
||||
}
|
||||
PacketEvents.get().terminate();
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,11 @@ public abstract class PacketEvent implements CallableEvent {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public void callPacketEvent(final PacketListenerDynamic listener) {
|
||||
listener.onPacketEvent(this);
|
||||
public void callPacketEventExternal(final PacketListenerAbstract listener) {
|
||||
listener.onPacketEventExternal(this);
|
||||
}
|
||||
|
||||
public boolean isInbuilt() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ package io.github.retrooper.packetevents.event;
|
||||
* Implement this interface in your listener if you are using the legacy event system.
|
||||
*
|
||||
* @author retrooper
|
||||
* @see PacketListenerDynamic
|
||||
* @see PacketListenerAbstract
|
||||
* @since 1.2.6
|
||||
* @deprecated There is a new and better listener for the new event system.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
package io.github.retrooper.packetevents.event;
|
||||
|
||||
import io.github.retrooper.packetevents.event.impl.*;
|
||||
import io.github.retrooper.packetevents.event.priority.PacketEventPriority;
|
||||
import io.github.retrooper.packetevents.utils.immutableset.ImmutableSetCustom;
|
||||
|
||||
/**
|
||||
* Abstract packet listener.
|
||||
* @author retrooper
|
||||
* @since 1.8
|
||||
*/
|
||||
public abstract class PacketListenerAbstract {
|
||||
private final PacketEventPriority priority;
|
||||
public ImmutableSetCustom<Byte> serverSidedStatusAllowance;
|
||||
public ImmutableSetCustom<Byte> serverSidedLoginAllowance;
|
||||
public ImmutableSetCustom<Byte> serverSidedPlayAllowance;
|
||||
|
||||
public ImmutableSetCustom<Byte> clientSidedStatusAllowance;
|
||||
public ImmutableSetCustom<Byte> clientSidedHandshakeAllowance;
|
||||
public ImmutableSetCustom<Byte> clientSidedLoginAllowance;
|
||||
public ImmutableSetCustom<Byte> clientSidedPlayAllowance;
|
||||
|
||||
public PacketListenerAbstract(final PacketEventPriority priority) {
|
||||
this.priority = priority;
|
||||
this.serverSidedStatusAllowance = null;
|
||||
this.serverSidedLoginAllowance = null;
|
||||
this.serverSidedPlayAllowance = null;
|
||||
|
||||
this.clientSidedStatusAllowance = null;
|
||||
this.clientSidedHandshakeAllowance = null;
|
||||
this.clientSidedLoginAllowance = null;
|
||||
this.clientSidedPlayAllowance = null;
|
||||
}
|
||||
|
||||
|
||||
public PacketListenerAbstract() {
|
||||
this(PacketEventPriority.NORMAL);
|
||||
}
|
||||
|
||||
public final PacketEventPriority getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
public void onPacketStatusReceive(PacketStatusReceiveEvent event) {
|
||||
}
|
||||
|
||||
public void onPacketStatusSend(PacketStatusSendEvent event) {
|
||||
}
|
||||
|
||||
public void onPacketHandshakeReceive(PacketHandshakeReceiveEvent event) {
|
||||
}
|
||||
|
||||
public void onPacketLoginReceive(PacketLoginReceiveEvent event) {
|
||||
}
|
||||
|
||||
public void onPacketLoginSend(PacketLoginSendEvent event) {
|
||||
}
|
||||
|
||||
public void onPacketPlayReceive(PacketPlayReceiveEvent event) {
|
||||
}
|
||||
|
||||
public void onPacketPlaySend(PacketPlaySendEvent event) {
|
||||
}
|
||||
|
||||
public void onPostPacketPlayReceive(PostPacketPlayReceiveEvent event) {
|
||||
}
|
||||
|
||||
public void onPostPacketPlaySend(PostPacketPlaySendEvent event) {
|
||||
}
|
||||
|
||||
public void onPostPlayerInject(PostPlayerInjectEvent event) {
|
||||
}
|
||||
|
||||
public void onPlayerInject(PlayerInjectEvent event) {
|
||||
}
|
||||
|
||||
public void onPlayerEject(PlayerEjectEvent event) {
|
||||
}
|
||||
|
||||
public void onPacketEventExternal(PacketEvent event) {
|
||||
}
|
||||
|
||||
public final void addServerSidedStatusFilter(Byte... statusPacketIDs) {
|
||||
if (this.serverSidedStatusAllowance == null) {
|
||||
this.serverSidedStatusAllowance = new ImmutableSetCustom<>(statusPacketIDs);
|
||||
} else {
|
||||
this.serverSidedStatusAllowance.addAll(statusPacketIDs);
|
||||
}
|
||||
}
|
||||
|
||||
public final void addServerSidedLoginFilter(Byte... loginPacketIDs) {
|
||||
if (this.serverSidedLoginAllowance == null) {
|
||||
this.serverSidedLoginAllowance = new ImmutableSetCustom<>(loginPacketIDs);
|
||||
} else {
|
||||
this.serverSidedLoginAllowance.addAll(loginPacketIDs);
|
||||
}
|
||||
}
|
||||
|
||||
public final void addServerSidedPlayFilter(Byte... playPacketIDs) {
|
||||
if (this.serverSidedPlayAllowance == null) {
|
||||
this.serverSidedPlayAllowance = new ImmutableSetCustom<>(playPacketIDs);
|
||||
} else {
|
||||
this.serverSidedPlayAllowance.addAll(playPacketIDs);
|
||||
}
|
||||
}
|
||||
|
||||
public final void addClientSidedStatusFilter(Byte... statusPacketIDs) {
|
||||
if (this.clientSidedStatusAllowance == null) {
|
||||
this.clientSidedStatusAllowance = new ImmutableSetCustom<>(statusPacketIDs);
|
||||
} else {
|
||||
this.clientSidedStatusAllowance.addAll(statusPacketIDs);
|
||||
}
|
||||
}
|
||||
|
||||
public final void addClientSidedHandshakeFilter(Byte... handshakePacketIDs) {
|
||||
if (this.clientSidedHandshakeAllowance == null) {
|
||||
this.clientSidedHandshakeAllowance = new ImmutableSetCustom<>(handshakePacketIDs);
|
||||
} else {
|
||||
this.clientSidedHandshakeAllowance.addAll(handshakePacketIDs);
|
||||
}
|
||||
}
|
||||
|
||||
public final void addClientSidedLoginFilter(Byte... loginPacketIDs) {
|
||||
if (this.clientSidedLoginAllowance == null) {
|
||||
this.clientSidedLoginAllowance = new ImmutableSetCustom<>(loginPacketIDs);
|
||||
} else {
|
||||
this.clientSidedLoginAllowance.addAll(loginPacketIDs);
|
||||
}
|
||||
}
|
||||
|
||||
public final void addClientSidedPlayFilter(Byte... playPacketIDs) {
|
||||
if (this.clientSidedPlayAllowance == null) {
|
||||
this.clientSidedPlayAllowance = new ImmutableSetCustom<>(playPacketIDs);
|
||||
} else {
|
||||
this.clientSidedPlayAllowance.addAll(playPacketIDs);
|
||||
}
|
||||
}
|
||||
|
||||
public final void filterAll() {
|
||||
filterServerSidedStatus();
|
||||
filterServerSidedLogin();
|
||||
filterServerSidedPlay();
|
||||
|
||||
filterClientSidedStatus();
|
||||
filterClientSidedHandshake();
|
||||
filterClientSidedLogin();
|
||||
filterClientSidedPlay();
|
||||
}
|
||||
|
||||
public final void filterServerSidedStatus() {
|
||||
this.serverSidedStatusAllowance = new ImmutableSetCustom<>();
|
||||
}
|
||||
|
||||
public final void filterServerSidedLogin() {
|
||||
this.serverSidedLoginAllowance = new ImmutableSetCustom<>();
|
||||
}
|
||||
|
||||
public final void filterServerSidedPlay() {
|
||||
this.serverSidedPlayAllowance = new ImmutableSetCustom<>();
|
||||
}
|
||||
|
||||
public final void filterClientSidedStatus() {
|
||||
this.clientSidedStatusAllowance = new ImmutableSetCustom<>();
|
||||
}
|
||||
|
||||
public final void filterClientSidedHandshake() {
|
||||
this.clientSidedHandshakeAllowance = new ImmutableSetCustom<>();
|
||||
}
|
||||
|
||||
public final void filterClientSidedLogin() {
|
||||
this.clientSidedLoginAllowance = new ImmutableSetCustom<>();
|
||||
}
|
||||
|
||||
public final void filterClientSidedPlay() {
|
||||
this.clientSidedPlayAllowance = new ImmutableSetCustom<>();
|
||||
}
|
||||
}
|
||||
@@ -24,68 +24,23 @@
|
||||
|
||||
package io.github.retrooper.packetevents.event;
|
||||
|
||||
import io.github.retrooper.packetevents.event.impl.*;
|
||||
import io.github.retrooper.packetevents.event.priority.PacketEventPriority;
|
||||
|
||||
/**
|
||||
* Dynamic packet event listener.
|
||||
* Implement whatever event method you need.
|
||||
* Nothing will happen if you don't implement an event method.
|
||||
* Deprecated abstract PacketListener.
|
||||
* Please use {@link PacketListenerAbstract}, but this class will still work for a bit.
|
||||
*
|
||||
* @author retrooper
|
||||
* @since 1.7.7
|
||||
*/
|
||||
public abstract class PacketListenerDynamic {
|
||||
private final PacketEventPriority priority;
|
||||
|
||||
@Deprecated
|
||||
public abstract class PacketListenerDynamic extends PacketListenerAbstract {
|
||||
public PacketListenerDynamic(final PacketEventPriority priority) {
|
||||
this.priority = priority;
|
||||
super(priority);
|
||||
}
|
||||
|
||||
|
||||
public PacketListenerDynamic() {
|
||||
this(PacketEventPriority.NORMAL);
|
||||
}
|
||||
|
||||
public PacketEventPriority getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
public void onPacketStatusReceive(PacketStatusReceiveEvent event) {
|
||||
|
||||
}
|
||||
|
||||
public void onPacketStatusSend(PacketStatusSendEvent event) {
|
||||
}
|
||||
|
||||
public void onPacketLoginReceive(PacketLoginReceiveEvent event) {
|
||||
}
|
||||
|
||||
public void onPacketLoginSend(PacketLoginSendEvent event) {
|
||||
|
||||
}
|
||||
|
||||
public void onPacketPlayReceive(PacketPlayReceiveEvent event) {
|
||||
}
|
||||
|
||||
public void onPacketPlaySend(PacketPlaySendEvent event) {
|
||||
}
|
||||
|
||||
public void onPostPacketPlayReceive(PostPacketPlayReceiveEvent event) {
|
||||
}
|
||||
|
||||
public void onPostPacketPlaySend(PostPacketPlaySendEvent event) {
|
||||
}
|
||||
|
||||
public void onPostPlayerInject(PostPlayerInjectEvent event) {
|
||||
|
||||
}
|
||||
|
||||
public void onPlayerInject(PlayerInjectEvent event) {
|
||||
}
|
||||
|
||||
public void onPlayerEject(PlayerEjectEvent event) {
|
||||
}
|
||||
|
||||
public void onPacketEvent(PacketEvent event) {
|
||||
super(PacketEventPriority.NORMAL);
|
||||
}
|
||||
}
|
||||
@@ -25,14 +25,14 @@
|
||||
package io.github.retrooper.packetevents.event.eventtypes;
|
||||
|
||||
import io.github.retrooper.packetevents.event.PacketEvent;
|
||||
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
|
||||
import io.github.retrooper.packetevents.event.PacketListenerAbstract;
|
||||
import io.github.retrooper.packetevents.event.impl.PacketPlayReceiveEvent;
|
||||
|
||||
/**
|
||||
* The {@link PacketEvent} implements this interface.
|
||||
* Every inbuilt event should implement the {@link #call(PacketListenerDynamic)} method.
|
||||
* Every inbuilt event should implement the {@link #call(PacketListenerAbstract)} method.
|
||||
* If you are making a custom event, don't implement this.
|
||||
* The {@link PacketListenerDynamic#onPacketEvent(PacketEvent)} method is called for every event,
|
||||
* The {@link PacketListenerAbstract#onPacketEventExternal(PacketEvent)} method is called for every event that is not in-built.
|
||||
* including custom events.
|
||||
*
|
||||
* @author retrooper
|
||||
@@ -40,5 +40,5 @@ import io.github.retrooper.packetevents.event.impl.PacketPlayReceiveEvent;
|
||||
* @since 1.8
|
||||
*/
|
||||
public interface CallableEvent {
|
||||
void call(PacketListenerDynamic listener);
|
||||
void call(PacketListenerAbstract listener);
|
||||
}
|
||||
@@ -54,18 +54,4 @@ public interface CancellableEvent {
|
||||
* @param val Is the event cancelled
|
||||
*/
|
||||
void setCancelled(boolean val);
|
||||
|
||||
/**
|
||||
* Cancel the event.
|
||||
* You can achieve the same result by just using {@link #setCancelled(boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
void cancel();
|
||||
|
||||
/**
|
||||
* Uncancel the event.
|
||||
* You can achieve the same result by just using {@link #setCancelled(boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
void uncancel();
|
||||
}
|
||||
-10
@@ -15,16 +15,6 @@ public abstract class CancellableNMSPacketEvent extends NMSPacketEvent implement
|
||||
super(address, packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uncancel() {
|
||||
cancelled = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
|
||||
+11
-3
@@ -44,15 +44,16 @@ public abstract class NMSPacketEvent extends PacketEvent implements CallableEven
|
||||
private final InetSocketAddress socketAddress;
|
||||
protected NMSPacket packet;
|
||||
protected boolean cancelled;
|
||||
private final byte packetID;
|
||||
|
||||
public NMSPacketEvent(Object channel, NMSPacket packet) {
|
||||
this.socketAddress = ChannelUtils.getSocketAddress(channel);
|
||||
this.packet = packet;
|
||||
this(ChannelUtils.getSocketAddress(channel), packet);//Call the constructor below
|
||||
}
|
||||
|
||||
public NMSPacketEvent(InetSocketAddress address, NMSPacket packet) {
|
||||
this.socketAddress = address;
|
||||
this.packet = packet;
|
||||
packetID = PacketType.packetIDMap.getOrDefault(packet.getRawNMSPacket().getClass(), PacketType.INVALID);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,5 +105,12 @@ public abstract class NMSPacketEvent extends PacketEvent implements CallableEven
|
||||
*
|
||||
* @return Packet ID.
|
||||
*/
|
||||
public abstract byte getPacketId();
|
||||
public byte getPacketId() {
|
||||
return packetID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInbuilt() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
package io.github.retrooper.packetevents.event.impl;
|
||||
|
||||
import io.github.retrooper.packetevents.event.PacketListenerAbstract;
|
||||
import io.github.retrooper.packetevents.event.eventtypes.CancellableNMSPacketEvent;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
/**
|
||||
* The {@code PacketHandshakeReceiveEvent} event is fired whenever the a HANDSHAKE packet is received from a client.
|
||||
* The {@code PacketHandshakeReceiveEvent} does not have to do with a bukkit player object due to the player object being null in this state.
|
||||
* Use the {@link #getSocketAddress()} to identify who sends the packet.
|
||||
*
|
||||
* @author retrooper
|
||||
* @see <a href="https://wiki.vg/Protocol#Handshaking">https://wiki.vg/Protocol#Handshaking</a>
|
||||
* @since 1.8
|
||||
*/
|
||||
public class PacketHandshakeReceiveEvent extends CancellableNMSPacketEvent {
|
||||
public PacketHandshakeReceiveEvent(final Object channel, final NMSPacket packet) {
|
||||
super(channel, packet);
|
||||
}
|
||||
|
||||
public PacketHandshakeReceiveEvent(final InetSocketAddress socketAddress, final NMSPacket packet) {
|
||||
super(socketAddress, packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void call(PacketListenerAbstract listener) {
|
||||
if (listener.clientSidedLoginAllowance == null || listener.clientSidedLoginAllowance.contains(getPacketId())) {
|
||||
listener.onPacketHandshakeReceive(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-18
@@ -24,9 +24,8 @@
|
||||
|
||||
package io.github.retrooper.packetevents.event.impl;
|
||||
|
||||
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
|
||||
import io.github.retrooper.packetevents.event.PacketListenerAbstract;
|
||||
import io.github.retrooper.packetevents.event.eventtypes.CancellableNMSPacketEvent;
|
||||
import io.github.retrooper.packetevents.packettype.PacketType;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
@@ -50,22 +49,10 @@ public class PacketLoginReceiveEvent extends CancellableNMSPacketEvent {
|
||||
super(socketAddress, packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Each binding in each packet state has their own constants.
|
||||
* Example Usage:
|
||||
* <p>
|
||||
* {@code if (getPacketId() == PacketType.Login.Client.HANDSHAKE) }
|
||||
* </p>
|
||||
*
|
||||
* @return Packet ID.
|
||||
*/
|
||||
@Override
|
||||
public byte getPacketId() {
|
||||
return PacketType.Login.Client.packetIds.getOrDefault(packet.getRawNMSPacket().getClass(), PacketType.INVALID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void call(PacketListenerDynamic listener) {
|
||||
listener.onPacketLoginReceive(this);
|
||||
public void call(PacketListenerAbstract listener) {
|
||||
if (listener.clientSidedLoginAllowance == null || listener.clientSidedLoginAllowance.contains(getPacketId())) {
|
||||
listener.onPacketLoginReceive(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,9 +24,8 @@
|
||||
|
||||
package io.github.retrooper.packetevents.event.impl;
|
||||
|
||||
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
|
||||
import io.github.retrooper.packetevents.event.PacketListenerAbstract;
|
||||
import io.github.retrooper.packetevents.event.eventtypes.CancellableNMSPacketEvent;
|
||||
import io.github.retrooper.packetevents.packettype.PacketType;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
@@ -51,12 +50,9 @@ public class PacketLoginSendEvent extends CancellableNMSPacketEvent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getPacketId() {
|
||||
return PacketType.Login.Server.packetIds.getOrDefault(packet.getRawNMSPacket().getClass(), PacketType.INVALID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void call(PacketListenerDynamic listener) {
|
||||
listener.onPacketLoginSend(this);
|
||||
public void call(PacketListenerAbstract listener) {
|
||||
if (listener.serverSidedLoginAllowance == null || listener.serverSidedLoginAllowance.contains(getPacketId())) {
|
||||
listener.onPacketLoginSend(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-28
@@ -24,10 +24,9 @@
|
||||
|
||||
package io.github.retrooper.packetevents.event.impl;
|
||||
|
||||
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
|
||||
import io.github.retrooper.packetevents.event.PacketListenerAbstract;
|
||||
import io.github.retrooper.packetevents.event.eventtypes.CancellableNMSPacketEvent;
|
||||
import io.github.retrooper.packetevents.event.eventtypes.PlayerEvent;
|
||||
import io.github.retrooper.packetevents.packettype.PacketType;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -45,7 +44,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
public final class PacketPlayReceiveEvent extends CancellableNMSPacketEvent implements PlayerEvent {
|
||||
private final Player player;
|
||||
|
||||
public PacketPlayReceiveEvent(final Player player, final Object channel, final NMSPacket packet) {
|
||||
public PacketPlayReceiveEvent(Player player, Object channel, NMSPacket packet) {
|
||||
super(channel, packet);
|
||||
this.player = player;
|
||||
}
|
||||
@@ -62,31 +61,10 @@ public final class PacketPlayReceiveEvent extends CancellableNMSPacketEvent impl
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the socket address of the packet sender.
|
||||
* This address if guaranteed to never be null.
|
||||
* You could use this to identify who is sending packets
|
||||
* whenever the player object is null.
|
||||
*
|
||||
* @return Packet sender's socket address.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Each binding in each packet state has their own constants.
|
||||
* Example Usage:
|
||||
* <p>
|
||||
* {@code if (getPacketId() == PacketType.Play.Client.USE_ENTITY) }
|
||||
* </p>
|
||||
*
|
||||
* @return Packet ID.
|
||||
*/
|
||||
@Override
|
||||
public byte getPacketId() {
|
||||
return PacketType.Play.Client.packetIds.getOrDefault(packet.getRawNMSPacket().getClass(), PacketType.INVALID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void call(PacketListenerDynamic listener) {
|
||||
listener.onPacketPlayReceive(this);
|
||||
public void call(PacketListenerAbstract listener) {
|
||||
if (listener.clientSidedPlayAllowance == null || listener.clientSidedPlayAllowance.contains(getPacketId())) {
|
||||
listener.onPacketPlayReceive(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,10 +24,9 @@
|
||||
|
||||
package io.github.retrooper.packetevents.event.impl;
|
||||
|
||||
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
|
||||
import io.github.retrooper.packetevents.event.PacketListenerAbstract;
|
||||
import io.github.retrooper.packetevents.event.eventtypes.CancellableNMSPacketEvent;
|
||||
import io.github.retrooper.packetevents.event.eventtypes.PlayerEvent;
|
||||
import io.github.retrooper.packetevents.packettype.PacketType;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -61,23 +60,11 @@ public final class PacketPlaySendEvent extends CancellableNMSPacketEvent impleme
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Each binding in each packet state has their own constants.
|
||||
* Example Usage:
|
||||
* <p>
|
||||
* {@code if (getPacketId() == PacketType.Play.Server.KEEP_ALIVE) }
|
||||
* </p>
|
||||
*
|
||||
* @return Packet ID.
|
||||
*/
|
||||
@Override
|
||||
public byte getPacketId() {
|
||||
return PacketType.Play.Server.packetIds.getOrDefault(packet.getRawNMSPacket().getClass(), PacketType.INVALID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void call(PacketListenerDynamic listener) {
|
||||
listener.onPacketPlaySend(this);
|
||||
public void call(PacketListenerAbstract listener) {
|
||||
if (listener.serverSidedPlayAllowance == null || listener.serverSidedPlayAllowance.contains(getPacketId())) {
|
||||
listener.onPacketPlaySend(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-18
@@ -24,9 +24,8 @@
|
||||
|
||||
package io.github.retrooper.packetevents.event.impl;
|
||||
|
||||
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
|
||||
import io.github.retrooper.packetevents.event.PacketListenerAbstract;
|
||||
import io.github.retrooper.packetevents.event.eventtypes.CancellableNMSPacketEvent;
|
||||
import io.github.retrooper.packetevents.packettype.PacketType;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
@@ -50,22 +49,10 @@ public class PacketStatusReceiveEvent extends CancellableNMSPacketEvent {
|
||||
super(socketAddress, packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Each binding in each packet state has their own constants.
|
||||
* Example Usage:
|
||||
* <p>
|
||||
* {@code if (getPacketId() == PacketType.Status.Client.PING) }
|
||||
* </p>
|
||||
*
|
||||
* @return Packet ID.
|
||||
*/
|
||||
@Override
|
||||
public byte getPacketId() {
|
||||
return PacketType.Status.Client.packetIds.getOrDefault(packet.getRawNMSPacket().getClass(), PacketType.INVALID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void call(PacketListenerDynamic listener) {
|
||||
listener.onPacketStatusReceive(this);
|
||||
public void call(PacketListenerAbstract listener) {
|
||||
if (listener.clientSidedStatusAllowance == null || listener.clientSidedStatusAllowance.contains(getPacketId())) {
|
||||
listener.onPacketStatusReceive(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-17
@@ -24,10 +24,9 @@
|
||||
|
||||
package io.github.retrooper.packetevents.event.impl;
|
||||
|
||||
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
|
||||
import io.github.retrooper.packetevents.event.PacketListenerAbstract;
|
||||
import io.github.retrooper.packetevents.event.eventtypes.CancellableEvent;
|
||||
import io.github.retrooper.packetevents.event.eventtypes.CancellableNMSPacketEvent;
|
||||
import io.github.retrooper.packetevents.packettype.PacketType;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
@@ -52,22 +51,11 @@ public class PacketStatusSendEvent extends CancellableNMSPacketEvent {
|
||||
super(address, packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Each binding in each packet state has their own constants.
|
||||
* Example Usage:
|
||||
* <p>
|
||||
* {@code if (getPacketId() == PacketType.Status.Server.PONG) }
|
||||
* </p>
|
||||
*
|
||||
* @return Packet ID.
|
||||
*/
|
||||
@Override
|
||||
public byte getPacketId() {
|
||||
return PacketType.Status.Server.packetIds.getOrDefault(packet.getRawNMSPacket().getClass(), PacketType.INVALID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void call(PacketListenerDynamic listener) {
|
||||
listener.onPacketStatusSend(this);
|
||||
public void call(PacketListenerAbstract listener) {
|
||||
if (listener.serverSidedStatusAllowance == null || listener.serverSidedStatusAllowance.contains(getPacketId())) {
|
||||
listener.onPacketStatusSend(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,18 +24,15 @@
|
||||
|
||||
package io.github.retrooper.packetevents.event.impl;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.event.PacketEvent;
|
||||
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
|
||||
import io.github.retrooper.packetevents.event.PacketListenerAbstract;
|
||||
import io.github.retrooper.packetevents.event.eventtypes.CancellableEvent;
|
||||
import io.github.retrooper.packetevents.event.eventtypes.PlayerEvent;
|
||||
import io.github.retrooper.packetevents.settings.PacketEventsSettings;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* The {@code PlayerEjectEvent} event is fired whenever a player is ejected.
|
||||
* A player is ejected by PacketEvents whenever they quit the server.
|
||||
* This class implements {@link CancellableEvent} and {@link PlayerEvent}.
|
||||
*
|
||||
* @author retrooper
|
||||
@@ -44,22 +41,10 @@ import org.jetbrains.annotations.NotNull;
|
||||
*/
|
||||
public final class PlayerEjectEvent extends PacketEvent implements CancellableEvent, PlayerEvent {
|
||||
private final Player player;
|
||||
private final boolean async;
|
||||
private boolean cancelled;
|
||||
|
||||
public PlayerEjectEvent(final Player player, final boolean isAsync) {
|
||||
public PlayerEjectEvent(final Player player) {
|
||||
this.player = player;
|
||||
this.async = isAsync;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uncancel() {
|
||||
cancelled = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -85,20 +70,21 @@ public final class PlayerEjectEvent extends PacketEvent implements CancellableEv
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns if the event has been called asynchronously.
|
||||
* If the {@link PacketEventsSettings#shouldEjectAsync()} is enabled, the event will be called asynchronously
|
||||
* and the player will be ejected asynchronously.
|
||||
* The {@link PacketEventsSettings} can be accessed here:
|
||||
*
|
||||
* @return Is the ejection asynchronous.
|
||||
* @see PacketEvents#getSettings()
|
||||
* @return Is the event called async?
|
||||
* @deprecated Now always false
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isAsync() {
|
||||
return async;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void call(PacketListenerDynamic listener) {
|
||||
public void call(PacketListenerAbstract listener) {
|
||||
listener.onPlayerEject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInbuilt() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -26,13 +26,11 @@ package io.github.retrooper.packetevents.event.impl;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.event.PacketEvent;
|
||||
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
|
||||
import io.github.retrooper.packetevents.event.PacketListenerAbstract;
|
||||
import io.github.retrooper.packetevents.event.eventtypes.CancellableEvent;
|
||||
import io.github.retrooper.packetevents.event.eventtypes.PlayerEvent;
|
||||
import io.github.retrooper.packetevents.settings.PacketEventsSettings;
|
||||
import io.github.retrooper.packetevents.utils.netty.channel.ChannelUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
@@ -49,23 +47,11 @@ import java.net.InetSocketAddress;
|
||||
public final class PlayerInjectEvent extends PacketEvent implements CancellableEvent, PlayerEvent {
|
||||
private final Player player;
|
||||
private final InetSocketAddress address;
|
||||
private final boolean async;
|
||||
private boolean cancelled;
|
||||
|
||||
public PlayerInjectEvent(final Player player, final boolean isAsync) {
|
||||
public PlayerInjectEvent(final Player player) {
|
||||
this.player = player;
|
||||
this.address = ChannelUtils.getSocketAddress(PacketEvents.get().packetHandlerInternal.getChannel(player));
|
||||
this.async = isAsync;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uncancel() {
|
||||
cancelled = false;
|
||||
this.address = ChannelUtils.getSocketAddress(PacketEvents.get().packetProcessorInternal.getChannel(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -95,26 +81,26 @@ public final class PlayerInjectEvent extends PacketEvent implements CancellableE
|
||||
*
|
||||
* @return Socket address of the injecting player.
|
||||
*/
|
||||
@NotNull
|
||||
@Nullable
|
||||
public InetSocketAddress getSocketAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns if the event has been called asynchronously.
|
||||
* If the {@link PacketEventsSettings#shouldInjectAsync()} is enabled, the event will be called asynchronously
|
||||
* and the player will be injected asynchronously.
|
||||
* The {@link PacketEventsSettings} can be accessed here:
|
||||
*
|
||||
* @return Is the injection asynchronous.
|
||||
* @see PacketEvents#getSettings()
|
||||
* @deprecated Will always be false
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isAsync() {
|
||||
return async;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void call(PacketListenerDynamic listener) {
|
||||
public void call(PacketListenerAbstract listener) {
|
||||
listener.onPlayerInject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInbuilt() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+5
-21
@@ -24,13 +24,11 @@
|
||||
|
||||
package io.github.retrooper.packetevents.event.impl;
|
||||
|
||||
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
|
||||
import io.github.retrooper.packetevents.event.PacketListenerAbstract;
|
||||
import io.github.retrooper.packetevents.event.eventtypes.NMSPacketEvent;
|
||||
import io.github.retrooper.packetevents.event.eventtypes.PlayerEvent;
|
||||
import io.github.retrooper.packetevents.packettype.PacketType;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* The {@code PostPacketPlayReceiveEvent} event is fired after minecraft processes
|
||||
@@ -54,32 +52,18 @@ public class PostPacketPlayReceiveEvent extends NMSPacketEvent implements Player
|
||||
|
||||
/**
|
||||
* This method returns the bukkit player object of the packet sender.
|
||||
* The player object might be null during early packets.
|
||||
*
|
||||
* @return Packet sender.
|
||||
*/
|
||||
@Nullable
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Each binding in each packet state has their own constants.
|
||||
* Example Usage:
|
||||
* <p>
|
||||
* {@code if (getPacketId() == PacketType.Play.Client.ARM_ANIMATION) }
|
||||
* </p>
|
||||
*
|
||||
* @return Packet ID.
|
||||
*/
|
||||
@Override
|
||||
public byte getPacketId() {
|
||||
return PacketType.Play.Client.packetIds.getOrDefault(packet.getRawNMSPacket().getClass(), PacketType.INVALID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void call(PacketListenerDynamic listener) {
|
||||
listener.onPostPacketPlayReceive(this);
|
||||
public void call(PacketListenerAbstract listener) {
|
||||
if (listener.clientSidedPlayAllowance == null || listener.clientSidedPlayAllowance.contains(getPacketId())) {
|
||||
listener.onPostPacketPlayReceive(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-21
@@ -24,13 +24,11 @@
|
||||
|
||||
package io.github.retrooper.packetevents.event.impl;
|
||||
|
||||
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
|
||||
import io.github.retrooper.packetevents.event.PacketListenerAbstract;
|
||||
import io.github.retrooper.packetevents.event.eventtypes.NMSPacketEvent;
|
||||
import io.github.retrooper.packetevents.event.eventtypes.PlayerEvent;
|
||||
import io.github.retrooper.packetevents.packettype.PacketType;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* The {@code PostPacketPlaySendEvent} event is fired after minecraft processes
|
||||
@@ -54,32 +52,18 @@ public class PostPacketPlaySendEvent extends NMSPacketEvent implements PlayerEve
|
||||
|
||||
/**
|
||||
* This method returns the bukkit player object of the packet sender.
|
||||
* The player object is might be null during early packets.
|
||||
*
|
||||
* @return Packet receiver.
|
||||
*/
|
||||
@Nullable
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Each binding in each packet state has their own constants.
|
||||
* Example Usage:
|
||||
* <p>
|
||||
* {@code if (getPacketId() == PacketType.Play.Server.KEEP_ALIVE) }
|
||||
* </p>
|
||||
*
|
||||
* @return Packet ID.
|
||||
*/
|
||||
@Override
|
||||
public byte getPacketId() {
|
||||
return PacketType.Play.Server.packetIds.getOrDefault(packet.getRawNMSPacket().getClass(), PacketType.INVALID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void call(PacketListenerDynamic listener) {
|
||||
listener.onPostPacketPlaySend(this);
|
||||
public void call(PacketListenerAbstract listener) {
|
||||
if (listener.serverSidedPlayAllowance == null || listener.serverSidedPlayAllowance.contains(getPacketId())) {
|
||||
listener.onPostPacketPlaySend(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-3
@@ -26,7 +26,7 @@ package io.github.retrooper.packetevents.event.impl;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.event.PacketEvent;
|
||||
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
|
||||
import io.github.retrooper.packetevents.event.PacketListenerAbstract;
|
||||
import io.github.retrooper.packetevents.event.eventtypes.PlayerEvent;
|
||||
import io.github.retrooper.packetevents.utils.netty.channel.ChannelUtils;
|
||||
import io.github.retrooper.packetevents.utils.player.ClientVersion;
|
||||
@@ -75,7 +75,7 @@ public class PostPlayerInjectEvent extends PacketEvent implements PlayerEvent {
|
||||
*/
|
||||
@NotNull
|
||||
public Object getChannel() {
|
||||
return PacketEvents.get().packetHandlerInternal.getChannel(player);
|
||||
return PacketEvents.get().packetProcessorInternal.getChannel(player);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -104,7 +104,12 @@ public class PostPlayerInjectEvent extends PacketEvent implements PlayerEvent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void call(PacketListenerDynamic listener) {
|
||||
public void call(PacketListenerAbstract listener) {
|
||||
listener.onPostPlayerInject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInbuilt() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ 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.PacketListenerAbstract;
|
||||
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
|
||||
|
||||
/**
|
||||
@@ -54,7 +55,7 @@ public interface EventManager {
|
||||
*/
|
||||
default EventManager callEvent(PacketEvent event) {
|
||||
//The dynamic event manager calls the legacy event manager.
|
||||
PEEventManager.EVENT_MANAGER_DYNAMIC.callEvent(event);
|
||||
PEEventManager.EVENT_MANAGER_MODERN.callEvent(event);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -113,49 +114,51 @@ public interface EventManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the dynamic event listener.
|
||||
* Register a PacketListenerDynamic listener.
|
||||
*
|
||||
* @param listener {@link PacketListenerDynamic}
|
||||
* @return Same event manager instance.
|
||||
*/
|
||||
@Deprecated
|
||||
default EventManager registerListener(PacketListenerDynamic listener) {
|
||||
PEEventManager.EVENT_MANAGER_MODERN.registerListener(listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register multiple PacketListenerDynamic listeners.
|
||||
*
|
||||
* @param listeners {@link PacketListenerDynamic}
|
||||
* @return Same event manager instance.
|
||||
*/
|
||||
@Deprecated
|
||||
default EventManager registerListeners(PacketListenerDynamic... listeners) {
|
||||
PEEventManager.EVENT_MANAGER_MODERN.registerListeners(listeners);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register a PacketListenerAbstract listener.
|
||||
*
|
||||
* @param listener {@link PacketListenerAbstract}
|
||||
* @return Same event manager instance.
|
||||
*/
|
||||
default EventManager registerListener(PacketListenerAbstract listener) {
|
||||
if (listener != null) {
|
||||
PEEventManager.EVENT_MANAGER_DYNAMIC.registerListener(listener);
|
||||
PEEventManager.EVENT_MANAGER_MODERN.registerListener(listener);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register multiple dynamic event listeners with one method.
|
||||
* Register multiple PacketListenerAbstract listeners.
|
||||
*
|
||||
* @param listeners {@link PacketListenerDynamic}
|
||||
* @param listeners {@link PacketListenerAbstract}
|
||||
* @return Same event manager instance.
|
||||
*/
|
||||
default EventManager registerListeners(PacketListenerDynamic... listeners) {
|
||||
PEEventManager.EVENT_MANAGER_DYNAMIC.registerListeners(listeners);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister the dynamic event listener.
|
||||
*
|
||||
* @param listener {@link PacketListenerDynamic}
|
||||
* @return Same event manager instance.
|
||||
*/
|
||||
default EventManager unregisterListener(PacketListenerDynamic listener) {
|
||||
PEEventManager.EVENT_MANAGER_DYNAMIC.unregisterListener(listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister multiple dynamic event listeners with one method.
|
||||
* Recommended to use the dynamic event listener.
|
||||
*
|
||||
* @param listeners {@link PacketListenerDynamic}
|
||||
* @return Same event manager instance.
|
||||
*/
|
||||
default EventManager unregisterListeners(PacketListenerDynamic... listeners) {
|
||||
PEEventManager.EVENT_MANAGER_DYNAMIC.unregisterListeners(listeners);
|
||||
default EventManager registerListeners(PacketListenerAbstract... listeners) {
|
||||
PEEventManager.EVENT_MANAGER_MODERN.registerListeners(listeners);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -166,7 +169,7 @@ public interface EventManager {
|
||||
* @return Same event manager instance.
|
||||
*/
|
||||
default EventManager unregisterAllListeners() {
|
||||
PEEventManager.EVENT_MANAGER_DYNAMIC.unregisterAllListeners();
|
||||
PEEventManager.EVENT_MANAGER_MODERN.unregisterAllListeners();
|
||||
PEEventManager.EVENT_MANAGER_LEGACY.unregisterAllListeners();
|
||||
return this;
|
||||
}
|
||||
|
||||
-148
@@ -1,148 +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.event.manager;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
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.priority.PacketEventPriority;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
class EventManagerDynamic {
|
||||
/**
|
||||
* All listeners ordered by their priority.
|
||||
* The most low priority ones are at the begging of the list and the most high priority ones are at the end.
|
||||
*/
|
||||
private final List<PacketListenerDynamic> listeners = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Call the PacketEvent.
|
||||
* This method processes the event on all the registered dynamic packet event listeners.
|
||||
* The {@link PacketEventPriority#LOWEST} prioritized listeners will be processing first,
|
||||
* the {@link PacketEventPriority#MONITOR} will be processing last and can
|
||||
* be the final decider whether the event has been cancelled or not.
|
||||
* This call event also calls the legacy event manager call event.
|
||||
*
|
||||
* @param event {@link PacketEvent}
|
||||
* @see EventManagerLegacy#callEvent(PacketEvent, byte)
|
||||
*/
|
||||
public void callEvent(final PacketEvent event) {
|
||||
boolean cancel = false;
|
||||
if (event instanceof CancellableEvent) {
|
||||
cancel = ((CancellableEvent) event).isCancelled();
|
||||
}
|
||||
byte highestReachedPriority = PacketEventPriority.LOWEST.getPriorityValue();
|
||||
for (PacketListenerDynamic listener : listeners) {
|
||||
highestReachedPriority = listener.getPriority().getPriorityValue();
|
||||
try {
|
||||
event.callPacketEvent(listener);
|
||||
event.call(listener);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
PacketEvents.get().getPlugin().getLogger()
|
||||
.log(Level.SEVERE, "PacketEvents found an exception while calling a packet listener.", ex);
|
||||
}
|
||||
if (event instanceof CancellableEvent) {
|
||||
CancellableEvent ce = (CancellableEvent) event;
|
||||
cancel = ce.isCancelled();
|
||||
}
|
||||
}
|
||||
if (event instanceof CancellableEvent) {
|
||||
CancellableEvent ce = (CancellableEvent) event;
|
||||
ce.setCancelled(cancel);
|
||||
}
|
||||
|
||||
PEEventManager.EVENT_MANAGER_LEGACY.callEvent(event, highestReachedPriority);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the dynamic packet event listener.
|
||||
*
|
||||
* @param listener {@link PacketListenerDynamic}
|
||||
*/
|
||||
public void registerListener(final PacketListenerDynamic listener) {
|
||||
final byte priorityValue = listener.getPriority().getPriorityValue();
|
||||
if (listeners.isEmpty()) {
|
||||
listeners.add(listener);
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < listeners.size(); i++) {
|
||||
PacketListenerDynamic other = listeners.get(i);
|
||||
byte otherPriorityValue = other.getPriority().getPriorityValue();
|
||||
if (i + 1 == listeners.size()) {
|
||||
listeners.add(listener);
|
||||
break;
|
||||
} else if (otherPriorityValue == priorityValue) {
|
||||
listeners.add(i + 1, listener);
|
||||
break;
|
||||
} else if (otherPriorityValue > priorityValue) {
|
||||
listeners.add(i, listener);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register multiple dynamic packet event listeners with one method.
|
||||
*
|
||||
* @param listeners {@link PacketListenerDynamic}
|
||||
*/
|
||||
public void registerListeners(PacketListenerDynamic... listeners) {
|
||||
for (PacketListenerDynamic listener : listeners) {
|
||||
registerListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister the dynamic packet event listener.
|
||||
*
|
||||
* @param listener {@link PacketListenerDynamic}
|
||||
*/
|
||||
public void unregisterListener(PacketListenerDynamic listener) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister multiple dynamic packet event listeners with one method.
|
||||
*
|
||||
* @param listeners {@link PacketListenerDynamic}
|
||||
*/
|
||||
public void unregisterListeners(PacketListenerDynamic... listeners) {
|
||||
for (PacketListenerDynamic listener : listeners) {
|
||||
unregisterListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister all dynamic packet event listeners.
|
||||
*/
|
||||
public void unregisterAllListeners() {
|
||||
listeners.clear();
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -47,7 +47,7 @@ class EventManagerLegacy {
|
||||
/**
|
||||
* Call a PacketEvent with the legacy event manager.
|
||||
* This method processes the event on all legacy packet event listeners.
|
||||
* This method is actually called by {@link EventManagerDynamic#callEvent(PacketEvent)} as the
|
||||
* This method is actually called by {@link EventManagerModern#callEvent(PacketEvent)} as the
|
||||
* if you mix the two event systems, the dynamic listeners are always processed first and pass
|
||||
* their highest reached event priority that this legacy one has to beat/reach to be able to cancel
|
||||
* the event.
|
||||
@@ -163,4 +163,4 @@ class EventManagerLegacy {
|
||||
public void unregisterAllListeners() {
|
||||
staticRegisteredMethods.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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.PacketEvents;
|
||||
import io.github.retrooper.packetevents.event.PacketEvent;
|
||||
import io.github.retrooper.packetevents.event.PacketListenerAbstract;
|
||||
import io.github.retrooper.packetevents.event.eventtypes.CancellableEvent;
|
||||
import io.github.retrooper.packetevents.event.priority.PacketEventPriority;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Level;
|
||||
|
||||
class EventManagerModern {
|
||||
private final Map<Byte, HashSet<PacketListenerAbstract>> listenersMap = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Call the PacketEvent.
|
||||
* This method processes the event on all the registered dynamic packet event listeners.
|
||||
* The {@link PacketEventPriority#LOWEST} prioritized listeners will be processing first,
|
||||
* the {@link PacketEventPriority#MONITOR} will be processing last and can
|
||||
* be the final decider whether the event has been cancelled or not.
|
||||
* This call event also calls the legacy event manager call event.
|
||||
*
|
||||
* @param event {@link PacketEvent}
|
||||
* @see EventManagerLegacy#callEvent(PacketEvent, byte)
|
||||
*/
|
||||
public void callEvent(final PacketEvent event) {
|
||||
boolean cancel = false;
|
||||
if (event instanceof CancellableEvent) {
|
||||
cancel = ((CancellableEvent) event).isCancelled();
|
||||
}
|
||||
byte highestReachedPriority = PacketEventPriority.LOWEST.getPriorityValue();
|
||||
for (byte priority = PacketEventPriority.LOWEST.getPriorityValue(); priority <= PacketEventPriority.MONITOR.getPriorityValue(); priority++) {
|
||||
HashSet<PacketListenerAbstract> listeners = listenersMap.get(priority);
|
||||
if (listeners != null) {
|
||||
for (PacketListenerAbstract listener : listeners) {
|
||||
try {
|
||||
event.call(listener);
|
||||
} catch (Exception ex) {
|
||||
PacketEvents.get().getPlugin().getLogger()
|
||||
.log(Level.SEVERE, "PacketEvents found an exception while calling a packet listener.", ex);
|
||||
}
|
||||
if (event instanceof CancellableEvent) {
|
||||
CancellableEvent ce = (CancellableEvent) event;
|
||||
cancel = ce.isCancelled();
|
||||
highestReachedPriority = priority;
|
||||
}
|
||||
}
|
||||
if (event instanceof CancellableEvent) {
|
||||
CancellableEvent ce = (CancellableEvent) event;
|
||||
ce.setCancelled(cancel);
|
||||
}
|
||||
}
|
||||
}
|
||||
PEEventManager.EVENT_MANAGER_LEGACY.callEvent(event, highestReachedPriority);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the dynamic packet event listener.
|
||||
*
|
||||
* @param listener {@link PacketListenerAbstract}
|
||||
*/
|
||||
public synchronized void registerListener(final PacketListenerAbstract listener) {
|
||||
byte priority = listener.getPriority().getPriorityValue();
|
||||
HashSet<PacketListenerAbstract> listenerSet = listenersMap.get(priority);
|
||||
if (listenerSet == null) {
|
||||
listenerSet = new HashSet<>();
|
||||
}
|
||||
listenerSet.add(listener);
|
||||
listenersMap.put(priority, listenerSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register multiple dynamic packet event listeners with one method.
|
||||
*
|
||||
* @param listeners {@link PacketListenerAbstract}
|
||||
*/
|
||||
public synchronized void registerListeners(PacketListenerAbstract... listeners) {
|
||||
for (PacketListenerAbstract listener : listeners) {
|
||||
registerListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister all dynamic packet event listeners.
|
||||
*/
|
||||
public synchronized void unregisterAllListeners() {
|
||||
listenersMap.clear();
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,6 @@ package io.github.retrooper.packetevents.event.manager;
|
||||
public class PEEventManager implements EventManager {
|
||||
|
||||
public static final EventManagerLegacy EVENT_MANAGER_LEGACY = new EventManagerLegacy();
|
||||
public static final EventManagerDynamic EVENT_MANAGER_DYNAMIC = new EventManagerDynamic();
|
||||
public static final EventManagerModern EVENT_MANAGER_MODERN = new EventManagerModern();
|
||||
|
||||
}
|
||||
+11
-21
@@ -26,9 +26,9 @@ package io.github.retrooper.packetevents.event.priority;
|
||||
|
||||
/**
|
||||
* Event priority enum for the new event system.
|
||||
* The event priority counts for the whole {@link io.github.retrooper.packetevents.event.PacketListenerDynamic}
|
||||
* The event priority counts for the whole {@link io.github.retrooper.packetevents.event.PacketListenerAbstract}
|
||||
* and not for just one event.
|
||||
* The priority can be specified in the PacketListenerDynamic constructor.
|
||||
* The priority can be specified in the PacketListenerAbstract constructor.
|
||||
* If you don't specify a priority in the constructor, it will use the {@link #NORMAL} priority.
|
||||
*
|
||||
* @author retrooper
|
||||
@@ -41,7 +41,7 @@ public enum PacketEventPriority {
|
||||
* Use this if you need to be the first processing the event and
|
||||
* need no power in cancelling an event or preventing an event cancellation.
|
||||
*/
|
||||
LOWEST((byte) 0),
|
||||
LOWEST,
|
||||
|
||||
/**
|
||||
* A weak event priority.
|
||||
@@ -49,7 +49,7 @@ public enum PacketEventPriority {
|
||||
* Use this if you would prefer to be one of the first to process the event,
|
||||
* but don't mind if some other listener processes before you.
|
||||
*/
|
||||
LOW((byte) 1),
|
||||
LOW,
|
||||
|
||||
/**
|
||||
* Default event priority.
|
||||
@@ -57,14 +57,14 @@ public enum PacketEventPriority {
|
||||
* Use this if you don't really care/know when you process or just want to
|
||||
* be in the middle.
|
||||
*/
|
||||
NORMAL((byte) 2),
|
||||
NORMAL,
|
||||
|
||||
/**
|
||||
* Higher than the {@link PacketEventPriority#NORMAL} event priority.
|
||||
* Fourth to be processed(IN THE DYNAMIC EVENT SYSTEM ONLY).
|
||||
* Use this if you want to process before the default event prioritized listeners.
|
||||
*/
|
||||
HIGH((byte) 3),
|
||||
HIGH,
|
||||
|
||||
/**
|
||||
* Second most powerful event priority.
|
||||
@@ -75,7 +75,7 @@ public enum PacketEventPriority {
|
||||
* mind if some other listener urgently needs to decide over you.
|
||||
* {@link PacketEventPriority#MONITOR} is rarely ever recommended to use.
|
||||
*/
|
||||
HIGHEST((byte) 4),
|
||||
HIGHEST,
|
||||
|
||||
/**
|
||||
* Most powerful event priority.
|
||||
@@ -84,24 +84,14 @@ public enum PacketEventPriority {
|
||||
* or urgently need to be the final decider whether the event has cancelled or not.
|
||||
* This is rarely recommended.
|
||||
*/
|
||||
MONITOR((byte) 5);
|
||||
MONITOR;
|
||||
|
||||
final byte priorityValue;
|
||||
|
||||
PacketEventPriority(byte priorityValue) {
|
||||
this.priorityValue = priorityValue;
|
||||
public static PacketEventPriority getPacketEventPriority(byte bytePriority) {
|
||||
return values()[bytePriority];
|
||||
}
|
||||
|
||||
public byte getPriorityValue() {
|
||||
return priorityValue;
|
||||
}
|
||||
|
||||
public static PacketEventPriority getPacketEventPriority(byte bytePriority) {
|
||||
for (PacketEventPriority priority : values()) {
|
||||
if (priority.priorityValue == bytePriority) {
|
||||
return priority;
|
||||
}
|
||||
}
|
||||
return NORMAL;
|
||||
return (byte) ordinal();
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
|
||||
|
||||
/**
|
||||
* An exception thrown by PacketEvents when a wrapper is used although it isn't supported on the local server version.
|
||||
* Make sure to decompile a wrapper before using it, if you are unsure if it is supported through out all the server versions.
|
||||
* We override a {@link WrappedPacket#isSupported()} method if it isn't supported on all server versions.
|
||||
*
|
||||
* @author retrooper
|
||||
* @see WrappedPacket#isSupported()
|
||||
* @see WrappedPacket.SupportedVersions
|
||||
* @since 1.7
|
||||
*/
|
||||
public class WrapperUnsupportedUsageException extends RuntimeException {
|
||||
public WrapperUnsupportedUsageException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public WrapperUnsupportedUsageException(Class<? extends WrappedPacket> wrapperClass) {
|
||||
this("You are using a packet wrapper which happens to be unsupported on the local server version. Packet wrapper you attempted to use: " + ClassUtil.getClassSimpleName(wrapperClass));
|
||||
}
|
||||
}
|
||||
@@ -1,444 +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.handler;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.event.impl.*;
|
||||
import io.github.retrooper.packetevents.injector.GlobalChannelInjector;
|
||||
import io.github.retrooper.packetevents.packettype.PacketType;
|
||||
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.login.in.handshake.WrappedPacketLoginInHandshake;
|
||||
import io.github.retrooper.packetevents.packetwrappers.login.in.start.WrappedPacketLoginInStart;
|
||||
import io.github.retrooper.packetevents.settings.PacketEventsSettings;
|
||||
import io.github.retrooper.packetevents.utils.gameprofile.WrappedGameProfile;
|
||||
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 org.bukkit.entity.Player;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Internal manager of everything related to packets.
|
||||
* For example injecting, channel caching, internal processing, packet sending....
|
||||
* This class is only meant to be used internally.
|
||||
* This could end up being refactored or renamed without a deprecation as it is only meant to be used internally.
|
||||
*
|
||||
* @author retrooper
|
||||
* @see <a href="http://netty.io">http://netty.io</a>
|
||||
* @since 1.7.9
|
||||
*/
|
||||
public class PacketHandlerInternal {
|
||||
public final GlobalChannelInjector injector = new GlobalChannelInjector();
|
||||
public final Map<UUID, Long> keepAliveMap = new HashMap<>();
|
||||
public final Map<String, Object> channelMap = new WeakHashMap<>();
|
||||
|
||||
public PacketHandlerInternal() {
|
||||
injector.prepare();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a player's netty channel object with their name.
|
||||
* This netty channel object is cached in a {@link ConcurrentHashMap} as the value and
|
||||
* the name is the key.
|
||||
* We cache the name and the channel quite early infact,
|
||||
* once we receive the {@link PacketType.Login.Client#START} packet(which contains the game profile)
|
||||
* and the game profile contains the player name.
|
||||
* The wrapper for that packet is {@link WrappedPacketLoginInStart}.
|
||||
* If PacketEvents couldn't cache(when you have {@link PacketEventsSettings#shouldInjectEarly()} set to false),
|
||||
* PacketEvents will use some reflection to see if CraftBukkit has the netty channel.
|
||||
* If you access this before the START login packet was sent, you will for sure experience issues.
|
||||
*
|
||||
* @param player Target player.
|
||||
* @return Netty channel of a player by their name.
|
||||
* @see <a href="https://wiki.vg/Protocol#Login_Start">https://wiki.vg/Protocol#Login_Start</a>
|
||||
* @see Player#getName()
|
||||
*/
|
||||
public Object getChannel(Player player) {
|
||||
String name = player.getName();
|
||||
Object channel = channelMap.get(name);
|
||||
if (channel == null) {
|
||||
channel = NMSUtils.getChannel(player);
|
||||
channelMap.put(name, channel);
|
||||
}
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject a player.
|
||||
* Executed synchronously or asynchronously depending on what you have the associated setting set to.
|
||||
* Injecting a player is basically pairing the cached netty channel
|
||||
* {@link #getChannel(Player)} to a bukkit player object.
|
||||
* Bukkit initializes the {@link Player} object some time after
|
||||
* we inject the netty channel, so we need to pair the two.
|
||||
* PacketEvents already injects a player when the bukkit
|
||||
* {@link org.bukkit.event.player.PlayerJoinEvent} or {@link org.bukkit.event.player.PlayerLoginEvent}
|
||||
* is called, depending on your {@link PacketEventsSettings#shouldInjectEarly()} setting is set to.
|
||||
*
|
||||
* @param player Target bukkit player.
|
||||
*/
|
||||
public void injectPlayer(Player player) {
|
||||
if (PacketEvents.get().getSettings().shouldInjectAsync()) {
|
||||
injectPlayerAsync(player);
|
||||
} else {
|
||||
injectPlayerSync(player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Eject a player.
|
||||
* Executed synchronously or asynchronously depending on what you have the associated setting set to.
|
||||
* Ejecting a player is basically unpairing the cached netty channel
|
||||
* {@link #getChannel(Player)} from the bukkit player.
|
||||
* Do this if you want to stop listening to a user's packets.
|
||||
* PacketEvents already ejects a player when the bukkit
|
||||
* {@link org.bukkit.event.player.PlayerQuitEvent} is called.
|
||||
*
|
||||
* @param player Target player.
|
||||
*/
|
||||
public void ejectPlayer(Player player) {
|
||||
if (PacketEvents.get().getSettings().shouldEjectAsync()) {
|
||||
ejectPlayerAsync(player);
|
||||
} else {
|
||||
ejectPlayerSync(player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronously inject a player.
|
||||
*
|
||||
* @param player Target player.
|
||||
* @see #injectPlayer(Player)
|
||||
*/
|
||||
public void injectPlayerSync(Player player) {
|
||||
PlayerInjectEvent injectEvent = new PlayerInjectEvent(player, false);
|
||||
PacketEvents.get().getEventManager().callEvent(injectEvent);
|
||||
if (!injectEvent.isCancelled()) {
|
||||
injector.injectPlayerSync(player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously inject a player.
|
||||
*
|
||||
* @param player Target player.
|
||||
* @see #injectPlayer(Player)
|
||||
*/
|
||||
public void injectPlayerAsync(Player player) {
|
||||
PlayerInjectEvent injectEvent = new PlayerInjectEvent(player, true);
|
||||
PacketEvents.get().getEventManager().callEvent(injectEvent);
|
||||
if (!injectEvent.isCancelled()) {
|
||||
injector.injectPlayerAsync(player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronously eject a player.
|
||||
*
|
||||
* @param player Target player.
|
||||
* @see #ejectPlayer(Player)
|
||||
*/
|
||||
public void ejectPlayerSync(Player player) {
|
||||
PlayerEjectEvent ejectEvent = new PlayerEjectEvent(player, false);
|
||||
PacketEvents.get().getEventManager().callEvent(ejectEvent);
|
||||
if (!ejectEvent.isCancelled()) {
|
||||
injector.ejectPlayerSync(player);
|
||||
keepAliveMap.remove(player.getUniqueId());
|
||||
channelMap.remove(player.getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously eject a player.
|
||||
*
|
||||
* @param player Target player.
|
||||
* @see #ejectPlayer(Player)
|
||||
*/
|
||||
public void ejectPlayerAsync(Player player) {
|
||||
PlayerEjectEvent ejectEvent = new PlayerEjectEvent(player, true);
|
||||
PacketEvents.get().getEventManager().callEvent(ejectEvent);
|
||||
if (!ejectEvent.isCancelled()) {
|
||||
injector.ejectPlayerAsync(player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write and flush a packet to a netty channel.
|
||||
* This netty channel is an object as 1.7.10 and 1.8 and above
|
||||
* have different netty package locations.
|
||||
*
|
||||
* @param channel Netty channel.
|
||||
* @param packet NMS Packet.
|
||||
*/
|
||||
public void sendPacket(Object channel, Object packet) {
|
||||
injector.sendPacket(channel, packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make PacketEvents process an incoming packet.
|
||||
*
|
||||
* @param player Packet sender.
|
||||
* @param channel Packet sender's netty channel.
|
||||
* @param packet NMS Packet.
|
||||
* @return NMS Packet, null if the event was cancelled.
|
||||
*/
|
||||
public Object read(Player player, Object channel, Object packet) {
|
||||
if (PacketTypeClasses.Login.Client.START.equals(packet.getClass())) {
|
||||
WrappedPacketLoginInStart startWrapper = new WrappedPacketLoginInStart(new NMSPacket(packet));
|
||||
WrappedGameProfile gameProfile = startWrapper.getGameProfile();
|
||||
channelMap.put(gameProfile.name, channel);
|
||||
}
|
||||
if (player == null) {
|
||||
String simpleClassName = ClassUtil.getClassSimpleName(packet.getClass());
|
||||
//Status packet
|
||||
if (simpleClassName.startsWith("PacketS")) {
|
||||
final PacketStatusReceiveEvent event = new PacketStatusReceiveEvent(channel, new NMSPacket(packet));
|
||||
PacketEvents.get().getEventManager().callEvent(event);
|
||||
packet = event.getNMSPacket().getRawNMSPacket();
|
||||
interceptStatusReceive(event);
|
||||
if (event.isCancelled()) {
|
||||
packet = null;
|
||||
}
|
||||
} else {
|
||||
//Login packet
|
||||
final PacketLoginReceiveEvent event = new PacketLoginReceiveEvent(channel, new NMSPacket(packet));//Cache the channel
|
||||
//f (event.getPacketId() == PacketType.Login.Client.START) {
|
||||
// WrappedPacketLoginInStart startWrapper = new WrappedPacketLoginInStart(event.getNMSPacket());
|
||||
//WrappedGameProfile gameProfile = startWrapper.getGameProfile();
|
||||
//channelMap.put(gameProfile.name, channel);
|
||||
//}
|
||||
PacketEvents.get().getEventManager().callEvent(event);
|
||||
packet = event.getNMSPacket().getRawNMSPacket();
|
||||
interceptLoginReceive(event);
|
||||
if (event.isCancelled()) {
|
||||
packet = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final PacketPlayReceiveEvent event = new PacketPlayReceiveEvent(player, channel, new NMSPacket(packet));
|
||||
PacketEvents.get().getEventManager().callEvent(event);
|
||||
packet = event.getNMSPacket().getRawNMSPacket();
|
||||
interceptRead(event);
|
||||
if (event.isCancelled()) {
|
||||
packet = null;
|
||||
}
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make PacketEvents process an outgoing packet.
|
||||
* The NMS Packet will be null when netty should cancel a packet.
|
||||
*
|
||||
* @param player Packet receiver.
|
||||
* @param channel Packet receiver's netty channel.
|
||||
* @param packet NMS Packet.
|
||||
* @return NMS Packet, null if the event was cancelled.
|
||||
*/
|
||||
public Object write(Player player, Object channel, Object packet) {
|
||||
if (player == null) {
|
||||
String simpleClassName = ClassUtil.getClassSimpleName(packet.getClass());
|
||||
//Status packet
|
||||
if (simpleClassName.startsWith("PacketS")) {
|
||||
final PacketStatusSendEvent event = new PacketStatusSendEvent(channel, new NMSPacket(packet));
|
||||
PacketEvents.get().getEventManager().callEvent(event);
|
||||
packet = event.getNMSPacket().getRawNMSPacket();
|
||||
interceptStatusSend(event);
|
||||
if (event.isCancelled()) {
|
||||
packet = null;
|
||||
}
|
||||
}
|
||||
//Login packet
|
||||
else {
|
||||
final PacketLoginSendEvent event = new PacketLoginSendEvent(channel, new NMSPacket(packet));
|
||||
PacketEvents.get().getEventManager().callEvent(event);
|
||||
packet = event.getNMSPacket().getRawNMSPacket();
|
||||
interceptLoginSend(event);
|
||||
if (event.isCancelled()) {
|
||||
packet = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final PacketPlaySendEvent event = new PacketPlaySendEvent(player, channel, new NMSPacket(packet));
|
||||
PacketEvents.get().getEventManager().callEvent(event);
|
||||
packet = event.getNMSPacket().getRawNMSPacket();
|
||||
interceptWrite(event);
|
||||
if (event.isCancelled()) {
|
||||
packet = null;
|
||||
}
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make PacketEvents process an incoming PLAY packet after minecraft has processed it.
|
||||
* As minecraft has already processed the packet, we cannot cancel the action, nor the event.
|
||||
*
|
||||
* @param player Packet sender.
|
||||
* @param channel Netty channel of the packet sender.
|
||||
* @param packet NMS Packet.
|
||||
*/
|
||||
public void postRead(Player player, Object channel, Object packet) {
|
||||
if (player != null) {
|
||||
//Since player != null check is done, status and login packets won't come passed this point.
|
||||
PostPacketPlayReceiveEvent event = new PostPacketPlayReceiveEvent(player, channel, new NMSPacket(packet));
|
||||
PacketEvents.get().getEventManager().callEvent(event);
|
||||
interceptPostPlayReceive(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make PacketEvents process an outgoing PLAY packet after minecraft has already sent the packet.
|
||||
* This doesn't necessarily mean the client already received the packet,
|
||||
* but the server has sent it for sure by this time.
|
||||
* As minecraft has already processed the packet, we cannot cancel the action, nor the event.
|
||||
*
|
||||
* @param player Packet receiver.
|
||||
* @param channel Netty channel of the packet receiver.
|
||||
* @param packet NMS Packet.
|
||||
*/
|
||||
public void postWrite(Player player, Object channel, Object packet) {
|
||||
if (player != null) {
|
||||
//Since player != null check is done, status and login packets won't come passed this point.
|
||||
PostPacketPlaySendEvent event = new PostPacketPlaySendEvent(player, channel, new NMSPacket(packet));
|
||||
PacketEvents.get().getEventManager().callEvent(event);
|
||||
interceptPostPlaySend(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal processing of an incoming PLAY packet.
|
||||
*
|
||||
* @param event PLAY server-bound packet event.
|
||||
*/
|
||||
private void interceptRead(PacketPlayReceiveEvent event) {
|
||||
if (event.getPacketId() == PacketType.Play.Client.KEEP_ALIVE) {
|
||||
UUID uuid = event.getPlayer().getUniqueId();
|
||||
long timestamp = keepAliveMap.getOrDefault(uuid, event.getTimestamp());
|
||||
long currentTime = event.getTimestamp();
|
||||
long ping = currentTime - timestamp;
|
||||
long smoothedPing = (PacketEvents.get().getPlayerUtils().getSmoothedPing(event.getPlayer().getUniqueId()) * 3L + ping) / 4;
|
||||
PacketEvents.get().getPlayerUtils().playerPingMap.put(uuid, (int) ping);
|
||||
PacketEvents.get().getPlayerUtils().playerSmoothedPingMap.put(uuid, (int) smoothedPing);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal processing of an outgoing PLAY packet.
|
||||
*
|
||||
* @param event PLAY client-bound packet event.
|
||||
*/
|
||||
private void interceptWrite(PacketPlaySendEvent event) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal processing of an incoming LOGIN packet.
|
||||
*
|
||||
* @param event LOGIN server-bound packet event.
|
||||
*/
|
||||
private void interceptLoginReceive(PacketLoginReceiveEvent event) {
|
||||
if (event.getPacketId() == PacketType.Login.Client.HANDSHAKE) {
|
||||
WrappedPacketLoginInHandshake handshake = new WrappedPacketLoginInHandshake(event.getNMSPacket());
|
||||
int protocolVersion = handshake.getProtocolVersion();
|
||||
ClientVersion version = ClientVersion.getClientVersion(protocolVersion);
|
||||
PacketEvents.get().getPlayerUtils().tempClientVersionMap.put(event.getSocketAddress(), version);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal processing of an outgoing LOGIN packet.
|
||||
*
|
||||
* @param event client-bound LOGIN packet event.
|
||||
*/
|
||||
private void interceptLoginSend(PacketLoginSendEvent event) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal processing of an incoming STATUS packet.
|
||||
*
|
||||
* @param event server-bound STATUS packet event.
|
||||
*/
|
||||
private void interceptStatusReceive(PacketStatusReceiveEvent event) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal processing of an outgoing STATUS packet.
|
||||
*
|
||||
* @param event client-bound STATUS packet event.
|
||||
*/
|
||||
private void interceptStatusSend(PacketStatusSendEvent event) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal processing of a packet that has already been processed by minecraft.
|
||||
*
|
||||
* @param event post server-bound play packet event.
|
||||
*/
|
||||
private void interceptPostPlayReceive(PostPacketPlayReceiveEvent event) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal processing of a packet that has already been sent to a client.
|
||||
* Doesn't necessarily mean the client has received it yet.
|
||||
*
|
||||
* @param event post client-bound play packet event.
|
||||
*/
|
||||
private void interceptPostPlaySend(PostPacketPlaySendEvent event) {
|
||||
if (event.getPacketId() == PacketType.Play.Server.KEEP_ALIVE) {
|
||||
if (event.getPlayer() != null) {
|
||||
keepAliveMap.put(event.getPlayer().getUniqueId(), event.getTimestamp());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If you are using the EarlyInjector,
|
||||
* calling this close method will unregister the channel handlers it registered when the plugin enabled.
|
||||
* PacketEvents already unregisters them in the {@link PacketEvents#terminate()} method.
|
||||
*/
|
||||
public void cleanup() {
|
||||
injector.cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
* If you are using the EarlyInjector,
|
||||
* calling this close method will unregister the channel handlers it registered when the plugin enabled
|
||||
* ASYNCHRONOUSLY.
|
||||
* PacketEvents already unregisters them in the {@link PacketEvents#terminate()} method.
|
||||
*/
|
||||
public void cleanupAsync() {
|
||||
injector.cleanupAsync();
|
||||
}
|
||||
}
|
||||
@@ -1,33 +1,17 @@
|
||||
package io.github.retrooper.packetevents.injector;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public interface ChannelInjector {
|
||||
default void prepare() {
|
||||
void inject();
|
||||
|
||||
}
|
||||
void eject();
|
||||
|
||||
default void cleanup() {
|
||||
void injectPlayer(Player player);
|
||||
|
||||
}
|
||||
void ejectPlayer(Player player);
|
||||
|
||||
default void cleanupAsync() {
|
||||
PacketEvents.get().injectAndEjectExecutorService.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
cleanup();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void injectPlayerSync(Player player);
|
||||
|
||||
void ejectPlayerSync(Player player);
|
||||
|
||||
void injectPlayerAsync(Player player);
|
||||
|
||||
void ejectPlayerAsync(Player player);
|
||||
boolean hasInjected(Player player);
|
||||
|
||||
void sendPacket(Object channel, Object rawNMSPacket);
|
||||
}
|
||||
+5
-6
@@ -22,13 +22,12 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.retrooper.packetevents.utils.versionlookup.v_1_7_10;
|
||||
package io.github.retrooper.packetevents.injector;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class ProtocolVersionAccessor_v_1_7 {
|
||||
public static int getProtocolVersion(Player player) {
|
||||
net.minecraft.server.v1_7_R4.EntityPlayer entityPlayer = ((org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer) player).getHandle();
|
||||
return entityPlayer.playerConnection.networkManager.getVersion();
|
||||
}
|
||||
public interface EarlyInjector extends ChannelInjector {
|
||||
void updatePlayerObject(Player player, Object channel);
|
||||
|
||||
boolean isBound();
|
||||
}
|
||||
+46
-34
@@ -1,65 +1,77 @@
|
||||
package io.github.retrooper.packetevents.injector;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.injector.earlyinjector.EarlyChannelInjector7;
|
||||
import io.github.retrooper.packetevents.injector.earlyinjector.EarlyChannelInjector8;
|
||||
import io.github.retrooper.packetevents.injector.lateinjector.LateChannelInjector7;
|
||||
import io.github.retrooper.packetevents.injector.lateinjector.LateChannelInjector8;
|
||||
import io.github.retrooper.packetevents.event.impl.PlayerEjectEvent;
|
||||
import io.github.retrooper.packetevents.event.impl.PlayerInjectEvent;
|
||||
import io.github.retrooper.packetevents.injector.legacy.early.EarlyChannelInjectorLegacy;
|
||||
import io.github.retrooper.packetevents.injector.modern.early.EarlyChannelInjectorModern;
|
||||
import io.github.retrooper.packetevents.injector.legacy.late.LateChannelInjectorLegacy;
|
||||
import io.github.retrooper.packetevents.injector.modern.late.LateChannelInjectorModern;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class GlobalChannelInjector implements ChannelInjector {
|
||||
private final ChannelInjector injector;
|
||||
private ChannelInjector injector;
|
||||
|
||||
public GlobalChannelInjector() {
|
||||
|
||||
}
|
||||
|
||||
public void load() {
|
||||
boolean legacy = NMSUtils.legacyNettyImportMode;
|
||||
//Early injector
|
||||
if (PacketEvents.get().getSettings().shouldInjectEarly()) {
|
||||
injector = legacy ? new EarlyChannelInjector7() : new EarlyChannelInjector8();
|
||||
}
|
||||
//Late injector
|
||||
else {
|
||||
injector = legacy ? new LateChannelInjector7() : new LateChannelInjector8();
|
||||
if (!PacketEvents.get().getSettings().shouldUseCompatibilityInjector()) {
|
||||
injector = legacy ? new EarlyChannelInjectorLegacy() : new EarlyChannelInjectorModern();
|
||||
} else {
|
||||
injector = legacy ? new LateChannelInjectorLegacy() : new LateChannelInjectorModern();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepare() {
|
||||
injector.prepare();
|
||||
public void inject() {
|
||||
try {
|
||||
//Try inject...
|
||||
injector.inject();
|
||||
} catch (Exception ex) {
|
||||
//Failed to inject! Let us revert to the compatibility injector and re-inject.
|
||||
if (injector instanceof EarlyInjector) {
|
||||
PacketEvents.get().getSettings().compatInjector(true);
|
||||
load();
|
||||
injector.inject();
|
||||
PacketEvents.get().getPlugin().getLogger().warning("PacketEvents failed to inject with the Early Injector. Reverting to the Compatibility/Late Injector... This is just a warning, but please report this!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
injector.cleanup();
|
||||
public void eject() {
|
||||
injector.eject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanupAsync() {
|
||||
injector.cleanupAsync();
|
||||
public void injectPlayer(Player player) {
|
||||
PlayerInjectEvent injectEvent = new PlayerInjectEvent(player);
|
||||
PacketEvents.get().callEvent(injectEvent);
|
||||
if (!injectEvent.isCancelled()) {
|
||||
injector.injectPlayer(player);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectPlayerSync(Player player) {
|
||||
injector.injectPlayerSync(player);
|
||||
public void ejectPlayer(Player player) {
|
||||
PlayerEjectEvent ejectEvent = new PlayerEjectEvent(player);
|
||||
PacketEvents.get().callEvent(ejectEvent);
|
||||
if (!ejectEvent.isCancelled()) {
|
||||
injector.ejectPlayer(player);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ejectPlayerSync(Player player) {
|
||||
injector.ejectPlayerSync(player);
|
||||
public boolean hasInjected(Player player) {
|
||||
return injector.hasInjected(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectPlayerAsync(Player player) {
|
||||
injector.injectPlayerAsync(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ejectPlayerAsync(Player player) {
|
||||
injector.ejectPlayerAsync(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPacket(Object channel, Object rawNMSPacket) {
|
||||
injector.sendPacket(channel, rawNMSPacket);
|
||||
public void sendPacket(Object ch, Object rawNMSPacket) {
|
||||
injector.sendPacket(ch, rawNMSPacket);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package io.github.retrooper.packetevents.injector;
|
||||
|
||||
public interface LateInjector extends ChannelInjector {
|
||||
|
||||
}
|
||||
-337
@@ -1,337 +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.injector.earlyinjector;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
import io.github.retrooper.packetevents.utils.server.ServerVersion;
|
||||
import net.minecraft.util.io.netty.channel.*;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* 1.7.10 Spigot Early channel injector.
|
||||
* This is an early injector for 1.7.10 spigot servers.
|
||||
* The netty import on spigot changed since 1.8.
|
||||
* So we needed to make a new class using the older import location to support 1.7.10.
|
||||
* This is why we also commonly use a java {@link Object} class when it comes to netty channels
|
||||
* in some classes to maintain support for both netty imports.
|
||||
*
|
||||
* @author retrooper
|
||||
* @since 1.8
|
||||
*/
|
||||
public class EarlyChannelInjector7 implements EarlyInjector {
|
||||
/**
|
||||
* Netty minecraft server channels.
|
||||
*/
|
||||
private final List<Channel> serverChannels = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* First channel initializer.
|
||||
* Used to inject incoming channels.
|
||||
*/
|
||||
private ChannelInitializer<Channel> firstChannelInitializer;
|
||||
|
||||
/**
|
||||
* Second channel initializer.
|
||||
*/
|
||||
private ChannelInitializer<Channel> secondChannelInitializer;
|
||||
|
||||
/**
|
||||
* Channel handler.
|
||||
*/
|
||||
private ChannelInboundHandlerAdapter channelHandler;
|
||||
|
||||
/**
|
||||
* Network managers.
|
||||
*/
|
||||
private List<Object> networkMarkers;
|
||||
|
||||
|
||||
/**
|
||||
* Access minecraft's network managers to synchronize against as they interfere with our channel injection.
|
||||
* Initiate the channel initializers and the channel handler.
|
||||
* Access minecraft's server channels and add our own.
|
||||
*/
|
||||
@Override
|
||||
public void prepare() {
|
||||
networkMarkers = NMSUtils.getNetworkMarkers();
|
||||
firstChannelInitializer = new ChannelInitializer<Channel>() {
|
||||
@Override
|
||||
protected void initChannel(final Channel channel) {
|
||||
if (networkMarkers != null) {
|
||||
synchronized (networkMarkers) {
|
||||
channel.eventLoop().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (PacketEvents.get().getServerUtils().getVersion().isNewerThan(ServerVersion.v_1_11_2)) {
|
||||
channel.eventLoop().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
injectChannel(channel);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
injectChannel(channel);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
channel.eventLoop().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (PacketEvents.get().getServerUtils().getVersion().isNewerThan(ServerVersion.v_1_11_2)) {
|
||||
channel.eventLoop().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
injectChannel(channel);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
injectChannel(channel);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
secondChannelInitializer = new ChannelInitializer<Channel>() {
|
||||
@Override
|
||||
protected void initChannel(Channel channel) {
|
||||
channel.pipeline().addLast(firstChannelInitializer);
|
||||
}
|
||||
};
|
||||
|
||||
channelHandler = new ChannelInboundHandlerAdapter() {
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) {
|
||||
Channel channel = (Channel) msg;
|
||||
channel.pipeline().addFirst(secondChannelInitializer);
|
||||
ctx.fireChannelRead(msg);
|
||||
}
|
||||
};
|
||||
|
||||
//Wrapper for the minecraft server connection.
|
||||
WrappedPacket serverConnectionWrapper = new WrappedPacket(new NMSPacket(NMSUtils.getMinecraftServerConnection()));
|
||||
boolean searching = true;
|
||||
for (int i = 0; searching; i++) {
|
||||
try {
|
||||
//Get the list.
|
||||
List<Object> serverChannelList = (List<Object>) serverConnectionWrapper.readObject(i, List.class);
|
||||
for (Object serverChannel : serverChannelList) {
|
||||
//Is this the server channel list?
|
||||
if (serverChannel instanceof ChannelFuture) {
|
||||
//Yes it is...
|
||||
Channel channel = ((ChannelFuture) serverChannel).channel();
|
||||
serverChannels.add(channel);
|
||||
//Add our channel handler to all the server channel pipelines.
|
||||
channel.pipeline().addFirst(channelHandler);
|
||||
searching = false;
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove our channel handler from all server channel pipelines from the current thread.
|
||||
*/
|
||||
@Override
|
||||
public void cleanup() {
|
||||
for (Channel channel : serverChannels) {
|
||||
try {
|
||||
channel.pipeline().remove(channelHandler);
|
||||
} catch (NoSuchElementException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject a netty channel to listen to packets.
|
||||
* If already injected, get the channel interceptor.
|
||||
*
|
||||
* @param ch Netty channel.
|
||||
* @return {@link PlayerChannelInterceptor}
|
||||
*/
|
||||
@Override
|
||||
public PlayerChannelInterceptor injectChannel(Object ch) {
|
||||
Channel channel = (Channel) ch;
|
||||
String handlerName = PacketEvents.handlerName;
|
||||
PlayerChannelInterceptor interceptor = (PlayerChannelInterceptor) channel.pipeline().get(handlerName);
|
||||
if (interceptor == null) {
|
||||
interceptor = new PlayerChannelInterceptor();
|
||||
if (channel.pipeline().get("packet_handler") != null) {
|
||||
channel.pipeline().addBefore("packet_handler", handlerName, interceptor);
|
||||
} else {
|
||||
throw new IllegalStateException("Failed to inject an incoming channel due to \"packet_handler\" not being added to the pipeline! Let them rejoin!");
|
||||
}
|
||||
}
|
||||
return interceptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Eject a netty channel.
|
||||
*
|
||||
* @param ch Netty channel.
|
||||
*/
|
||||
@Override
|
||||
public void ejectChannel(Object ch) {
|
||||
Channel channel = (Channel) ch;
|
||||
String handlerName = PacketEvents.handlerName;
|
||||
if (channel.pipeline().get(handlerName) != null) {
|
||||
channel.pipeline().remove(handlerName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject a player on the current thread.
|
||||
*
|
||||
* @param player Target player.
|
||||
*/
|
||||
@Override
|
||||
public void injectPlayerSync(Player player) {
|
||||
Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
|
||||
injectChannel(channel).player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Eject a player on the current thread.
|
||||
*
|
||||
* @param player Target player.
|
||||
*/
|
||||
@Override
|
||||
public void ejectPlayerSync(Player player) {
|
||||
Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
|
||||
ejectChannel(channel);
|
||||
PacketEvents.get().getPlayerUtils().clientVersionsMap.remove(player.getAddress());
|
||||
PacketEvents.get().getPlayerUtils().tempClientVersionMap.remove(player.getAddress());
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject a player on our custom inject and eject (fixed) thread pool (=asynchronously).
|
||||
*
|
||||
* @param player Target player.
|
||||
*/
|
||||
@Override
|
||||
public void injectPlayerAsync(Player player) {
|
||||
PacketEvents.get().injectAndEjectExecutorService.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
|
||||
injectChannel(channel).player = player;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Eject a player on our custom inject and eject (fixed) thread pool (=asynchronously).
|
||||
*
|
||||
* @param player Target player.
|
||||
*/
|
||||
@Override
|
||||
public void ejectPlayerAsync(Player player) {
|
||||
PacketEvents.get().injectAndEjectExecutorService.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
|
||||
ejectChannel(channel);
|
||||
PacketEvents.get().packetHandlerInternal.keepAliveMap.remove(player.getUniqueId());
|
||||
PacketEvents.get().packetHandlerInternal.channelMap.remove(player.getName());
|
||||
PacketEvents.get().getPlayerUtils().clientVersionsMap.remove(player.getAddress());
|
||||
PacketEvents.get().getPlayerUtils().tempClientVersionMap.remove(player.getAddress());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a raw NMS packet to a netty channel.
|
||||
*
|
||||
* @param ch Netty channel.
|
||||
* @param packet Raw NMS Packet.
|
||||
*/
|
||||
@Override
|
||||
public void sendPacket(Object ch, Object packet) {
|
||||
Channel channel = (Channel) ch;
|
||||
channel.writeAndFlush(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Player channel interceptor.
|
||||
*
|
||||
* @author retrooper
|
||||
* @since 1.8
|
||||
*/
|
||||
public static class PlayerChannelInterceptor extends ChannelDuplexHandler {
|
||||
/**
|
||||
* Associated player.
|
||||
* This is null until you inject the player.
|
||||
* (We inject the PLAYER by PlayerLoginEvent or PlayerJoinEvent depending on your settings)
|
||||
*/
|
||||
public volatile Player player;
|
||||
|
||||
/**
|
||||
* Incoming packet interception.
|
||||
*
|
||||
* @param ctx Netty channel handler context.
|
||||
* @param packet Raw NMS Packet.
|
||||
* @throws Exception Possible exception.
|
||||
*/
|
||||
@Override
|
||||
public void channelRead(final ChannelHandlerContext ctx, Object packet) throws Exception {
|
||||
packet = PacketEvents.get().packetHandlerInternal.read(player, ctx.channel(), packet);
|
||||
if (packet != null) {
|
||||
super.channelRead(ctx, packet);
|
||||
PacketEvents.get().packetHandlerInternal.postRead(player, ctx.channel(), packet);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Outgoing packet interception.
|
||||
*
|
||||
* @param ctx Netty channel handler context.
|
||||
* @param packet Raw NMS Packet
|
||||
* @param promise Netty channel promise.
|
||||
* @throws Exception Possible exception.
|
||||
*/
|
||||
@Override
|
||||
public void write(final ChannelHandlerContext ctx, Object packet, final ChannelPromise promise) throws Exception {
|
||||
packet = PacketEvents.get().packetHandlerInternal.write(player, ctx.channel(), packet);
|
||||
if (packet != null) {
|
||||
super.write(ctx, packet, promise);
|
||||
PacketEvents.get().packetHandlerInternal.postWrite(player, ctx.channel(), packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-332
@@ -1,332 +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.injector.earlyinjector;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
import io.github.retrooper.packetevents.utils.server.ServerVersion;
|
||||
import io.netty.channel.*;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* 1.8 (and above) Spigot Early channel injector.
|
||||
* This is an early injector for 1.8 (and above) spigot servers.
|
||||
* The netty import on spigot changed since 1.8.
|
||||
* So we needed to make separate classes for the 1.7.10 and the 1.8+ injector.
|
||||
* This is why we also commonly use a java {@link Object} class when it comes to netty channels
|
||||
* in some classes to maintain support for both netty imports.
|
||||
*
|
||||
* @author retrooper
|
||||
* @since 1.8
|
||||
*/
|
||||
public class EarlyChannelInjector8 implements EarlyInjector {
|
||||
/**
|
||||
* Netty minecraft server channels.
|
||||
*/
|
||||
private final List<Channel> serverChannels = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* First channel initializer.
|
||||
* Used to inject incoming channels.
|
||||
*/
|
||||
private ChannelInitializer<Channel> firstChannelInitializer;
|
||||
|
||||
/**
|
||||
* Second channel initializer.
|
||||
*/
|
||||
private ChannelInitializer<Channel> secondChannelInitializer;
|
||||
|
||||
/**
|
||||
* Channel handler.
|
||||
*/
|
||||
private ChannelInboundHandlerAdapter channelHandler;
|
||||
|
||||
/**
|
||||
* Network managers.
|
||||
*/
|
||||
private List<Object> networkMarkers;
|
||||
|
||||
/**
|
||||
* Access minecraft's network managers to synchronize against as they interfere with our channel injection.
|
||||
* Initiate the channel initializers and the channel handler.
|
||||
* Access minecraft's server channels and add our own.
|
||||
*/
|
||||
@Override
|
||||
public void prepare() {
|
||||
networkMarkers = NMSUtils.getNetworkMarkers();
|
||||
firstChannelInitializer = new ChannelInitializer<Channel>() {
|
||||
@Override
|
||||
protected void initChannel(final Channel channel) {
|
||||
if (networkMarkers != null) {
|
||||
synchronized (networkMarkers) {
|
||||
if (PacketEvents.get().getServerUtils().getVersion().isNewerThan(ServerVersion.v_1_11_2)) {
|
||||
channel.eventLoop().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
injectChannel(channel);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
injectChannel(channel);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.eventLoop().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (PacketEvents.get().getServerUtils().getVersion().isNewerThan(ServerVersion.v_1_11_2)) {
|
||||
channel.eventLoop().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
injectChannel(channel);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
injectChannel(channel);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
secondChannelInitializer = new ChannelInitializer<Channel>() {
|
||||
@Override
|
||||
protected void initChannel(Channel channel) {
|
||||
channel.pipeline().addLast(firstChannelInitializer);
|
||||
}
|
||||
};
|
||||
|
||||
channelHandler = new ChannelInboundHandlerAdapter() {
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) {
|
||||
Channel channel = (Channel) msg;
|
||||
channel.pipeline().addFirst(secondChannelInitializer);
|
||||
ctx.fireChannelRead(msg);
|
||||
}
|
||||
};
|
||||
//Wrapper for the minecraft server connection.
|
||||
WrappedPacket serverConnectionWrapper = new WrappedPacket(new NMSPacket(NMSUtils.getMinecraftServerConnection()));
|
||||
boolean searching = true;
|
||||
for (int i = 0; searching; i++) {
|
||||
try {
|
||||
//Get the list.
|
||||
List<Object> serverChannelList = (List<Object>) serverConnectionWrapper.readObject(i, List.class);
|
||||
for (Object serverChannel : serverChannelList) {
|
||||
//Is this the server channel list?
|
||||
if (serverChannel instanceof ChannelFuture) {
|
||||
//Yes it is...
|
||||
Channel channel = ((ChannelFuture) serverChannel).channel();
|
||||
serverChannels.add(channel);
|
||||
//Add our channel handler to all server channel pipelines.
|
||||
channel.pipeline().addFirst(channelHandler);
|
||||
searching = false;
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove our channel handler from all server channel pipelines from the current thread.
|
||||
*/
|
||||
@Override
|
||||
public void cleanup() {
|
||||
for (Channel channel : serverChannels) {
|
||||
try {
|
||||
channel.pipeline().remove(channelHandler);
|
||||
} catch (NoSuchElementException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject a netty channel to listen to packets.
|
||||
* If already injected, get the channel interceptor.
|
||||
*
|
||||
* @param ch Netty channel.
|
||||
* @return {@link PlayerChannelInterceptor}
|
||||
*/
|
||||
@Override
|
||||
public PlayerChannelInterceptor injectChannel(Object ch) {
|
||||
Channel channel = (Channel) ch;
|
||||
final String handlerName = PacketEvents.handlerName;
|
||||
try {
|
||||
PlayerChannelInterceptor interceptor = (PlayerChannelInterceptor) channel.pipeline().get(handlerName);
|
||||
if (interceptor == null) {
|
||||
interceptor = new PlayerChannelInterceptor();
|
||||
if (channel.pipeline().get("packet_handler") != null) {
|
||||
channel.pipeline().addBefore("packet_handler", handlerName, interceptor);
|
||||
}
|
||||
}
|
||||
return interceptor;
|
||||
} catch (IllegalArgumentException ex) {
|
||||
//Let us try again
|
||||
return (PlayerChannelInterceptor) channel.pipeline().get(handlerName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Eject a netty channel.
|
||||
*
|
||||
* @param ch Netty channel.
|
||||
*/
|
||||
@Override
|
||||
public void ejectChannel(Object ch) {
|
||||
Channel channel = (Channel) ch;
|
||||
String handlerName = PacketEvents.handlerName;
|
||||
if (channel.pipeline().get(handlerName) != null) {
|
||||
channel.pipeline().remove(handlerName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject a player on the current thread.
|
||||
*
|
||||
* @param player Target player.
|
||||
*/
|
||||
@Override
|
||||
public void injectPlayerSync(Player player) {
|
||||
Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
|
||||
injectChannel(channel).player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Eject a player on the current thread.
|
||||
*
|
||||
* @param player Target player.
|
||||
*/
|
||||
@Override
|
||||
public void ejectPlayerSync(Player player) {
|
||||
Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
|
||||
ejectChannel(channel);
|
||||
PacketEvents.get().getPlayerUtils().clientVersionsMap.remove(player.getAddress());
|
||||
PacketEvents.get().getPlayerUtils().tempClientVersionMap.remove(player.getAddress());
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject a player on our custom inject and eject (fixed) thread pool (=asynchronously).
|
||||
*
|
||||
* @param player Target player.
|
||||
*/
|
||||
@Override
|
||||
public void injectPlayerAsync(Player player) {
|
||||
PacketEvents.get().injectAndEjectExecutorService.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
|
||||
injectChannel(channel).player = player;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Eject a player on our custom inject and eject (fixed) thread pool (=asynchronously).
|
||||
*
|
||||
* @param player Target player.
|
||||
*/
|
||||
@Override
|
||||
public void ejectPlayerAsync(Player player) {
|
||||
PacketEvents.get().injectAndEjectExecutorService.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
|
||||
ejectChannel(channel);
|
||||
PacketEvents.get().packetHandlerInternal.keepAliveMap.remove(player.getUniqueId());
|
||||
PacketEvents.get().packetHandlerInternal.channelMap.remove(player.getName());
|
||||
PacketEvents.get().getPlayerUtils().clientVersionsMap.remove(player.getAddress());
|
||||
PacketEvents.get().getPlayerUtils().tempClientVersionMap.remove(player.getAddress());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a raw NMS packet to a netty channel.
|
||||
*
|
||||
* @param ch Netty channel.
|
||||
* @param packet Raw NMS Packet.
|
||||
*/
|
||||
@Override
|
||||
public void sendPacket(Object ch, Object packet) {
|
||||
Channel channel = (Channel) ch;
|
||||
channel.writeAndFlush(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Player channel interceptor.
|
||||
*
|
||||
* @author retrooper
|
||||
* @since 1.8
|
||||
*/
|
||||
public static class PlayerChannelInterceptor extends ChannelDuplexHandler {
|
||||
/**
|
||||
* Associated player.
|
||||
* This is null until you inject the player.
|
||||
* (We inject the PLAYER by PlayerLoginEvent or PlayerJoinEvent depending on your settings)
|
||||
*/
|
||||
public volatile Player player;
|
||||
|
||||
/**
|
||||
* Incoming packet interception.
|
||||
*
|
||||
* @param ctx Netty channel handler context.
|
||||
* @param packet Raw NMS Packet.
|
||||
* @throws Exception Possible exception.
|
||||
*/
|
||||
@Override
|
||||
public void channelRead(final ChannelHandlerContext ctx, Object packet) throws Exception {
|
||||
packet = PacketEvents.get().packetHandlerInternal.read(player, ctx.channel(), packet);
|
||||
if (packet != null) {
|
||||
super.channelRead(ctx, packet);
|
||||
PacketEvents.get().packetHandlerInternal.postRead(player, ctx.channel(), packet);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Outgoing packet interception.
|
||||
*
|
||||
* @param ctx Netty channel handler context.
|
||||
* @param packet Raw NMS Packet
|
||||
* @param promise Netty channel promise.
|
||||
* @throws Exception Possible exception.
|
||||
*/
|
||||
@Override
|
||||
public void write(final ChannelHandlerContext ctx, Object packet, final ChannelPromise promise) throws Exception {
|
||||
packet = PacketEvents.get().packetHandlerInternal.write(player, ctx.channel(), packet);
|
||||
if (packet != null) {
|
||||
super.write(ctx, packet, promise);
|
||||
PacketEvents.get().packetHandlerInternal.postWrite(player, ctx.channel(), packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
package io.github.retrooper.packetevents.injector.earlyinjector;
|
||||
|
||||
import io.github.retrooper.packetevents.injector.ChannelInjector;
|
||||
|
||||
public interface EarlyInjector extends ChannelInjector {
|
||||
void prepare();
|
||||
|
||||
void cleanup();
|
||||
|
||||
Object injectChannel(Object channel);
|
||||
|
||||
void ejectChannel(Object channel);
|
||||
}
|
||||
-102
@@ -1,102 +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.injector.lateinjector;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import net.minecraft.util.io.netty.channel.Channel;
|
||||
import net.minecraft.util.io.netty.channel.ChannelDuplexHandler;
|
||||
import net.minecraft.util.io.netty.channel.ChannelHandlerContext;
|
||||
import net.minecraft.util.io.netty.channel.ChannelPromise;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class LateChannelInjector7 implements LateInjector {
|
||||
@Override
|
||||
public void injectPlayerSync(Player player) {
|
||||
final ChannelDuplexHandler channelDuplexHandler = new ChannelDuplexHandler() {
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object packet) throws Exception {
|
||||
packet = PacketEvents.get().packetHandlerInternal.read(player, ctx.channel(), packet);
|
||||
if (packet != null) {
|
||||
super.channelRead(ctx, packet);
|
||||
PacketEvents.get().packetHandlerInternal.postRead(player, ctx.channel(), packet);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception {
|
||||
packet = PacketEvents.get().packetHandlerInternal.write(player, ctx.channel(), packet);
|
||||
if (packet != null) {
|
||||
super.write(ctx, packet, promise);
|
||||
PacketEvents.get().packetHandlerInternal.postWrite(player, ctx.channel(), packet);
|
||||
}
|
||||
}
|
||||
};
|
||||
final Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
|
||||
channel.pipeline().addBefore("packet_handler", PacketEvents.handlerName, channelDuplexHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ejectPlayerSync(Player player) {
|
||||
final Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
|
||||
if (channel.pipeline().get(PacketEvents.handlerName) != null) {
|
||||
channel.pipeline().remove(PacketEvents.handlerName);
|
||||
}
|
||||
PacketEvents.get().getPlayerUtils().clientVersionsMap.remove(player.getAddress());
|
||||
PacketEvents.get().getPlayerUtils().tempClientVersionMap.remove(player.getAddress());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectPlayerAsync(Player player) {
|
||||
PacketEvents.get().injectAndEjectExecutorService.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
injectPlayerSync(player);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ejectPlayerAsync(Player player) {
|
||||
PacketEvents.get().injectAndEjectExecutorService.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
|
||||
if (channel.pipeline().get(PacketEvents.handlerName) != null) {
|
||||
channel.pipeline().remove(PacketEvents.handlerName);
|
||||
}
|
||||
PacketEvents.get().packetHandlerInternal.keepAliveMap.remove(player.getUniqueId());
|
||||
PacketEvents.get().packetHandlerInternal.channelMap.remove(player.getName());
|
||||
PacketEvents.get().getPlayerUtils().clientVersionsMap.remove(player.getAddress());
|
||||
PacketEvents.get().getPlayerUtils().tempClientVersionMap.remove(player.getAddress());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPacket(Object rawChannel, Object packet) {
|
||||
Channel channel = (Channel) rawChannel;
|
||||
channel.pipeline().writeAndFlush(packet);
|
||||
}
|
||||
}
|
||||
-112
@@ -1,112 +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.injector.lateinjector;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelDuplexHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
public class LateChannelInjector8 implements LateInjector {
|
||||
@Override
|
||||
public void injectPlayerSync(Player player) {
|
||||
final ChannelDuplexHandler channelDuplexHandler = new ChannelDuplexHandler() {
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object packet) throws Exception {
|
||||
packet = PacketEvents.get().packetHandlerInternal.read(player, ctx.channel(), packet);
|
||||
if (packet != null) {
|
||||
super.channelRead(ctx, packet);
|
||||
PacketEvents.get().packetHandlerInternal.postRead(player, ctx.channel(), packet);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception {
|
||||
packet = PacketEvents.get().packetHandlerInternal.write(player, ctx.channel(), packet);
|
||||
if (packet != null) {
|
||||
super.write(ctx, packet, promise);
|
||||
PacketEvents.get().packetHandlerInternal.postWrite(player, ctx.channel(), packet);
|
||||
}
|
||||
}
|
||||
};
|
||||
final Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
|
||||
channel.pipeline().addBefore("packet_handler", PacketEvents.handlerName, channelDuplexHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ejectPlayerSync(Player player) {
|
||||
final Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
|
||||
if (channel.pipeline().get(PacketEvents.handlerName) != null) {
|
||||
try {
|
||||
channel.pipeline().remove(PacketEvents.handlerName);
|
||||
} catch (NoSuchElementException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
PacketEvents.get().getPlayerUtils().clientVersionsMap.remove(player.getAddress());
|
||||
PacketEvents.get().getPlayerUtils().tempClientVersionMap.remove(player.getAddress());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectPlayerAsync(Player player) {
|
||||
PacketEvents.get().injectAndEjectExecutorService.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
injectPlayerSync(player);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ejectPlayerAsync(Player player) {
|
||||
PacketEvents.get().injectAndEjectExecutorService.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
|
||||
if (channel.pipeline().get(PacketEvents.handlerName) != null) {
|
||||
try {
|
||||
channel.pipeline().remove(PacketEvents.handlerName);
|
||||
} catch (NoSuchElementException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
PacketEvents.get().packetHandlerInternal.keepAliveMap.remove(player.getUniqueId());
|
||||
PacketEvents.get().packetHandlerInternal.channelMap.remove(player.getName());
|
||||
PacketEvents.get().getPlayerUtils().clientVersionsMap.remove(player.getAddress());
|
||||
PacketEvents.get().getPlayerUtils().tempClientVersionMap.remove(player.getAddress());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPacket(Object rawChannel, Object packet) {
|
||||
Channel channel = (Channel) rawChannel;
|
||||
channel.pipeline().writeAndFlush(packet);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package io.github.retrooper.packetevents.injector.lateinjector;
|
||||
|
||||
import io.github.retrooper.packetevents.injector.ChannelInjector;
|
||||
|
||||
public interface LateInjector extends ChannelInjector {
|
||||
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.injector.legacy;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import net.minecraft.util.io.netty.channel.ChannelDuplexHandler;
|
||||
import net.minecraft.util.io.netty.channel.ChannelHandlerContext;
|
||||
import net.minecraft.util.io.netty.channel.ChannelPromise;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class PlayerChannelHandlerLegacy extends ChannelDuplexHandler {
|
||||
/**
|
||||
* Associated player.
|
||||
* This is null until the player is injected.
|
||||
*/
|
||||
public volatile Player player;
|
||||
|
||||
@Override
|
||||
public void channelRead(final ChannelHandlerContext ctx, Object packet) throws Exception {
|
||||
try {
|
||||
packet = PacketEvents.get().packetProcessorInternal.read(player, ctx.channel(), packet);
|
||||
if (packet != null) {
|
||||
super.channelRead(ctx, packet);
|
||||
PacketEvents.get().packetProcessorInternal.postRead(player, ctx.channel(), packet);
|
||||
}
|
||||
}
|
||||
catch (Throwable t) {
|
||||
PacketEvents.get().getPlugin().getLogger().log(Level.SEVERE, "Unable to handle an incoming packet ", t.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final ChannelHandlerContext ctx, Object packet, final ChannelPromise promise) throws Exception {
|
||||
try {
|
||||
packet = PacketEvents.get().packetProcessorInternal.write(player, ctx.channel(), packet);
|
||||
if (packet != null) {
|
||||
super.write(ctx, packet, promise);
|
||||
PacketEvents.get().packetProcessorInternal.postWrite(player, ctx.channel(), packet);
|
||||
}
|
||||
}
|
||||
catch (Throwable t) {
|
||||
PacketEvents.get().getPlugin().getLogger().log(Level.SEVERE, "Unable to handle an outgoing packet ", t.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
+317
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* 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.injector.legacy.early;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.injector.EarlyInjector;
|
||||
import io.github.retrooper.packetevents.injector.legacy.PlayerChannelHandlerLegacy;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.list.ListWrapper;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
import net.minecraft.util.io.netty.channel.Channel;
|
||||
import net.minecraft.util.io.netty.channel.ChannelFuture;
|
||||
import net.minecraft.util.io.netty.channel.ChannelHandler;
|
||||
import net.minecraft.util.io.netty.channel.ChannelInitializer;
|
||||
import net.minecraft.util.io.netty.channel.socket.SocketChannel;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Early channel injector for 1.7.10 server versions.
|
||||
* Thank you ViaVersion.
|
||||
* https://github.com/ViaVersion/ViaVersion/tree/master/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaInjector.java
|
||||
*
|
||||
* @author retrooper, Thomazz, ViaVersion
|
||||
* @since 1.8
|
||||
*/
|
||||
public class EarlyChannelInjectorLegacy implements EarlyInjector {
|
||||
private final List<ChannelFuture> injectedFutures = new ArrayList<>();
|
||||
private final List<Map<Field, Object>> injectedLists = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void inject() {
|
||||
try {
|
||||
Object serverConnection = NMSUtils.getMinecraftServerConnection();
|
||||
for (Field field : serverConnection.getClass().getDeclaredFields()) {
|
||||
field.setAccessible(true);
|
||||
Object value = null;
|
||||
try {
|
||||
value = field.get(serverConnection);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (value instanceof List) {
|
||||
//Get the list.
|
||||
List listWrapper = new ListWrapper((List) value) {
|
||||
@Override
|
||||
public void processAdd(Object o) {
|
||||
if (o instanceof ChannelFuture) {
|
||||
try {
|
||||
injectChannelFuture((ChannelFuture) o);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
HashMap<Field, Object> map = new HashMap<>();
|
||||
map.put(field, serverConnection);
|
||||
injectedLists.add(map);
|
||||
|
||||
field.set(serverConnection, listWrapper);
|
||||
|
||||
synchronized (listWrapper) {
|
||||
for (Object serverChannel : (List) value) {
|
||||
//Is this the server channel future list?
|
||||
if (serverChannel instanceof ChannelFuture) {
|
||||
//Yes it is...
|
||||
injectChannelFuture((ChannelFuture) serverChannel);
|
||||
} else {
|
||||
break;//Wrong list
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
PacketEvents.get().getPlugin().getLogger().severe("PacketEvents failed to inject!");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
//Player channels might have been registered already. Let us add our handlers. We are a little late though.
|
||||
//This only happens when you join extremely early on older versions of minecraft.
|
||||
List<Object> networkManagers = NMSUtils.getNetworkManagers();
|
||||
synchronized (networkManagers) {
|
||||
for (Object networkManager : networkManagers) {
|
||||
WrappedPacket networkManagerWrapper = new WrappedPacket(new NMSPacket(networkManager));
|
||||
Channel channel = (Channel) networkManagerWrapper.readObject(0, NMSUtils.nettyChannelClass);
|
||||
if (channel == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (channel.pipeline().get("packet_handler") != null) {
|
||||
channel.pipeline().addBefore("packet_handler", PacketEvents.handlerName, new PlayerChannelHandlerLegacy());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void injectChannelFuture(ChannelFuture channelFuture) {
|
||||
List<String> channelHandlerNames = channelFuture.channel().pipeline().names();
|
||||
ChannelHandler bootstrapAcceptor = null;
|
||||
Field bootstrapAcceptorField = null;
|
||||
for (String handlerName : channelHandlerNames) {
|
||||
ChannelHandler handler = channelFuture.channel().pipeline().get(handlerName);
|
||||
try {
|
||||
bootstrapAcceptorField = handler.getClass().getDeclaredField("childHandler");
|
||||
bootstrapAcceptorField.setAccessible(true);
|
||||
bootstrapAcceptorField.get(handler);
|
||||
bootstrapAcceptor = handler;
|
||||
} catch (Exception ex) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (bootstrapAcceptor == null) {
|
||||
bootstrapAcceptor = channelFuture.channel().pipeline().first();
|
||||
}
|
||||
|
||||
ChannelInitializer<?> oldChannelInitializer = null;
|
||||
try {
|
||||
oldChannelInitializer = (ChannelInitializer<?>) bootstrapAcceptorField.get(bootstrapAcceptor);
|
||||
|
||||
ChannelInitializer<?> channelInitializer = new PEChannelInitializerLegacy(oldChannelInitializer);
|
||||
|
||||
//Replace the old channel initializer with our own.
|
||||
bootstrapAcceptorField.setAccessible(true);
|
||||
bootstrapAcceptorField.set(bootstrapAcceptor, channelInitializer);
|
||||
|
||||
injectedFutures.add(channelFuture);
|
||||
} catch (IllegalAccessException e) {
|
||||
ClassLoader cl = bootstrapAcceptor.getClass().getClassLoader();
|
||||
if (cl.getClass().getName().equals("org.bukkit.plugin.java.PluginClassLoader")) {
|
||||
PluginDescriptionFile yaml = null;
|
||||
try {
|
||||
yaml = (PluginDescriptionFile) PluginDescriptionFile.class.getDeclaredField("description").get(cl);
|
||||
} catch (IllegalAccessException | NoSuchFieldException e2) {
|
||||
e2.printStackTrace();
|
||||
}
|
||||
throw new IllegalStateException("PacketEvents failed to inject, because of " + bootstrapAcceptor.getClass().getName() + ", you might want to try running without " + yaml.getName() + "?");
|
||||
} else {
|
||||
throw new IllegalStateException("PacketEvents failed to find core component 'childHandler', please check your plugins. issue: " + bootstrapAcceptor.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eject() {
|
||||
Field childHandlerField = null;
|
||||
for (ChannelFuture future : injectedFutures) {
|
||||
List<String> names = future.channel().pipeline().names();
|
||||
ChannelHandler bootstrapAcceptor = null;
|
||||
// Pick best
|
||||
for (String name : names) {
|
||||
try {
|
||||
ChannelHandler handler = future.channel().pipeline().get(name);
|
||||
if (childHandlerField == null) {
|
||||
childHandlerField = handler.getClass().getDeclaredField("childHandler");
|
||||
childHandlerField.setAccessible(true);
|
||||
}
|
||||
|
||||
ChannelInitializer<SocketChannel> oldInit = (ChannelInitializer<SocketChannel>) childHandlerField.get(handler);
|
||||
if (oldInit instanceof PEChannelInitializerLegacy) {
|
||||
bootstrapAcceptor = handler;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Not this one
|
||||
}
|
||||
}
|
||||
// Default to first
|
||||
if (bootstrapAcceptor == null) {
|
||||
bootstrapAcceptor = future.channel().pipeline().first();
|
||||
}
|
||||
|
||||
try {
|
||||
ChannelInitializer<SocketChannel> oldInit = (ChannelInitializer<SocketChannel>) childHandlerField.get(bootstrapAcceptor);
|
||||
if (oldInit instanceof PEChannelInitializerLegacy) {
|
||||
childHandlerField.setAccessible(true);
|
||||
childHandlerField.set(bootstrapAcceptor, ((PEChannelInitializerLegacy) oldInit).getOldChannelInitializer());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
PacketEvents.get().getPlugin().getLogger().severe("PacketEvents failed to eject the injection handler! Please reboot!");
|
||||
}
|
||||
}
|
||||
injectedFutures.clear();
|
||||
|
||||
for (Map<Field, Object> map : injectedLists) {
|
||||
try {
|
||||
for (Field key : map.keySet()) {
|
||||
key.setAccessible(true);
|
||||
Object o = map.get(key);
|
||||
if (o instanceof ListWrapper) {
|
||||
key.set(o, ((ListWrapper) o).getOriginalList());
|
||||
}
|
||||
}
|
||||
|
||||
} catch (IllegalAccessException e) {
|
||||
PacketEvents.get().getPlugin().getLogger().severe("PacketEvents failed to eject the injection handler! Please reboot!!");
|
||||
}
|
||||
}
|
||||
|
||||
injectedLists.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectPlayer(Player player) {
|
||||
Object channel = PacketEvents.get().packetProcessorInternal.getChannel(player);
|
||||
if (channel != null) {
|
||||
updatePlayerObject(player, channel);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ejectPlayer(Player player) {
|
||||
Object channel = PacketEvents.get().packetProcessorInternal.getChannel(player);
|
||||
if (channel != null) {
|
||||
Channel chnl = (Channel) channel;
|
||||
try {
|
||||
chnl.pipeline().remove(PacketEvents.handlerName);
|
||||
} catch (Exception ex) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasInjected(Player player) {
|
||||
Object channel = PacketEvents.get().packetProcessorInternal.getChannel(player);
|
||||
if (channel == null) {
|
||||
return false;
|
||||
}
|
||||
PlayerChannelHandlerLegacy handler = getHandler(channel);
|
||||
return handler != null && handler.player != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPacket(Object ch, Object rawNMSPacket) {
|
||||
Channel channel = (Channel) ch;
|
||||
channel.writeAndFlush(rawNMSPacket);
|
||||
}
|
||||
|
||||
private PlayerChannelHandlerLegacy getHandler(Object rawChannel) {
|
||||
Channel channel = (Channel) rawChannel;
|
||||
ChannelHandler handler = channel.pipeline().get(PacketEvents.handlerName);
|
||||
if (handler instanceof PlayerChannelHandlerLegacy) {
|
||||
return (PlayerChannelHandlerLegacy) handler;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePlayerObject(Player player, Object rawChannel) {
|
||||
PlayerChannelHandlerLegacy handler = getHandler(rawChannel);
|
||||
if (handler != null) {
|
||||
handler.player = player;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBound() {
|
||||
try {
|
||||
Object connection = NMSUtils.getMinecraftServerConnection();
|
||||
if (connection == null) {
|
||||
return false;
|
||||
}
|
||||
for (Field field : connection.getClass().getDeclaredFields()) {
|
||||
field.setAccessible(true);
|
||||
final Object value = field.get(connection);
|
||||
if (value instanceof List) {
|
||||
// Inject the list
|
||||
synchronized (value) {
|
||||
for (Object o : (List) value) {
|
||||
if (o instanceof ChannelFuture) {
|
||||
return true;
|
||||
} else {
|
||||
break; // not the right list.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.injector.legacy.early;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.injector.legacy.PlayerChannelHandlerLegacy;
|
||||
import io.github.retrooper.packetevents.utils.reflection.Reflection;
|
||||
import net.minecraft.util.io.netty.channel.ChannelInitializer;
|
||||
import net.minecraft.util.io.netty.channel.socket.SocketChannel;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class PEChannelInitializerLegacy extends ChannelInitializer<SocketChannel> {
|
||||
private final ChannelInitializer<?> oldChannelInitializer;
|
||||
private Method initChannelMethod;
|
||||
|
||||
public PEChannelInitializerLegacy(ChannelInitializer<?> oldChannelInitializer) {
|
||||
this.oldChannelInitializer = oldChannelInitializer;
|
||||
load();
|
||||
}
|
||||
|
||||
private void load() {
|
||||
initChannelMethod = Reflection.getMethod(oldChannelInitializer.getClass(), "initChannel", 0);
|
||||
}
|
||||
|
||||
public ChannelInitializer<?> getOldChannelInitializer() {
|
||||
return oldChannelInitializer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initChannel(SocketChannel socketChannel) throws Exception {
|
||||
initChannelMethod.invoke(oldChannelInitializer, socketChannel);
|
||||
PlayerChannelHandlerLegacy channelHandler = new PlayerChannelHandlerLegacy();
|
||||
if (socketChannel.pipeline().get("packet_handler") != null) {
|
||||
socketChannel.pipeline().addBefore("packet_handler", PacketEvents.handlerName, channelHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.injector.legacy.late;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.injector.legacy.PlayerChannelHandlerLegacy;
|
||||
import io.github.retrooper.packetevents.injector.LateInjector;
|
||||
import net.minecraft.util.io.netty.channel.Channel;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class LateChannelInjectorLegacy implements LateInjector {
|
||||
@Override
|
||||
public void inject() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eject() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectPlayer(Player player) {
|
||||
PlayerChannelHandlerLegacy playerChannelHandlerLegacy = new PlayerChannelHandlerLegacy();
|
||||
playerChannelHandlerLegacy.player = player;
|
||||
Channel channel = (Channel) PacketEvents.get().packetProcessorInternal.getChannel(player);
|
||||
channel.pipeline().addBefore("packet_handler", PacketEvents.handlerName, playerChannelHandlerLegacy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ejectPlayer(Player player) {
|
||||
Object channel = PacketEvents.get().packetProcessorInternal.getChannel(player);
|
||||
if (channel != null) {
|
||||
Channel chnl = (Channel) channel;
|
||||
try {
|
||||
chnl.pipeline().remove(PacketEvents.handlerName);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasInjected(Player player) {
|
||||
Channel channel = (Channel) PacketEvents.get().packetProcessorInternal.getChannel(player);
|
||||
return channel.pipeline().get(PacketEvents.handlerName) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPacket(Object rawChannel, Object packet) {
|
||||
Channel channel = (Channel) rawChannel;
|
||||
channel.pipeline().writeAndFlush(packet);
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.injector.modern;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.netty.channel.ChannelDuplexHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class PlayerChannelHandlerModern extends ChannelDuplexHandler {
|
||||
/**
|
||||
* Associated player.
|
||||
* This is null until we inject the player.
|
||||
*/
|
||||
public volatile Player player;
|
||||
|
||||
@Override
|
||||
public void channelRead(final ChannelHandlerContext ctx, Object packet) throws Exception {
|
||||
try {
|
||||
packet = PacketEvents.get().packetProcessorInternal.read(player, ctx.channel(), packet);
|
||||
if (packet != null) {
|
||||
super.channelRead(ctx, packet);
|
||||
PacketEvents.get().packetProcessorInternal.postRead(player, ctx.channel(), packet);
|
||||
}
|
||||
}
|
||||
catch (Throwable t) {
|
||||
PacketEvents.get().getPlugin().getLogger().log(Level.SEVERE, "Unable to handle an incoming packet ", t.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final ChannelHandlerContext ctx, Object packet, final ChannelPromise promise) throws Exception {
|
||||
try {
|
||||
packet = PacketEvents.get().packetProcessorInternal.write(player, ctx.channel(), packet);
|
||||
if (packet != null) {
|
||||
super.write(ctx, packet, promise);
|
||||
PacketEvents.get().packetProcessorInternal.postWrite(player, ctx.channel(), packet);
|
||||
}
|
||||
}
|
||||
catch (Throwable t) {
|
||||
PacketEvents.get().getPlugin().getLogger().log(Level.SEVERE, "Unable to handle an outgoing packet ", t.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
+310
@@ -0,0 +1,310 @@
|
||||
/*
|
||||
* 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.injector.modern.early;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.injector.EarlyInjector;
|
||||
import io.github.retrooper.packetevents.injector.modern.PlayerChannelHandlerModern;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.list.ListWrapper;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Early channel injector for all server versions higher than 1.7.10.
|
||||
* Thank you ViaVersion.
|
||||
* https://github.com/ViaVersion/ViaVersion/tree/master/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaInjector.java
|
||||
*
|
||||
* @author retrooper, Thomazz, ViaVersion
|
||||
* @since 1.8
|
||||
*/
|
||||
public class EarlyChannelInjectorModern implements EarlyInjector {
|
||||
private final List<ChannelFuture> injectedFutures = new ArrayList<>();
|
||||
private final List<Map<Field, Object>> injectedLists = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void inject() {
|
||||
try {
|
||||
Object serverConnection = NMSUtils.getMinecraftServerConnection();
|
||||
for (Field field : serverConnection.getClass().getDeclaredFields()) {
|
||||
field.setAccessible(true);
|
||||
Object value = null;
|
||||
try {
|
||||
value = field.get(serverConnection);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (value instanceof List) {
|
||||
//Get the list.
|
||||
List listWrapper = new ListWrapper((List) value) {
|
||||
@Override
|
||||
public void processAdd(Object o) {
|
||||
if (o instanceof ChannelFuture) {
|
||||
try {
|
||||
injectChannelFuture((ChannelFuture) o);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
HashMap<Field, Object> map = new HashMap<>();
|
||||
map.put(field, serverConnection);
|
||||
injectedLists.add(map);
|
||||
|
||||
field.set(serverConnection, listWrapper);
|
||||
|
||||
synchronized (listWrapper) {
|
||||
for (Object serverChannel : (List) value) {
|
||||
//Is this the server channel future list?
|
||||
if (serverChannel instanceof ChannelFuture) {
|
||||
//Yes it is...
|
||||
injectChannelFuture((ChannelFuture) serverChannel);
|
||||
} else {
|
||||
break;//Wrong list
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new IllegalStateException("PacketEvents failed to inject!", ex);
|
||||
}
|
||||
|
||||
//Player channels might have been registered already. Let us add our handlers. We are a little late though.
|
||||
//This only happens when you join extremely early on older versions of minecraft.
|
||||
List<Object> networkManagers = NMSUtils.getNetworkManagers();
|
||||
synchronized (networkManagers) {
|
||||
for (Object networkManager : networkManagers) {
|
||||
WrappedPacket networkManagerWrapper = new WrappedPacket(new NMSPacket(networkManager));
|
||||
Channel channel = (Channel) networkManagerWrapper.readObject(0, NMSUtils.nettyChannelClass);
|
||||
if (channel == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (channel.pipeline().get("packet_handler") != null) {
|
||||
channel.pipeline().addBefore("packet_handler", PacketEvents.handlerName, new PlayerChannelHandlerModern());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void injectChannelFuture(ChannelFuture channelFuture) {
|
||||
List<String> channelHandlerNames = channelFuture.channel().pipeline().names();
|
||||
ChannelHandler bootstrapAcceptor = null;
|
||||
Field bootstrapAcceptorField = null;
|
||||
for (String handlerName : channelHandlerNames) {
|
||||
ChannelHandler handler = channelFuture.channel().pipeline().get(handlerName);
|
||||
try {
|
||||
bootstrapAcceptorField = handler.getClass().getDeclaredField("childHandler");
|
||||
bootstrapAcceptorField.setAccessible(true);
|
||||
bootstrapAcceptorField.get(handler);
|
||||
bootstrapAcceptor = handler;
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
|
||||
if (bootstrapAcceptor == null) {
|
||||
bootstrapAcceptor = channelFuture.channel().pipeline().first();
|
||||
}
|
||||
|
||||
ChannelInitializer<?> oldChannelInitializer;
|
||||
try {
|
||||
oldChannelInitializer = (ChannelInitializer<?>) bootstrapAcceptorField.get(bootstrapAcceptor);
|
||||
|
||||
ChannelInitializer<?> channelInitializer = new PEChannelInitializerModern(oldChannelInitializer);
|
||||
|
||||
//Replace the old channel initializer with our own.
|
||||
bootstrapAcceptorField.setAccessible(true);
|
||||
bootstrapAcceptorField.set(bootstrapAcceptor, channelInitializer);
|
||||
injectedFutures.add(channelFuture);
|
||||
} catch (IllegalAccessException e) {
|
||||
ClassLoader cl = bootstrapAcceptor.getClass().getClassLoader();
|
||||
if (cl.getClass().getName().equals("org.bukkit.plugin.java.PluginClassLoader")) {
|
||||
PluginDescriptionFile yaml = null;
|
||||
try {
|
||||
yaml = (PluginDescriptionFile) PluginDescriptionFile.class.getDeclaredField("description").get(cl);
|
||||
} catch (IllegalAccessException | NoSuchFieldException e2) {
|
||||
e2.printStackTrace();
|
||||
}
|
||||
throw new IllegalStateException("PacketEvents failed to inject, because of " + bootstrapAcceptor.getClass().getName() + ", you might want to try running without " + yaml.getName() + "?");
|
||||
} else {
|
||||
throw new IllegalStateException("PacketEvents failed to find core component 'childHandler', please check your plugins. issue: " + bootstrapAcceptor.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eject() {
|
||||
Field childHandlerField = null;
|
||||
for (ChannelFuture future : injectedFutures) {
|
||||
List<String> names = future.channel().pipeline().names();
|
||||
ChannelHandler bootstrapAcceptor = null;
|
||||
// Pick best
|
||||
for (String name : names) {
|
||||
try {
|
||||
ChannelHandler handler = future.channel().pipeline().get(name);
|
||||
if (childHandlerField == null) {
|
||||
childHandlerField = handler.getClass().getDeclaredField("childHandler");
|
||||
childHandlerField.setAccessible(true);
|
||||
}
|
||||
|
||||
ChannelInitializer<SocketChannel> oldInit = (ChannelInitializer<SocketChannel>) childHandlerField.get(handler);
|
||||
if (oldInit instanceof PEChannelInitializerModern) {
|
||||
bootstrapAcceptor = handler;
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
// Not this one
|
||||
}
|
||||
}
|
||||
// Default to first
|
||||
if (bootstrapAcceptor == null) {
|
||||
bootstrapAcceptor = future.channel().pipeline().first();
|
||||
}
|
||||
|
||||
try {
|
||||
ChannelInitializer<SocketChannel> oldInit = (ChannelInitializer<SocketChannel>) childHandlerField.get(bootstrapAcceptor);
|
||||
if (oldInit instanceof PEChannelInitializerModern) {
|
||||
childHandlerField.setAccessible(true);
|
||||
childHandlerField.set(bootstrapAcceptor, ((PEChannelInitializerModern) oldInit).getOldChannelInitializer());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
PacketEvents.get().getPlugin().getLogger().severe("PacketEvents failed to eject the injection handler! Please reboot!");
|
||||
}
|
||||
}
|
||||
injectedFutures.clear();
|
||||
|
||||
for (Map<Field, Object> map : injectedLists) {
|
||||
try {
|
||||
for (Field key : map.keySet()) {
|
||||
key.setAccessible(true);
|
||||
Object o = map.get(key);
|
||||
if (o instanceof ListWrapper) {
|
||||
key.set(o, ((ListWrapper) o).getOriginalList());
|
||||
}
|
||||
}
|
||||
|
||||
} catch (IllegalAccessException e) {
|
||||
PacketEvents.get().getPlugin().getLogger().severe("PacketEvents failed to eject the injection handler! Please reboot!!");
|
||||
}
|
||||
}
|
||||
|
||||
injectedLists.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectPlayer(Player player) {
|
||||
Object channel = PacketEvents.get().packetProcessorInternal.getChannel(player);
|
||||
if (channel != null) {
|
||||
updatePlayerObject(player, channel);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ejectPlayer(Player player) {
|
||||
Object channel = PacketEvents.get().packetProcessorInternal.getChannel(player);
|
||||
if (channel != null) {
|
||||
Channel chnl = (Channel) channel;
|
||||
try {
|
||||
chnl.pipeline().remove(PacketEvents.handlerName);
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasInjected(Player player) {
|
||||
Object channel = PacketEvents.get().packetProcessorInternal.getChannel(player);
|
||||
if (channel == null) {
|
||||
return false;
|
||||
}
|
||||
PlayerChannelHandlerModern handler = getHandler(channel);
|
||||
return handler != null && handler.player != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPacket(Object ch, Object rawNMSPacket) {
|
||||
Channel channel = (Channel) ch;
|
||||
channel.writeAndFlush(rawNMSPacket);
|
||||
}
|
||||
|
||||
private PlayerChannelHandlerModern getHandler(Object rawChannel) {
|
||||
Channel channel = (Channel) rawChannel;
|
||||
ChannelHandler handler = channel.pipeline().get(PacketEvents.handlerName);
|
||||
if (handler instanceof PlayerChannelHandlerModern) {
|
||||
return (PlayerChannelHandlerModern) handler;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePlayerObject(Player player, Object rawChannel) {
|
||||
PlayerChannelHandlerModern handler = getHandler(rawChannel);
|
||||
if (handler != null) {
|
||||
handler.player = player;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBound() {
|
||||
try {
|
||||
Object connection = NMSUtils.getMinecraftServerConnection();
|
||||
if (connection == null) {
|
||||
return false;
|
||||
}
|
||||
for (Field field : connection.getClass().getDeclaredFields()) {
|
||||
field.setAccessible(true);
|
||||
final Object value = field.get(connection);
|
||||
if (value instanceof List) {
|
||||
// Inject the list
|
||||
synchronized (value) {
|
||||
for (Object o : (List) value) {
|
||||
if (o instanceof ChannelFuture) {
|
||||
return true;
|
||||
} else {
|
||||
break; // not the right list.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.injector.modern.early;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.injector.modern.PlayerChannelHandlerModern;
|
||||
import io.github.retrooper.packetevents.utils.reflection.Reflection;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class PEChannelInitializerModern extends ChannelInitializer<SocketChannel> {
|
||||
private final ChannelInitializer<?> oldChannelInitializer;
|
||||
private Method initChannelMethod;
|
||||
|
||||
public PEChannelInitializerModern(ChannelInitializer<?> oldChannelInitializer) {
|
||||
this.oldChannelInitializer = oldChannelInitializer;
|
||||
load();
|
||||
}
|
||||
|
||||
private void load() {
|
||||
initChannelMethod = Reflection.getMethod(oldChannelInitializer.getClass(), "initChannel", 0);
|
||||
}
|
||||
|
||||
public ChannelInitializer<?> getOldChannelInitializer() {
|
||||
return oldChannelInitializer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initChannel(SocketChannel socketChannel) throws Exception {
|
||||
initChannelMethod.invoke(oldChannelInitializer, socketChannel);
|
||||
PlayerChannelHandlerModern channelHandler = new PlayerChannelHandlerModern();
|
||||
if (socketChannel.pipeline().get("packet_handler") != null) {
|
||||
socketChannel.pipeline().addBefore("packet_handler", PacketEvents.handlerName, channelHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.injector.modern.late;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.injector.modern.PlayerChannelHandlerModern;
|
||||
import io.github.retrooper.packetevents.injector.LateInjector;
|
||||
import io.netty.channel.Channel;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class LateChannelInjectorModern implements LateInjector {
|
||||
@Override
|
||||
public void inject() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eject() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectPlayer(Player player) {
|
||||
PlayerChannelHandlerModern playerChannelHandlerModern = new PlayerChannelHandlerModern();
|
||||
playerChannelHandlerModern.player = player;
|
||||
Channel channel = (Channel) PacketEvents.get().packetProcessorInternal.getChannel(player);
|
||||
channel.pipeline().addBefore("packet_handler", PacketEvents.handlerName, playerChannelHandlerModern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ejectPlayer(Player player) {
|
||||
Object channel = PacketEvents.get().packetProcessorInternal.getChannel(player);
|
||||
if (channel != null) {
|
||||
Channel chnl = (Channel) channel;
|
||||
try {
|
||||
chnl.pipeline().remove(PacketEvents.handlerName);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasInjected(Player player) {
|
||||
Channel channel = (Channel) PacketEvents.get().packetProcessorInternal.getChannel(player);
|
||||
return channel.pipeline().get(PacketEvents.handlerName) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPacket(Object rawChannel, Object packet) {
|
||||
Channel channel = (Channel) rawChannel;
|
||||
channel.pipeline().writeAndFlush(packet);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package io.github.retrooper.packetevents.packettype;
|
||||
|
||||
/**
|
||||
* @author retrooper
|
||||
* @since 1.8
|
||||
*/
|
||||
public enum PacketState {
|
||||
STATUS, HANDSHAKING, LOGIN, PLAY
|
||||
}
|
||||
@@ -28,7 +28,9 @@ import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.utils.server.ServerVersion;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Packet Type IDs.
|
||||
@@ -43,7 +45,28 @@ public class PacketType {
|
||||
* If a Packet Type could not be resolved, it will be set to the current value of this constant.
|
||||
* This value may change over the versions so it is important to use the variable and not hard code its value.
|
||||
*/
|
||||
public static final byte INVALID = -1;
|
||||
public static final byte INVALID = -128;
|
||||
public static final Map<Class<?>, Byte> packetIDMap = new IdentityHashMap<>();
|
||||
|
||||
private static void insertPacketID(Class<?> cls, byte packetID) {
|
||||
if (cls != null) {
|
||||
packetIDMap.put(cls, packetID);
|
||||
}
|
||||
}
|
||||
|
||||
public static void load() {
|
||||
Status.Client.load();
|
||||
Status.Server.load();
|
||||
|
||||
Handshaking.Client.load();
|
||||
|
||||
Login.Client.load();
|
||||
Login.Server.load();
|
||||
|
||||
Play.Client.load();
|
||||
Play.Server.load();
|
||||
}
|
||||
|
||||
/**
|
||||
* Status Packet IDs.
|
||||
*
|
||||
@@ -60,15 +83,10 @@ public class PacketType {
|
||||
* @since 1.8
|
||||
*/
|
||||
public static class Client {
|
||||
public static final byte START = 0, PING = 1;
|
||||
public static final Map<Class<?>, Byte> packetIds = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Load the server-bound status Packet IDs.
|
||||
*/
|
||||
public static void init() {
|
||||
packetIds.put(PacketTypeClasses.Status.Client.START, Client.START);
|
||||
packetIds.put(PacketTypeClasses.Status.Client.PING, Client.PING);
|
||||
public static final byte START = -127, PING = -126;
|
||||
private static void load() {
|
||||
insertPacketID(PacketTypeClasses.Status.Client.START, Client.START);
|
||||
insertPacketID(PacketTypeClasses.Status.Client.PING, Client.PING);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,15 +98,32 @@ public class PacketType {
|
||||
* @since 1.8
|
||||
*/
|
||||
public static class Server {
|
||||
public static final byte PONG = 0, SERVER_INFO = 1;
|
||||
public static final Map<Class<?>, Byte> packetIds = new HashMap<>();
|
||||
public static final byte PONG = -125, SERVER_INFO = -124;
|
||||
private static void load() {
|
||||
insertPacketID(PacketTypeClasses.Status.Server.PONG, Server.PONG);
|
||||
insertPacketID(PacketTypeClasses.Status.Server.SERVER_INFO, Server.SERVER_INFO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the client-bound Status Packet IDs.
|
||||
*/
|
||||
public static void init() {
|
||||
packetIds.put(PacketTypeClasses.Status.Server.PONG, Server.PONG);
|
||||
packetIds.put(PacketTypeClasses.Status.Server.SERVER_INFO, Server.SERVER_INFO);
|
||||
/**
|
||||
* Handshaking Packet IDs.
|
||||
*
|
||||
* @author retrooper
|
||||
* @see <a href="https://wiki.vg/Protocol#Handshaking">https://wiki.vg/Protocol#Handshaking</a>
|
||||
* @since 1.8
|
||||
*/
|
||||
public static class Handshaking {
|
||||
/**
|
||||
* Server-bound (client-sided) Handshaking Packet IDs.
|
||||
*
|
||||
* @author retrooper
|
||||
* @since 1.8
|
||||
*/
|
||||
public static class Client {
|
||||
public static final byte SET_PROTOCOL = -123;
|
||||
private static void load() {
|
||||
insertPacketID(PacketTypeClasses.Handshaking.Client.SET_PROTOCOL, Client.SET_PROTOCOL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -109,17 +144,11 @@ public class PacketType {
|
||||
* @since 1.8
|
||||
*/
|
||||
public static class Client {
|
||||
public static final Map<Class<?>, Byte> packetIds = new HashMap<>();
|
||||
public static final byte HANDSHAKE = 0, CUSTOM_PAYLOAD = 1, START = 2, ENCRYPTION_BEGIN = 3;
|
||||
|
||||
/**
|
||||
* Load the server-bound Login Packet IDs.
|
||||
*/
|
||||
public static void init() {
|
||||
packetIds.put(PacketTypeClasses.Login.Client.HANDSHAKE, Client.HANDSHAKE);
|
||||
packetIds.put(PacketTypeClasses.Login.Client.CUSTOM_PAYLOAD, Client.CUSTOM_PAYLOAD);
|
||||
packetIds.put(PacketTypeClasses.Login.Client.START, Client.START);
|
||||
packetIds.put(PacketTypeClasses.Login.Client.ENCRYPTION_BEGIN, Client.ENCRYPTION_BEGIN);
|
||||
public static final byte CUSTOM_PAYLOAD = -122, START = -121, ENCRYPTION_BEGIN = -120;
|
||||
private static void load() {
|
||||
insertPacketID(PacketTypeClasses.Login.Client.CUSTOM_PAYLOAD, Client.CUSTOM_PAYLOAD);
|
||||
insertPacketID(PacketTypeClasses.Login.Client.START, Client.START);
|
||||
insertPacketID(PacketTypeClasses.Login.Client.ENCRYPTION_BEGIN, Client.ENCRYPTION_BEGIN);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,18 +160,13 @@ public class PacketType {
|
||||
* @since 1.8
|
||||
*/
|
||||
public static class Server {
|
||||
public static final Map<Class<?>, Byte> packetIds = new HashMap<>();
|
||||
public static final byte CUSTOM_PAYLOAD = 0, DISCONNECT = 1, ENCRYPTION_BEGIN = 2, SUCCESS = 3, SET_COMPRESSION = 4;
|
||||
|
||||
/**
|
||||
* Load the client-bound Login Packet IDs.
|
||||
*/
|
||||
public static void init() {
|
||||
packetIds.put(PacketTypeClasses.Login.Server.CUSTOM_PAYLOAD, Server.CUSTOM_PAYLOAD);
|
||||
packetIds.put(PacketTypeClasses.Login.Server.DISCONNECT, Server.DISCONNECT);
|
||||
packetIds.put(PacketTypeClasses.Login.Server.ENCRYPTION_BEGIN, Server.ENCRYPTION_BEGIN);
|
||||
packetIds.put(PacketTypeClasses.Login.Server.SUCCESS, Server.SUCCESS);
|
||||
packetIds.put(PacketTypeClasses.Login.Server.SET_COMPRESSION, Server.SET_COMPRESSION);
|
||||
public static final byte CUSTOM_PAYLOAD = -119, DISCONNECT = -118, ENCRYPTION_BEGIN = -117, SUCCESS = -116, SET_COMPRESSION = -115;
|
||||
private static void load() {
|
||||
insertPacketID(PacketTypeClasses.Login.Server.CUSTOM_PAYLOAD, Server.CUSTOM_PAYLOAD);
|
||||
insertPacketID(PacketTypeClasses.Login.Server.DISCONNECT, Server.DISCONNECT);
|
||||
insertPacketID(PacketTypeClasses.Login.Server.ENCRYPTION_BEGIN, Server.ENCRYPTION_BEGIN);
|
||||
insertPacketID(PacketTypeClasses.Login.Server.SUCCESS, Server.SUCCESS);
|
||||
insertPacketID(PacketTypeClasses.Login.Server.SET_COMPRESSION, Server.SET_COMPRESSION);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -163,72 +187,68 @@ public class PacketType {
|
||||
* @since 1.8
|
||||
*/
|
||||
public static class Client {
|
||||
public static final Map<Class<?>, Byte> packetIds = new HashMap<>();
|
||||
public static final byte TELEPORT_ACCEPT = 0,
|
||||
TILE_NBT_QUERY = 1, DIFFICULTY_CHANGE = 2, CHAT = 3, CLIENT_COMMAND = 4,
|
||||
SETTINGS = 5, TAB_COMPLETE = 6, TRANSACTION = 7, ENCHANT_ITEM = 8,
|
||||
WINDOW_CLICK = 9, CLOSE_WINDOW = 10, CUSTOM_PAYLOAD = 11, B_EDIT = 12,
|
||||
ENTITY_NBT_QUERY = 13, USE_ENTITY = 14, JIGSAW_GENERATE = 15, KEEP_ALIVE = 16,
|
||||
DIFFICULTY_LOCK = 17, POSITION = 18, POSITION_LOOK = 19, LOOK = 20,
|
||||
FLYING = 21, VEHICLE_MOVE = 22, BOAT_MOVE = 23, PICK_ITEM = 24,
|
||||
AUTO_RECIPE = 25, ABILITIES = 26, BLOCK_DIG = 27, ENTITY_ACTION = 28,
|
||||
STEER_VEHICLE = 29, RECIPE_DISPLAYED = 30, ITEM_NAME = 31, RESOURCE_PACK_STATUS = 32,
|
||||
ADVANCEMENTS = 33, TR_SEL = 34, BEACON = 35, HELD_ITEM_SLOT = 36,
|
||||
SET_COMMAND_BLOCK = 37, SET_COMMAND_MINECART = 38, SET_CREATIVE_SLOT = 39, SET_JIGSAW = 40,
|
||||
STRUCT = 41, UPDATE_SIGN = 42, ARM_ANIMATION = 43, SPECTATE = 44,
|
||||
USE_ITEM = 45, BLOCK_PLACE = 46;
|
||||
public static final byte TELEPORT_ACCEPT = -114,
|
||||
TILE_NBT_QUERY = -113, DIFFICULTY_CHANGE = -112, CHAT = -111, CLIENT_COMMAND = -110,
|
||||
SETTINGS = -109, TAB_COMPLETE = -108, TRANSACTION = -107, ENCHANT_ITEM = -106,
|
||||
WINDOW_CLICK = -105, CLOSE_WINDOW = -104, CUSTOM_PAYLOAD = -103, B_EDIT = -102,
|
||||
ENTITY_NBT_QUERY = -101, USE_ENTITY = -100, JIGSAW_GENERATE = -99, KEEP_ALIVE = -98,
|
||||
DIFFICULTY_LOCK = -97, POSITION = -96, POSITION_LOOK = -95, LOOK = -94,
|
||||
FLYING = -93, VEHICLE_MOVE = -92, BOAT_MOVE = -91, PICK_ITEM = -90,
|
||||
AUTO_RECIPE = -89, ABILITIES = -88, BLOCK_DIG = -87, ENTITY_ACTION = -86,
|
||||
STEER_VEHICLE = -85, RECIPE_DISPLAYED = -84, ITEM_NAME = -83, RESOURCE_PACK_STATUS = -82,
|
||||
ADVANCEMENTS = -81, TR_SEL = -80, BEACON = -79, HELD_ITEM_SLOT = -78,
|
||||
SET_COMMAND_BLOCK = -77, SET_COMMAND_MINECART = -76, SET_CREATIVE_SLOT = -75, SET_JIGSAW = -74,
|
||||
STRUCT = -73, UPDATE_SIGN = -72, ARM_ANIMATION = -71, SPECTATE = -70,
|
||||
USE_ITEM = -69, BLOCK_PLACE = -68;
|
||||
|
||||
/**
|
||||
* Load the server-bound Play Packet IDs.
|
||||
*/
|
||||
public static void init() {
|
||||
packetIds.put(PacketTypeClasses.Play.Client.TELEPORT_ACCEPT, TELEPORT_ACCEPT);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.TILE_NBT_QUERY, TILE_NBT_QUERY);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.DIFFICULTY_CHANGE, DIFFICULTY_CHANGE);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.CHAT, CHAT);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.CLIENT_COMMAND, CLIENT_COMMAND);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.SETTINGS, SETTINGS);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.TAB_COMPLETE, TAB_COMPLETE);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.TRANSACTION, TRANSACTION);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.ENCHANT_ITEM, ENCHANT_ITEM);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.WINDOW_CLICK, WINDOW_CLICK);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.CLOSE_WINDOW, CLOSE_WINDOW);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.CUSTOM_PAYLOAD, CUSTOM_PAYLOAD);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.B_EDIT, B_EDIT);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.ENTITY_NBT_QUERY, ENTITY_NBT_QUERY);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.USE_ENTITY, USE_ENTITY);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.JIGSAW_GENERATE, JIGSAW_GENERATE);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.KEEP_ALIVE, KEEP_ALIVE);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.DIFFICULTY_LOCK, DIFFICULTY_LOCK);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.POSITION, POSITION);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.POSITION_LOOK, POSITION_LOOK);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.LOOK, LOOK);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.FLYING, FLYING);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.VEHICLE_MOVE, VEHICLE_MOVE);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.BOAT_MOVE, BOAT_MOVE);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.PICK_ITEM, PICK_ITEM);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.AUTO_RECIPE, AUTO_RECIPE);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.ABILITIES, ABILITIES);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.BLOCK_DIG, BLOCK_DIG);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.ENTITY_ACTION, ENTITY_ACTION);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.STEER_VEHICLE, STEER_VEHICLE);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.RECIPE_DISPLAYED, RECIPE_DISPLAYED);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.ITEM_NAME, ITEM_NAME);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.RESOURCE_PACK_STATUS, RESOURCE_PACK_STATUS);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.ADVANCEMENTS, ADVANCEMENTS);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.TR_SEL, TR_SEL);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.BEACON, BEACON);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.HELD_ITEM_SLOT, HELD_ITEM_SLOT);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.SET_COMMAND_BLOCK, SET_COMMAND_BLOCK);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.SET_COMMAND_MINECART, SET_COMMAND_MINECART);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.SET_CREATIVE_SLOT, SET_CREATIVE_SLOT);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.SET_JIGSAW, SET_JIGSAW);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.STRUCT, STRUCT);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.UPDATE_SIGN, UPDATE_SIGN);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.ARM_ANIMATION, ARM_ANIMATION);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.SPECTATE, SPECTATE);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.USE_ITEM, USE_ITEM);
|
||||
packetIds.put(PacketTypeClasses.Play.Client.BLOCK_PLACE, BLOCK_PLACE);
|
||||
private static void load() {
|
||||
insertPacketID(PacketTypeClasses.Play.Client.TELEPORT_ACCEPT, TELEPORT_ACCEPT);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.TILE_NBT_QUERY, TILE_NBT_QUERY);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.DIFFICULTY_CHANGE, DIFFICULTY_CHANGE);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.CHAT, CHAT);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.CLIENT_COMMAND, CLIENT_COMMAND);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.SETTINGS, SETTINGS);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.TAB_COMPLETE, TAB_COMPLETE);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.TRANSACTION, TRANSACTION);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.ENCHANT_ITEM, ENCHANT_ITEM);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.WINDOW_CLICK, WINDOW_CLICK);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.CLOSE_WINDOW, CLOSE_WINDOW);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.CUSTOM_PAYLOAD, CUSTOM_PAYLOAD);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.B_EDIT, B_EDIT);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.ENTITY_NBT_QUERY, ENTITY_NBT_QUERY);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.USE_ENTITY, USE_ENTITY);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.JIGSAW_GENERATE, JIGSAW_GENERATE);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.KEEP_ALIVE, KEEP_ALIVE);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.DIFFICULTY_LOCK, DIFFICULTY_LOCK);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.POSITION, POSITION);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.POSITION_LOOK, POSITION_LOOK);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.LOOK, LOOK);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.FLYING, FLYING);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.VEHICLE_MOVE, VEHICLE_MOVE);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.BOAT_MOVE, BOAT_MOVE);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.PICK_ITEM, PICK_ITEM);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.AUTO_RECIPE, AUTO_RECIPE);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.ABILITIES, ABILITIES);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.BLOCK_DIG, BLOCK_DIG);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.ENTITY_ACTION, ENTITY_ACTION);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.STEER_VEHICLE, STEER_VEHICLE);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.RECIPE_DISPLAYED, RECIPE_DISPLAYED);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.ITEM_NAME, ITEM_NAME);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.RESOURCE_PACK_STATUS, RESOURCE_PACK_STATUS);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.ADVANCEMENTS, ADVANCEMENTS);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.TR_SEL, TR_SEL);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.BEACON, BEACON);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.HELD_ITEM_SLOT, HELD_ITEM_SLOT);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.SET_COMMAND_BLOCK, SET_COMMAND_BLOCK);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.SET_COMMAND_MINECART, SET_COMMAND_MINECART);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.SET_CREATIVE_SLOT, SET_CREATIVE_SLOT);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.SET_JIGSAW, SET_JIGSAW);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.STRUCT, STRUCT);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.UPDATE_SIGN, UPDATE_SIGN);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.ARM_ANIMATION, ARM_ANIMATION);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.SPECTATE, SPECTATE);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.USE_ITEM, USE_ITEM);
|
||||
insertPacketID(PacketTypeClasses.Play.Client.BLOCK_PLACE, BLOCK_PLACE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -270,8 +290,8 @@ public class PacketType {
|
||||
public static boolean isBlockPlace(final byte packetID) {
|
||||
final ServerVersion version = PacketEvents.get().getServerUtils().getVersion();
|
||||
return version.isNewerThan(ServerVersion.v_1_8_8) ?
|
||||
packetID == Client.USE_ITEM
|
||||
: packetID == Client.BLOCK_PLACE;
|
||||
packetID == PacketType.Play.Client.USE_ITEM
|
||||
: packetID == PacketType.Play.Client.BLOCK_PLACE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -284,132 +304,128 @@ public class PacketType {
|
||||
* @since 1.8
|
||||
*/
|
||||
public static class Server {
|
||||
public static final Map<Class<?>, Byte> packetIds = new HashMap<>();
|
||||
public static final byte SPAWN_ENTITY = 0, SPAWN_ENTITY_EXPERIENCE_ORB = 1, SPAWN_ENTITY_WEATHER = 2, SPAWN_ENTITY_LIVING = 3,
|
||||
SPAWN_ENTITY_PAINTING = 4, SPAWN_ENTITY_SPAWN = 5, ANIMATION = 6, STATISTIC = 7,
|
||||
BLOCK_BREAK = 8, BLOCK_BREAK_ANIMATION = 9, TILE_ENTITY_DATA = 10, BLOCK_ACTION = 11,
|
||||
BLOCK_CHANGE = 12, BOSS = 13, SERVER_DIFFICULTY = 14, CHAT = 15, MULTI_BLOCK_CHANGE = 16,
|
||||
TAB_COMPLETE = 17, COMMANDS = 18, TRANSACTION = 19, CLOSE_WINDOW = 20,
|
||||
WINDOW_ITEMS = 21, WINDOW_DATA = 22, SET_SLOT = 23, SET_COOLDOWN = 24,
|
||||
CUSTOM_PAYLOAD = 25, CUSTOM_SOUND_EFFECT = 26, KICK_DISCONNECT = 27, ENTITY_STATUS = 28,
|
||||
EXPLOSION = 29, UNLOAD_CHUNK = 30, GAME_STATE_CHANGE = 31, OPEN_WINDOW_HORSE = 32,
|
||||
KEEP_ALIVE = 33, MAP_CHUNK = 34, WORLD_EVENT = 35, WORLD_PARTICLES = 36,
|
||||
LIGHT_UPDATE = 37, LOGIN = 38, MAP = 39, OPEN_WINDOW_MERCHANT = 40,
|
||||
REL_ENTITY_MOVE = 41, REL_ENTITY_MOVE_LOOK = 42, ENTITY_LOOK = 43, ENTITY = 44,
|
||||
VEHICLE_MOVE = 45, OPEN_BOOK = 46, OPEN_WINDOW = 47, OPEN_SIGN_EDITOR = 48,
|
||||
AUTO_RECIPE = 49, ABILITIES = 50, COMBAT_EVENT = 51, PLAYER_INFO = 52,
|
||||
LOOK_AT = 53, POSITION = 54, RECIPES = 55, ENTITY_DESTROY = 56,
|
||||
REMOVE_ENTITY_EFFECT = 57, RESOURCE_PACK_SEND = 58, RESPAWN = 59, ENTITY_HEAD_ROTATION = 60,
|
||||
SELECT_ADVANCEMENT_TAB = 61, WORLD_BORDER = 62, CAMERA = 63, HELD_ITEM_SLOT = 64,
|
||||
VIEW_CENTRE = 65, VIEW_DISTANCE = 66, SCOREBOARD_DISPLAY_OBJECTIVE = 67, ENTITY_METADATA = 68,
|
||||
ATTACH_ENTITY = 69, ENTITY_VELOCITY = 70, ENTITY_EQUIPMENT = 71, EXPERIENCE = 72,
|
||||
UPDATE_HEALTH = 73, SCOREBOARD_OBJECTIVE = 74, MOUNT = 75, SCOREBOARD_TEAM = 76,
|
||||
SCOREBOARD_SCORE = 77, SPAWN_POSITION = 78, UPDATE_TIME = 79, TITLE = 80,
|
||||
ENTITY_SOUND = 81, NAMED_SOUND_EFFECT = 82, STOP_SOUND = 83, PLAYER_LIST_HEADER_FOOTER = 84,
|
||||
NBT_QUERY = 85, COLLECT = 86, ENTITY_TELEPORT = 87, ADVANCEMENTS = 88, UPDATE_ATTRIBUTES = 89,
|
||||
ENTITY_EFFECT = 90, RECIPE_UPDATE = 91, TAGS = 92, MAP_CHUNK_BULK = 93, NAMED_ENTITY_SPAWN = 94;
|
||||
public static final byte SPAWN_ENTITY = -67, SPAWN_ENTITY_EXPERIENCE_ORB = -66, SPAWN_ENTITY_WEATHER = -65, SPAWN_ENTITY_LIVING = -64,
|
||||
SPAWN_ENTITY_PAINTING = -63, SPAWN_ENTITY_SPAWN = -62, ANIMATION = -61, STATISTIC = -60,
|
||||
BLOCK_BREAK = -59, BLOCK_BREAK_ANIMATION = -58, TILE_ENTITY_DATA = -57, BLOCK_ACTION = -56,
|
||||
BLOCK_CHANGE = -55, BOSS = -54, SERVER_DIFFICULTY = -53, CHAT = -52, MULTI_BLOCK_CHANGE = -51,
|
||||
TAB_COMPLETE = -50, COMMANDS = -49, TRANSACTION = -48, CLOSE_WINDOW = -47,
|
||||
WINDOW_ITEMS = -46, WINDOW_DATA = -45, SET_SLOT = -44, SET_COOLDOWN = -43,
|
||||
CUSTOM_PAYLOAD = -42, CUSTOM_SOUND_EFFECT = -41, KICK_DISCONNECT = -40, ENTITY_STATUS = -39,
|
||||
EXPLOSION = -38, UNLOAD_CHUNK = -37, GAME_STATE_CHANGE = -36, OPEN_WINDOW_HORSE = -35,
|
||||
KEEP_ALIVE = -34, MAP_CHUNK = -33, WORLD_EVENT = -32, WORLD_PARTICLES = -31,
|
||||
LIGHT_UPDATE = -30, LOGIN = -29, MAP = -28, OPEN_WINDOW_MERCHANT = -27,
|
||||
REL_ENTITY_MOVE = -26, REL_ENTITY_MOVE_LOOK = -25, ENTITY_LOOK = -24, ENTITY = -23,
|
||||
VEHICLE_MOVE = -22, OPEN_BOOK = -21, OPEN_WINDOW = -20, OPEN_SIGN_EDITOR = -19,
|
||||
AUTO_RECIPE = -18, ABILITIES = -17, COMBAT_EVENT = -16, PLAYER_INFO = -15,
|
||||
LOOK_AT = -14, POSITION = -13, RECIPES = -12, ENTITY_DESTROY = -11,
|
||||
REMOVE_ENTITY_EFFECT = -10, RESOURCE_PACK_SEND = -9, RESPAWN = -8, ENTITY_HEAD_ROTATION = -7,
|
||||
SELECT_ADVANCEMENT_TAB = -6, WORLD_BORDER = -5, CAMERA = -4, HELD_ITEM_SLOT = -3,
|
||||
VIEW_CENTRE = -2, VIEW_DISTANCE = -1, SCOREBOARD_DISPLAY_OBJECTIVE = 0, ENTITY_METADATA = 1,
|
||||
ATTACH_ENTITY = 2, ENTITY_VELOCITY = 3, ENTITY_EQUIPMENT = 4, EXPERIENCE = 5,
|
||||
UPDATE_HEALTH = 6, SCOREBOARD_OBJECTIVE = 7, MOUNT = 8, SCOREBOARD_TEAM = 9,
|
||||
SCOREBOARD_SCORE = 10, SPAWN_POSITION = 11, UPDATE_TIME = 12, TITLE = 13,
|
||||
ENTITY_SOUND = 14, NAMED_SOUND_EFFECT = 15, STOP_SOUND = 16, PLAYER_LIST_HEADER_FOOTER = 17,
|
||||
NBT_QUERY = 18, COLLECT = 19, ENTITY_TELEPORT = 20, ADVANCEMENTS = 21, UPDATE_ATTRIBUTES = 22,
|
||||
ENTITY_EFFECT = 23, RECIPE_UPDATE = 24, TAGS = 25, MAP_CHUNK_BULK = 26, NAMED_ENTITY_SPAWN = 27;
|
||||
|
||||
/**
|
||||
* Load the client-bound Play Packet IDs.
|
||||
*/
|
||||
public static void init() {
|
||||
packetIds.put(PacketTypeClasses.Play.Server.SPAWN_ENTITY, SPAWN_ENTITY);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.SPAWN_ENTITY_EXPERIENCE_ORB, SPAWN_ENTITY_EXPERIENCE_ORB);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.SPAWN_ENTITY_WEATHER, SPAWN_ENTITY_WEATHER);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.SPAWN_ENTITY_LIVING, SPAWN_ENTITY_LIVING);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.SPAWN_ENTITY_PAINTING, SPAWN_ENTITY_PAINTING);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.SPAWN_ENTITY_SPAWN, SPAWN_ENTITY_SPAWN);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.ANIMATION, ANIMATION);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.STATISTIC, STATISTIC);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.BLOCK_BREAK, BLOCK_BREAK);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.BLOCK_BREAK_ANIMATION, BLOCK_BREAK_ANIMATION);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.TILE_ENTITY_DATA, TILE_ENTITY_DATA);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.BLOCK_ACTION, BLOCK_ACTION);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.BLOCK_CHANGE, BLOCK_CHANGE);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.BOSS, BOSS);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.SPAWN_ENTITY, SPAWN_ENTITY);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.SERVER_DIFFICULTY, SERVER_DIFFICULTY);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.CHAT, CHAT);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.MULTI_BLOCK_CHANGE, MULTI_BLOCK_CHANGE);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.TAB_COMPLETE, TAB_COMPLETE);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.COMMANDS, COMMANDS);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.TRANSACTION, TRANSACTION);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.CLOSE_WINDOW, CLOSE_WINDOW);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.WINDOW_ITEMS, WINDOW_ITEMS);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.WINDOW_DATA, WINDOW_DATA);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.SET_SLOT, SET_SLOT);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.SET_COOLDOWN, SET_COOLDOWN);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.CUSTOM_PAYLOAD, CUSTOM_PAYLOAD);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.CUSTOM_SOUND_EFFECT, CUSTOM_SOUND_EFFECT);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.KICK_DISCONNECT, KICK_DISCONNECT);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.ENTITY_STATUS, ENTITY_STATUS);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.EXPLOSION, EXPLOSION);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.UNLOAD_CHUNK, UNLOAD_CHUNK);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.GAME_STATE_CHANGE, GAME_STATE_CHANGE);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.OPEN_WINDOW_HORSE, OPEN_WINDOW_HORSE);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.KEEP_ALIVE, KEEP_ALIVE);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.MAP_CHUNK, MAP_CHUNK);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.WORLD_EVENT, WORLD_EVENT);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.WORLD_EVENT, SPAWN_ENTITY);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.WORLD_PARTICLES, WORLD_PARTICLES);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.LIGHT_UPDATE, LIGHT_UPDATE);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.LOGIN, LOGIN);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.MAP, MAP);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.OPEN_WINDOW_MERCHANT, OPEN_WINDOW_MERCHANT);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.REL_ENTITY_MOVE, REL_ENTITY_MOVE);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.REL_ENTITY_MOVE_LOOK, REL_ENTITY_MOVE_LOOK);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.ENTITY_LOOK, ENTITY_LOOK);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.ENTITY, ENTITY);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.VEHICLE_MOVE, VEHICLE_MOVE);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.OPEN_BOOK, OPEN_BOOK);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.OPEN_WINDOW, OPEN_WINDOW);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.OPEN_SIGN_EDITOR, OPEN_SIGN_EDITOR);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.AUTO_RECIPE, AUTO_RECIPE);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.ABILITIES, ABILITIES);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.COMBAT_EVENT, COMBAT_EVENT);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.PLAYER_INFO, PLAYER_INFO);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.LOOK_AT, LOOK_AT);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.POSITION, POSITION);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.RECIPES, RECIPES);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.ENTITY_DESTROY, ENTITY_DESTROY);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.REMOVE_ENTITY_EFFECT, REMOVE_ENTITY_EFFECT);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.RESOURCE_PACK_SEND, RESOURCE_PACK_SEND);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.RESPAWN, RESPAWN);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.ENTITY_HEAD_ROTATION, ENTITY_HEAD_ROTATION);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.SELECT_ADVANCEMENT_TAB, SELECT_ADVANCEMENT_TAB);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.WORLD_BORDER, WORLD_BORDER);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.CAMERA, CAMERA);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.HELD_ITEM_SLOT, HELD_ITEM_SLOT);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.VIEW_CENTRE, VIEW_CENTRE);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.VIEW_DISTANCE, VIEW_DISTANCE);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.SCOREBOARD_DISPLAY_OBJECTIVE, SCOREBOARD_DISPLAY_OBJECTIVE);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.ENTITY_METADATA, ENTITY_METADATA);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.ATTACH_ENTITY, ATTACH_ENTITY);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.ENTITY_VELOCITY, ENTITY_VELOCITY);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.ENTITY_EQUIPMENT, ENTITY_EQUIPMENT);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.EXPERIENCE, EXPERIENCE);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.UPDATE_HEALTH, UPDATE_HEALTH);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.SCOREBOARD_OBJECTIVE, SCOREBOARD_OBJECTIVE);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.MOUNT, MOUNT);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.SCOREBOARD_TEAM, SCOREBOARD_TEAM);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.SCOREBOARD_SCORE, SCOREBOARD_SCORE);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.SPAWN_POSITION, SPAWN_POSITION);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.UPDATE_TIME, UPDATE_TIME);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.TITLE, TITLE);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.ENTITY_SOUND, ENTITY_SOUND);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.NAMED_SOUND_EFFECT, NAMED_SOUND_EFFECT);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.STOP_SOUND, STOP_SOUND);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.PLAYER_LIST_HEADER_FOOTER, PLAYER_LIST_HEADER_FOOTER);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.NBT_QUERY, NBT_QUERY);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.COLLECT, COLLECT);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.ENTITY_TELEPORT, ENTITY_TELEPORT);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.ADVANCEMENTS, ADVANCEMENTS);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.UPDATE_ATTRIBUTES, UPDATE_ATTRIBUTES);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.ENTITY_EFFECT, ENTITY_EFFECT);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.RECIPE_UPDATE, RECIPE_UPDATE);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.TAGS, TAGS);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.MAP_CHUNK_BULK, MAP_CHUNK_BULK);
|
||||
packetIds.put(PacketTypeClasses.Play.Server.NAMED_ENTITY_SPAWN, NAMED_ENTITY_SPAWN);
|
||||
private static void load() {
|
||||
insertPacketID(PacketTypeClasses.Play.Server.SPAWN_ENTITY, SPAWN_ENTITY);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.SPAWN_ENTITY_EXPERIENCE_ORB, SPAWN_ENTITY_EXPERIENCE_ORB);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.SPAWN_ENTITY_WEATHER, SPAWN_ENTITY_WEATHER);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.SPAWN_ENTITY_LIVING, SPAWN_ENTITY_LIVING);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.SPAWN_ENTITY_PAINTING, SPAWN_ENTITY_PAINTING);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.SPAWN_ENTITY_SPAWN, SPAWN_ENTITY_SPAWN);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.ANIMATION, ANIMATION);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.STATISTIC, STATISTIC);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.BLOCK_BREAK, BLOCK_BREAK);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.BLOCK_BREAK_ANIMATION, BLOCK_BREAK_ANIMATION);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.TILE_ENTITY_DATA, TILE_ENTITY_DATA);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.BLOCK_ACTION, BLOCK_ACTION);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.BLOCK_CHANGE, BLOCK_CHANGE);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.BOSS, BOSS);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.SPAWN_ENTITY, SPAWN_ENTITY);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.SERVER_DIFFICULTY, SERVER_DIFFICULTY);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.CHAT, CHAT);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.MULTI_BLOCK_CHANGE, MULTI_BLOCK_CHANGE);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.TAB_COMPLETE, TAB_COMPLETE);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.COMMANDS, COMMANDS);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.TRANSACTION, TRANSACTION);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.CLOSE_WINDOW, CLOSE_WINDOW);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.WINDOW_ITEMS, WINDOW_ITEMS);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.WINDOW_DATA, WINDOW_DATA);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.SET_SLOT, SET_SLOT);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.SET_COOLDOWN, SET_COOLDOWN);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.CUSTOM_PAYLOAD, CUSTOM_PAYLOAD);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.CUSTOM_SOUND_EFFECT, CUSTOM_SOUND_EFFECT);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.KICK_DISCONNECT, KICK_DISCONNECT);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.ENTITY_STATUS, ENTITY_STATUS);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.EXPLOSION, EXPLOSION);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.UNLOAD_CHUNK, UNLOAD_CHUNK);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.GAME_STATE_CHANGE, GAME_STATE_CHANGE);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.OPEN_WINDOW_HORSE, OPEN_WINDOW_HORSE);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.KEEP_ALIVE, KEEP_ALIVE);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.MAP_CHUNK, MAP_CHUNK);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.WORLD_EVENT, WORLD_EVENT);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.WORLD_EVENT, SPAWN_ENTITY);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.WORLD_PARTICLES, WORLD_PARTICLES);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.LIGHT_UPDATE, LIGHT_UPDATE);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.LOGIN, LOGIN);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.MAP, MAP);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.OPEN_WINDOW_MERCHANT, OPEN_WINDOW_MERCHANT);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.REL_ENTITY_MOVE, REL_ENTITY_MOVE);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.REL_ENTITY_MOVE_LOOK, REL_ENTITY_MOVE_LOOK);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.ENTITY_LOOK, ENTITY_LOOK);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.ENTITY, ENTITY);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.VEHICLE_MOVE, VEHICLE_MOVE);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.OPEN_BOOK, OPEN_BOOK);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.OPEN_WINDOW, OPEN_WINDOW);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.OPEN_SIGN_EDITOR, OPEN_SIGN_EDITOR);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.AUTO_RECIPE, AUTO_RECIPE);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.ABILITIES, ABILITIES);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.COMBAT_EVENT, COMBAT_EVENT);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.PLAYER_INFO, PLAYER_INFO);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.LOOK_AT, LOOK_AT);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.POSITION, POSITION);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.RECIPES, RECIPES);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.ENTITY_DESTROY, ENTITY_DESTROY);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.REMOVE_ENTITY_EFFECT, REMOVE_ENTITY_EFFECT);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.RESOURCE_PACK_SEND, RESOURCE_PACK_SEND);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.RESPAWN, RESPAWN);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.ENTITY_HEAD_ROTATION, ENTITY_HEAD_ROTATION);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.SELECT_ADVANCEMENT_TAB, SELECT_ADVANCEMENT_TAB);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.WORLD_BORDER, WORLD_BORDER);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.CAMERA, CAMERA);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.HELD_ITEM_SLOT, HELD_ITEM_SLOT);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.VIEW_CENTRE, VIEW_CENTRE);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.VIEW_DISTANCE, VIEW_DISTANCE);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.SCOREBOARD_DISPLAY_OBJECTIVE, SCOREBOARD_DISPLAY_OBJECTIVE);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.ENTITY_METADATA, ENTITY_METADATA);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.ATTACH_ENTITY, ATTACH_ENTITY);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.ENTITY_VELOCITY, ENTITY_VELOCITY);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.ENTITY_EQUIPMENT, ENTITY_EQUIPMENT);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.EXPERIENCE, EXPERIENCE);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.UPDATE_HEALTH, UPDATE_HEALTH);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.SCOREBOARD_OBJECTIVE, SCOREBOARD_OBJECTIVE);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.MOUNT, MOUNT);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.SCOREBOARD_TEAM, SCOREBOARD_TEAM);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.SCOREBOARD_SCORE, SCOREBOARD_SCORE);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.SPAWN_POSITION, SPAWN_POSITION);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.UPDATE_TIME, UPDATE_TIME);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.TITLE, TITLE);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.ENTITY_SOUND, ENTITY_SOUND);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.NAMED_SOUND_EFFECT, NAMED_SOUND_EFFECT);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.STOP_SOUND, STOP_SOUND);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.PLAYER_LIST_HEADER_FOOTER, PLAYER_LIST_HEADER_FOOTER);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.NBT_QUERY, NBT_QUERY);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.COLLECT, COLLECT);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.ENTITY_TELEPORT, ENTITY_TELEPORT);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.ADVANCEMENTS, ADVANCEMENTS);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.UPDATE_ATTRIBUTES, UPDATE_ATTRIBUTES);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.ENTITY_EFFECT, ENTITY_EFFECT);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.RECIPE_UPDATE, RECIPE_UPDATE);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.TAGS, TAGS);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.MAP_CHUNK_BULK, MAP_CHUNK_BULK);
|
||||
insertPacketID(PacketTypeClasses.Play.Server.NAMED_ENTITY_SPAWN, NAMED_ENTITY_SPAWN);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,20 +24,24 @@
|
||||
|
||||
package io.github.retrooper.packetevents.packettype;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
import io.github.retrooper.packetevents.utils.reflection.SubclassUtil;
|
||||
import io.github.retrooper.packetevents.utils.server.ServerVersion;
|
||||
|
||||
public class PacketTypeClasses {
|
||||
public static void load() {
|
||||
//PLAY
|
||||
PacketTypeClasses.Play.Client.load();
|
||||
PacketTypeClasses.Play.Server.load();
|
||||
//LOGIN
|
||||
PacketTypeClasses.Login.Client.load();
|
||||
PacketTypeClasses.Login.Server.load();
|
||||
//STATUS
|
||||
PacketTypeClasses.Status.Client.load();
|
||||
PacketTypeClasses.Status.Server.load();
|
||||
//HANDSHAKING
|
||||
PacketTypeClasses.Handshaking.Client.load();
|
||||
//LOGIN
|
||||
PacketTypeClasses.Login.Client.load();
|
||||
PacketTypeClasses.Login.Server.load();
|
||||
//PLAY
|
||||
PacketTypeClasses.Play.Client.load();
|
||||
PacketTypeClasses.Play.Server.load();
|
||||
}
|
||||
|
||||
public static class Status {
|
||||
@@ -47,7 +51,6 @@ public class PacketTypeClasses {
|
||||
public static void load() {
|
||||
Client.START = NMSUtils.getNMSClassWithoutException("PacketStatusInStart");
|
||||
Client.PING = NMSUtils.getNMSClassWithoutException("PacketStatusInPing");
|
||||
PacketType.Status.Client.init();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,22 +60,31 @@ public class PacketTypeClasses {
|
||||
public static void load() {
|
||||
Server.PONG = NMSUtils.getNMSClassWithoutException("PacketStatusOutPong");
|
||||
Server.SERVER_INFO = NMSUtils.getNMSClassWithoutException("PacketStatusOutServerInfo");
|
||||
PacketType.Status.Server.init();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Handshaking {
|
||||
public static class Client {
|
||||
public static Class<?> SET_PROTOCOL;
|
||||
|
||||
public static void load() {
|
||||
Handshaking.Client.SET_PROTOCOL = NMSUtils.getNMSClassWithoutException("PacketHandshakingInSetProtocol");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Login {
|
||||
public static class Client {
|
||||
public static Class<?> HANDSHAKE, CUSTOM_PAYLOAD, START, ENCRYPTION_BEGIN;
|
||||
public static Class<?> CUSTOM_PAYLOAD, START, ENCRYPTION_BEGIN;
|
||||
|
||||
public static void load() {
|
||||
Client.HANDSHAKE = NMSUtils.getNMSClassWithoutException("PacketHandshakingInSetProtocol");
|
||||
//In and Out custom payload login packets have been here since AROUND 1.13.2.
|
||||
Client.CUSTOM_PAYLOAD = NMSUtils.getNMSClassWithoutException("PacketLoginInCustomPayload");
|
||||
//In and Out custom payload login packets have been here since 1.13
|
||||
if (PacketEvents.get().getServerUtils().getVersion().isNewerThanOrEquals(ServerVersion.v_1_13)) {
|
||||
Client.CUSTOM_PAYLOAD = NMSUtils.getNMSClassWithoutException("PacketLoginInCustomPayload");
|
||||
}
|
||||
Client.START = NMSUtils.getNMSClassWithoutException("PacketLoginInStart");
|
||||
Client.ENCRYPTION_BEGIN = NMSUtils.getNMSClassWithoutException("PacketLoginInEncryptionBegin");
|
||||
PacketType.Login.Client.init();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,12 +92,16 @@ public class PacketTypeClasses {
|
||||
public static Class<?> CUSTOM_PAYLOAD, DISCONNECT, ENCRYPTION_BEGIN, SUCCESS, SET_COMPRESSION;
|
||||
|
||||
public static void load() {
|
||||
Server.CUSTOM_PAYLOAD = NMSUtils.getNMSClassWithoutException("PacketLoginOutCustomPayload");
|
||||
//In and Out custom payload login packets have been here since 1.13
|
||||
if (PacketEvents.get().getServerUtils().getVersion().isNewerThanOrEquals(ServerVersion.v_1_13)) {
|
||||
Server.CUSTOM_PAYLOAD = NMSUtils.getNMSClassWithoutException("PacketLoginOutCustomPayload");
|
||||
}
|
||||
Server.DISCONNECT = NMSUtils.getNMSClassWithoutException("PacketLoginOutDisconnect");
|
||||
Server.ENCRYPTION_BEGIN = NMSUtils.getNMSClassWithoutException("PacketLoginOutEncryptionBegin");
|
||||
Server.SUCCESS = NMSUtils.getNMSClassWithoutException("PacketLoginOutSuccess");
|
||||
Server.SET_COMPRESSION = NMSUtils.getNMSClassWithoutException("PacketLoginOutSetCompression");
|
||||
PacketType.Login.Server.init();
|
||||
if (PacketEvents.get().getServerUtils().getVersion().isNewerThan(ServerVersion.v_1_7_10)) {
|
||||
Server.SET_COMPRESSION = NMSUtils.getNMSClassWithoutException("PacketLoginOutSetCompression");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,7 +130,7 @@ public class PacketTypeClasses {
|
||||
POSITION = NMSUtils.getNMSClass(PREFIX + "Position");
|
||||
POSITION_LOOK = NMSUtils.getNMSClass(PREFIX + "PositionLook");
|
||||
LOOK = NMSUtils.getNMSClass(PREFIX + "Look");
|
||||
} catch (ClassNotFoundException e) {
|
||||
} catch (Exception e) {
|
||||
POSITION = SubclassUtil.getSubClass(FLYING, PREFIX + "Position");
|
||||
POSITION_LOOK = SubclassUtil.getSubClass(FLYING, PREFIX + "PositionLook");
|
||||
LOOK = SubclassUtil.getSubClass(FLYING, PREFIX + "Look");
|
||||
@@ -166,17 +182,16 @@ public class PacketTypeClasses {
|
||||
SET_JIGSAW = NMSUtils.getNMSClassWithoutException(PREFIX + "SetJigsaw");
|
||||
STRUCT = NMSUtils.getNMSClassWithoutException(PREFIX + "Struct");
|
||||
SPECTATE = NMSUtils.getNMSClassWithoutException(PREFIX + "Spectate");
|
||||
} catch (ClassNotFoundException e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
BLOCK_PLACE = NMSUtils.getNMSClass(PREFIX + "BlockPlace");
|
||||
USE_ITEM = NMSUtils.getNMSClass(PREFIX + "UseItem");
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
PacketType.Play.Client.init();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,7 +326,6 @@ public class PacketTypeClasses {
|
||||
TAGS = NMSUtils.getNMSClassWithoutException(s + "Tags");
|
||||
MAP_CHUNK_BULK = NMSUtils.getNMSClassWithoutException(s + "MapChunkBulk");
|
||||
NAMED_ENTITY_SPAWN = NMSUtils.getNMSClassWithoutException(s + "NamedEntitySpawn");
|
||||
PacketType.Play.Server.init();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,17 +24,28 @@
|
||||
|
||||
package io.github.retrooper.packetevents.packetwrappers;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.exceptions.WrapperFieldNotFoundException;
|
||||
import io.github.retrooper.packetevents.exceptions.WrapperUnsupportedUsageException;
|
||||
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
|
||||
import io.github.retrooper.packetevents.packetwrappers.api.WrapperPacketReader;
|
||||
import io.github.retrooper.packetevents.packetwrappers.api.WrapperPacketWriter;
|
||||
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
|
||||
import io.github.retrooper.packetevents.utils.reflection.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.server.ServerVersion;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class WrappedPacket implements WrapperPacketReader, WrapperPacketWriter {
|
||||
|
||||
@@ -42,8 +53,8 @@ public class WrappedPacket implements WrapperPacketReader, WrapperPacketWriter {
|
||||
private static final Map<Class<?>, Map<Class<?>, Field[]>> FIELD_CACHE = new ConcurrentHashMap<>();
|
||||
private static final Field[] EMPTY_FIELD_ARRAY = new Field[0];
|
||||
public static ServerVersion version;
|
||||
protected NMSPacket packet;
|
||||
private final Class<?> packetClass;
|
||||
protected final NMSPacket packet;
|
||||
|
||||
public WrappedPacket() {
|
||||
packet = null;
|
||||
@@ -67,9 +78,19 @@ public class WrappedPacket implements WrapperPacketReader, WrapperPacketWriter {
|
||||
}
|
||||
|
||||
private void load0() {
|
||||
if (!isSupported()) {
|
||||
throw new WrapperUnsupportedUsageException(getClass());
|
||||
}
|
||||
final Class<? extends WrappedPacket> clazz = getClass();
|
||||
if (!LOADED_WRAPPERS.containsKey(clazz)) {
|
||||
load();
|
||||
try {
|
||||
load();
|
||||
} catch (Exception ex) {
|
||||
String wrapperName = ClassUtil.getClassSimpleName(getClass());
|
||||
PacketEvents.get().getPlugin().getLogger()
|
||||
.log(Level.SEVERE, "PacketEvents found an exception while loading the " + wrapperName + " packet wrapper. Please report this bug! Tell us about your server version, spigot and code(of you using the wrapper)", ex);
|
||||
LOADED_WRAPPERS.put(clazz, false);
|
||||
}
|
||||
LOADED_WRAPPERS.put(clazz, true);
|
||||
}
|
||||
}
|
||||
@@ -78,6 +99,79 @@ public class WrappedPacket implements WrapperPacketReader, WrapperPacketWriter {
|
||||
|
||||
}
|
||||
|
||||
protected boolean hasLoaded() {
|
||||
return LOADED_WRAPPERS.getOrDefault(getClass(), false);
|
||||
}
|
||||
|
||||
protected void throwUnsupportedOperation(Enum<?> enumConst) throws UnsupportedOperationException {
|
||||
Class<?> enumConstClass = enumConst.getClass();
|
||||
Field field = null;
|
||||
try {
|
||||
field = enumConstClass.getField(enumConst.name());
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (field.isAnnotationPresent(SupportedVersions.class)) {
|
||||
SupportedVersions supportedVersions = field.getAnnotation(SupportedVersions.class);
|
||||
List<ServerVersion> versionList = parseSupportedVersionsAnnotation(supportedVersions);
|
||||
String supportedVersionsMsg = Arrays.toString(versionList.toArray(new ServerVersion[0]));
|
||||
throw new UnsupportedOperationException("PacketEvents failed to use the " + enumConst.name() + " enum constant in the " + enumConstClass.getSimpleName() + " enum. This enum constant is not supported on your server version. (" + PacketEvents.get().getServerUtils().getVersion() + ")\n This enum constant is only supported on these server versions: " + supportedVersionsMsg);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("PacketEvents failed to use the " + enumConst.name() + " enum constant in the " + enumConstClass.getSimpleName() + " enum. This enum constant is not supported on your server version. (" + PacketEvents.get().getServerUtils().getVersion() + ")\n Failed to find out what server versions this enum constant is supported on.");
|
||||
}
|
||||
}
|
||||
|
||||
protected void throwUnsupportedOperation() throws UnsupportedOperationException {
|
||||
final String currentMethodName = "throwUnsupportedOperation";
|
||||
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
|
||||
int stackTraceElementIndex = 2;
|
||||
for (int i = 0; i < stackTraceElements.length; i++) {
|
||||
StackTraceElement element = stackTraceElements[i];
|
||||
if (element.getMethodName().equals(currentMethodName)) {
|
||||
stackTraceElementIndex = i + 1; //It is the next method
|
||||
break;
|
||||
}
|
||||
}
|
||||
StackTraceElement stackTraceElement = stackTraceElements[stackTraceElementIndex];
|
||||
String methodName = stackTraceElement.getMethodName();
|
||||
List<Method> possibleMethods = Reflection.getMethods(getClass(), methodName, null);
|
||||
Method method = null;
|
||||
for (Method m : possibleMethods) {
|
||||
if (m.isAnnotationPresent(SupportedVersions.class)) {
|
||||
method = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (method == null) {
|
||||
throw new UnsupportedOperationException("PacketEvents failed to access your requested field. This field is not supported on your server version. Failed to lookup the server versions this field supports...");
|
||||
} else {
|
||||
SupportedVersions supportedVersions = method.getAnnotation(SupportedVersions.class);
|
||||
List<ServerVersion> versionList = parseSupportedVersionsAnnotation(supportedVersions);
|
||||
|
||||
String supportedVersionsMsg = Arrays.toString(versionList.toArray(new ServerVersion[0]));
|
||||
throw new UnsupportedOperationException("PacketEvents failed to access your requested field. This field is not supported on your server version. (" + PacketEvents.get().getServerUtils().getVersion() + ")\n This field is only supported on these server versions: " + supportedVersionsMsg);
|
||||
}
|
||||
}
|
||||
|
||||
private List<ServerVersion> parseSupportedVersionsAnnotation(SupportedVersions supportedVersions) {
|
||||
List<ServerVersion> versionList = new ArrayList<>();
|
||||
for (int i = 0; i < supportedVersions.ranges().length; i += 2) {
|
||||
ServerVersion first = supportedVersions.ranges()[i];
|
||||
ServerVersion last = supportedVersions.ranges()[i + 1];
|
||||
if (first == last) {
|
||||
versionList.add(first);
|
||||
continue;
|
||||
} else if (first == ServerVersion.ERROR) {
|
||||
first = ServerVersion.getOldest();
|
||||
} else if (last == ServerVersion.ERROR) {
|
||||
last = ServerVersion.getLatest();
|
||||
}
|
||||
versionList.addAll(Arrays.asList(ServerVersion.values()).subList(first.ordinal(), last.ordinal() + 1));
|
||||
}
|
||||
versionList.remove(ServerVersion.ERROR);
|
||||
return versionList;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean readBoolean(int index) {
|
||||
@@ -151,7 +245,7 @@ public class WrappedPacket implements WrapperPacketReader, WrapperPacketWriter {
|
||||
|
||||
@Override
|
||||
public String[] readStringArray(int index) {
|
||||
return read(index, String[].class); // Can we be sure that returning the original array is okay?
|
||||
return read(index, String[].class); // JavaImpact: Can we be sure that returning the original array is okay? retrooper: Yes
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -159,6 +253,7 @@ public class WrappedPacket implements WrapperPacketReader, WrapperPacketWriter {
|
||||
return read(index, String.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object readAnyObject(int index) {
|
||||
try {
|
||||
Field f = packetClass.getDeclaredFields()[index];
|
||||
@@ -176,7 +271,13 @@ public class WrappedPacket implements WrapperPacketReader, WrapperPacketWriter {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object readObject(int index, Class<?> type) {
|
||||
@Override
|
||||
public <T> T readObject(int index, Class<? extends T> type) {
|
||||
return read(index, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum<?> readEnumConstant(int index, Class<? extends Enum<?>> type) {
|
||||
return read(index, type);
|
||||
}
|
||||
|
||||
@@ -185,7 +286,7 @@ public class WrappedPacket implements WrapperPacketReader, WrapperPacketWriter {
|
||||
Field field = getField(type, index);
|
||||
try {
|
||||
return (T) field.get(packet.getRawNMSPacket());
|
||||
} catch (IllegalAccessException | NullPointerException e) {
|
||||
} catch (IllegalAccessException | NullPointerException | ArrayIndexOutOfBoundsException e) {
|
||||
throw new WrapperFieldNotFoundException(packetClass, type, index);
|
||||
}
|
||||
}
|
||||
@@ -235,8 +336,64 @@ public class WrappedPacket implements WrapperPacketReader, WrapperPacketWriter {
|
||||
write(value.getClass(), index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeBooleanArray(int index, boolean[] array) {
|
||||
write(boolean[].class, index, array);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeByteArray(int index, byte[] value) {
|
||||
write(byte[].class, index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeShortArray(int index, short[] value) {
|
||||
write(short[].class, index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeIntArray(int index, int[] value) {
|
||||
write(int[].class, index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeLongArray(int index, long[] value) {
|
||||
write(long[].class, index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeFloatArray(int index, float[] value) {
|
||||
write(float[].class, index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDoubleArray(int index, double[] value) {
|
||||
write(double[].class, index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeStringArray(int index, String[] value) {
|
||||
write(String[].class, index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeAnyObject(int index, Object value) {
|
||||
try {
|
||||
Field f = packetClass.getDeclaredFields()[index];
|
||||
f.set(packet.getRawNMSPacket(), value);
|
||||
} catch (Exception e) {
|
||||
throw new WrapperFieldNotFoundException("PacketEvents failed to find any field indexed " + index + " in the " + ClassUtil.getClassSimpleName(packetClass) + " class!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeEnumConstant(int index, Enum<?> enumConstant) {
|
||||
write(enumConstant.getClass(), index, enumConstant);
|
||||
}
|
||||
|
||||
public void write(Class<?> type, int index, Object value) throws WrapperFieldNotFoundException {
|
||||
Field field = getField(type, index);
|
||||
//Reflection.getFieldWithoutFinalModifier(field);
|
||||
if (field == null) {
|
||||
throw new WrapperFieldNotFoundException(packetClass, type, index);
|
||||
}
|
||||
@@ -248,9 +405,13 @@ public class WrappedPacket implements WrapperPacketReader, WrapperPacketWriter {
|
||||
}
|
||||
|
||||
private Field getField(Class<?> type, int index) {
|
||||
Map<Class<?>, Field[]> cached = FIELD_CACHE.computeIfAbsent(packetClass, k -> new HashMap<>());
|
||||
Map<Class<?>, Field[]> cached = FIELD_CACHE.computeIfAbsent(packetClass, k -> new ConcurrentHashMap<>());
|
||||
Field[] fields = cached.computeIfAbsent(type, typeClass -> getFields(typeClass, packetClass.getDeclaredFields()));
|
||||
return fields[index];
|
||||
if (fields.length >= index + 1) {
|
||||
return fields[index];
|
||||
} else {
|
||||
throw new WrapperFieldNotFoundException(packetClass, type, index);
|
||||
}
|
||||
}
|
||||
|
||||
private Field[] getFields(Class<?> type, Field[] fields) {
|
||||
@@ -266,8 +427,29 @@ public class WrappedPacket implements WrapperPacketReader, WrapperPacketWriter {
|
||||
return ret.toArray(EMPTY_FIELD_ARRAY);
|
||||
}
|
||||
|
||||
// Does the server version support reading/sending this packet?
|
||||
|
||||
/**
|
||||
* Does the local server version support reading at-least one field with this packet wrapper?
|
||||
* If it does, we can label this wrapper to be supported on the local server version.
|
||||
* One example where it would not be supported would be if the packet the wrapper is wrapping doesn't even exist on the local server version.
|
||||
*
|
||||
* @return Is the wrapper supported on the local server version?
|
||||
*/
|
||||
public boolean isSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* If a method in a wrapper is annotated with this, it means it isn't supported on all server versions.
|
||||
* It not being supported by all server versions can lead to exceptions. Make sure you always decompile a wrapper getter before using it.
|
||||
* This annotation will specify what versions are supported.
|
||||
*
|
||||
* @author retrooper
|
||||
* @since 1.8
|
||||
*/
|
||||
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SupportedVersions {
|
||||
ServerVersion[] ranges() default {};
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -22,7 +22,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.retrooper.packetevents.packetwrappers;
|
||||
package io.github.retrooper.packetevents.packetwrappers.api;
|
||||
|
||||
/**
|
||||
* This interface indicates that a packet wrapper supports being sent to a client.
|
||||
+4
-2
@@ -22,7 +22,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.retrooper.packetevents.packetwrappers;
|
||||
package io.github.retrooper.packetevents.packetwrappers.api;
|
||||
|
||||
public interface WrapperPacketReader {
|
||||
|
||||
@@ -58,7 +58,9 @@ public interface WrapperPacketReader {
|
||||
|
||||
String readString(int index);
|
||||
|
||||
Object readObject(int index, Class<?> type);
|
||||
<T> T readObject(int index, Class<? extends T> type);
|
||||
|
||||
Enum<?> readEnumConstant(int index, Class<? extends Enum<?>> type);
|
||||
|
||||
Object readAnyObject(int index);
|
||||
}
|
||||
+22
-3
@@ -22,11 +22,9 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.retrooper.packetevents.packetwrappers;
|
||||
package io.github.retrooper.packetevents.packetwrappers.api;
|
||||
|
||||
public interface WrapperPacketWriter {
|
||||
|
||||
// TODO write for the arrays
|
||||
void writeBoolean(int index, boolean value);
|
||||
|
||||
void writeByte(int index, byte value);
|
||||
@@ -43,5 +41,26 @@ public interface WrapperPacketWriter {
|
||||
|
||||
void writeString(int index, String value);
|
||||
|
||||
//ARRAYS
|
||||
void writeBooleanArray(int index, boolean[] array);
|
||||
|
||||
void writeByteArray(int index, byte[] value);
|
||||
|
||||
void writeShortArray(int index, short[] value);
|
||||
|
||||
void writeIntArray(int index, int[] value);
|
||||
|
||||
void writeLongArray(int index, long[] value);
|
||||
|
||||
void writeFloatArray(int index, float[] value);
|
||||
|
||||
void writeDoubleArray(int index, double[] value);
|
||||
|
||||
void writeStringArray(int index, String[] value);
|
||||
|
||||
void writeObject(int index, Object object);
|
||||
|
||||
void writeAnyObject(int index, Object value);
|
||||
|
||||
void writeEnumConstant(int index, Enum<?> enumConstant);
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package io.github.retrooper.packetevents.packetwrappers.api.helper;
|
||||
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class WrappedPacketEntityAbstraction extends WrappedPacket {
|
||||
private final int entityIDFieldIndex;
|
||||
protected Entity entity;
|
||||
protected int entityID = -1;
|
||||
|
||||
public WrappedPacketEntityAbstraction(NMSPacket packet, int entityIDFieldIndex) {
|
||||
super(packet);
|
||||
this.entityIDFieldIndex = entityIDFieldIndex;
|
||||
}
|
||||
|
||||
public WrappedPacketEntityAbstraction(NMSPacket packet) {
|
||||
super(packet);
|
||||
this.entityIDFieldIndex = 0;
|
||||
}
|
||||
|
||||
public WrappedPacketEntityAbstraction(int entityIDFieldIndex) {
|
||||
super();
|
||||
this.entityIDFieldIndex = entityIDFieldIndex;
|
||||
}
|
||||
|
||||
public WrappedPacketEntityAbstraction() {
|
||||
super();
|
||||
this.entityIDFieldIndex = 0;
|
||||
}
|
||||
|
||||
public int getEntityId() {
|
||||
if (entityID != -1 || packet == null) {
|
||||
return entityID;
|
||||
}
|
||||
return entityID = readInt(entityIDFieldIndex);
|
||||
}
|
||||
|
||||
public void setEntityId(int entityID) {
|
||||
if (packet != null) {
|
||||
writeInt(entityIDFieldIndex, this.entityID = entityID);
|
||||
} else {
|
||||
this.entityID = entityID;
|
||||
}
|
||||
this.entity = null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Entity getEntity(@Nullable World world) {
|
||||
if (entity != null) {
|
||||
return entity;
|
||||
}
|
||||
return entity = NMSUtils.getEntityById(world, getEntityId());
|
||||
}
|
||||
|
||||
public Entity getEntity() {
|
||||
return getEntity(null);
|
||||
}
|
||||
|
||||
public void setEntity(@NotNull Entity entity) {
|
||||
setEntityId(entity.getEntityId());
|
||||
this.entity = entity;
|
||||
}
|
||||
}
|
||||
+16
-9
@@ -22,14 +22,14 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.retrooper.packetevents.packetwrappers.login.in.handshake;
|
||||
package io.github.retrooper.packetevents.packetwrappers.handshaking.setprotocol;
|
||||
|
||||
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
|
||||
public class WrappedPacketLoginInHandshake extends WrappedPacket {
|
||||
public WrappedPacketLoginInHandshake(NMSPacket packet) {
|
||||
public class WrappedPacketHandshakingInSetProtocol extends WrappedPacket {
|
||||
|
||||
public WrappedPacketHandshakingInSetProtocol(NMSPacket packet) {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
@@ -37,16 +37,23 @@ public class WrappedPacketLoginInHandshake extends WrappedPacket {
|
||||
return readInt(0);
|
||||
}
|
||||
|
||||
public String getHostName() {
|
||||
return readString(0);
|
||||
public void setProtocolVersion(int protocolVersion) {
|
||||
writeInt(0, protocolVersion);
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return readInt(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported() {
|
||||
return PacketTypeClasses.Login.Client.HANDSHAKE != null;
|
||||
public void setPort(int port) {
|
||||
writeInt(1, port);
|
||||
}
|
||||
|
||||
public String getHostName() {
|
||||
return readString(0);
|
||||
}
|
||||
|
||||
public void setHostName(String hostName) {
|
||||
writeString(0, hostName);
|
||||
}
|
||||
}
|
||||
+24
-18
@@ -30,35 +30,41 @@ import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
import io.github.retrooper.packetevents.utils.server.ServerVersion;
|
||||
|
||||
/**
|
||||
* This packet exists since 1.13
|
||||
*/
|
||||
public class WrappedPacketLoginInCustomPayload extends WrappedPacket {
|
||||
private static Class<?> byteBufClass;
|
||||
private static Class<?> packetDataSerializerClass;
|
||||
|
||||
public WrappedPacketLoginInCustomPayload(NMSPacket packet) {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void load() {
|
||||
packetDataSerializerClass = NMSUtils.getNMSClassWithoutException("PacketDataSerializer");
|
||||
try {
|
||||
byteBufClass = NMSUtils.getNettyClass("buffer.ByteBuf");
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
public int getMessageId() {
|
||||
return readInt(0);
|
||||
}
|
||||
|
||||
public void setMessageId(int id) {
|
||||
writeInt(0, id);
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
Object dataSerializer = readObject(0, packetDataSerializerClass);
|
||||
return PacketEvents.get().getByteBufUtil().getBytes(getBuffer());
|
||||
}
|
||||
|
||||
public void setData(byte[] data) {
|
||||
Object dataSerializer = readObject(0, NMSUtils.packetDataSerializerClass);
|
||||
WrappedPacket dataSerializerWrapper = new WrappedPacket(new NMSPacket(dataSerializer));
|
||||
PacketEvents.get().getByteBufUtil().setBytes(getBuffer(), data);
|
||||
}
|
||||
|
||||
private Object getBuffer() {
|
||||
Object dataSerializer = readObject(0, NMSUtils.packetDataSerializerClass);
|
||||
WrappedPacket byteBufWrapper = new WrappedPacket(new NMSPacket(dataSerializer));
|
||||
Object byteBuf = byteBufWrapper.readObject(0, byteBufClass);
|
||||
return PacketEvents.get().getByteBufUtil().getBytes(byteBuf);
|
||||
return byteBufWrapper.readObject(0, NMSUtils.byteBufClass);
|
||||
}
|
||||
|
||||
public void retain() {
|
||||
PacketEvents.get().getByteBufUtil().retain(getBuffer());
|
||||
}
|
||||
|
||||
public void release() {
|
||||
PacketEvents.get().getByteBufUtil().release(getBuffer());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+8
@@ -37,10 +37,18 @@ public class WrappedPacketLoginInEncryptionBegin extends WrappedPacket {
|
||||
return readByteArray(0);
|
||||
}
|
||||
|
||||
public void setPublicKey(byte[] key) {
|
||||
writeByteArray(0, key);
|
||||
}
|
||||
|
||||
public byte[] getVerifyToken() {
|
||||
return readByteArray(1);
|
||||
}
|
||||
|
||||
public void setVerifyToken(byte[] token) {
|
||||
writeByteArray(1, token);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported() {
|
||||
return PacketTypeClasses.Login.Client.ENCRYPTION_BEGIN != null;
|
||||
|
||||
+5
@@ -40,6 +40,11 @@ public class WrappedPacketLoginInStart extends WrappedPacket {
|
||||
return GameProfileUtil.getWrappedGameProfile(readObject(0, NMSUtils.gameProfileClass));
|
||||
}
|
||||
|
||||
public void setGameProfile(WrappedGameProfile wrappedGameProfile) {
|
||||
Object gameProfile = GameProfileUtil.getGameProfile(wrappedGameProfile.getId(), wrappedGameProfile.getName());
|
||||
write(NMSUtils.gameProfileClass, 0, gameProfile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported() {
|
||||
return PacketTypeClasses.Login.Client.START != null;
|
||||
|
||||
+34
-16
@@ -27,7 +27,7 @@ package io.github.retrooper.packetevents.packetwrappers.login.out.custompayload;
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.SendableWrapper;
|
||||
import io.github.retrooper.packetevents.packetwrappers.api.SendableWrapper;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
|
||||
@@ -37,8 +37,6 @@ import java.lang.reflect.InvocationTargetException;
|
||||
public class WrappedPacketLoginOutCustomPayload extends WrappedPacket implements SendableWrapper {
|
||||
private static Constructor<?> constructor;
|
||||
private static Constructor<?> packetDataSerializerConstructor;
|
||||
private static Class<?> byteBufClass;
|
||||
private static Class<?> packetDataSerializerClass;
|
||||
private int messageID;
|
||||
private String channelName;
|
||||
private byte[] data;
|
||||
@@ -51,16 +49,9 @@ public class WrappedPacketLoginOutCustomPayload extends WrappedPacket implements
|
||||
protected void load() {
|
||||
Class<?> packetClass = PacketTypeClasses.Login.Server.CUSTOM_PAYLOAD;
|
||||
if (packetClass != null) {
|
||||
packetDataSerializerClass = NMSUtils.getNMSClassWithoutException("PacketDataSerializer");
|
||||
try {
|
||||
byteBufClass = NMSUtils.getNettyClass("buffer.ByteBuf");
|
||||
} catch (ClassNotFoundException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
if (packetDataSerializerClass != null) {
|
||||
packetDataSerializerConstructor = packetDataSerializerClass.getConstructor(byteBufClass);
|
||||
if (NMSUtils.packetDataSerializerClass != null) {
|
||||
packetDataSerializerConstructor = NMSUtils.packetDataSerializerClass.getConstructor(NMSUtils.byteBufClass);
|
||||
}
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
@@ -81,27 +72,54 @@ public class WrappedPacketLoginOutCustomPayload extends WrappedPacket implements
|
||||
return messageID;
|
||||
}
|
||||
|
||||
public void setMessageId(int messageID) {
|
||||
if (packet != null) {
|
||||
writeInt(0, messageID);
|
||||
} else {
|
||||
this.messageID = messageID;
|
||||
}
|
||||
}
|
||||
|
||||
public String getChannelName() {
|
||||
if (packet != null) {
|
||||
Object minecraftKey = readObject(0, NMSUtils.minecraftKeyClass);
|
||||
return NMSUtils.getStringFromMinecraftKey(minecraftKey);
|
||||
return NMSUtils.getStringFromMinecraftKey(minecraftKey);
|
||||
}
|
||||
return channelName;
|
||||
}
|
||||
|
||||
public void setChannelName(String channelName) {
|
||||
if (packet != null) {
|
||||
Object minecraftKey = NMSUtils.generateMinecraftKey(channelName);
|
||||
writeObject(0, minecraftKey);
|
||||
} else {
|
||||
this.channelName = channelName;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
if (packet != null) {
|
||||
Object dataSerializer = readObject(0, packetDataSerializerClass);
|
||||
Object dataSerializer = readObject(0, NMSUtils.packetDataSerializerClass);
|
||||
WrappedPacket byteBufWrapper = new WrappedPacket(new NMSPacket(dataSerializer));
|
||||
Object byteBuf = byteBufWrapper.readObject(0, byteBufClass);
|
||||
Object byteBuf = byteBufWrapper.readObject(0, NMSUtils.byteBufClass);
|
||||
return PacketEvents.get().getByteBufUtil().getBytes(byteBuf);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(byte[] data) {
|
||||
PacketEvents.get().getByteBufUtil().setBytes(getBuffer(), data);
|
||||
}
|
||||
|
||||
private Object getBuffer() {
|
||||
Object dataSerializer = readObject(0, NMSUtils.packetDataSerializerClass);
|
||||
WrappedPacket byteBufWrapper = new WrappedPacket(new NMSPacket(dataSerializer));
|
||||
return byteBufWrapper.readObject(0, NMSUtils.byteBufClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object asNMSPacket() {
|
||||
Object byteBufObject = PacketEvents.get().getByteBufUtil().wrappedBuffer(data);
|
||||
Object byteBufObject = PacketEvents.get().getByteBufUtil().newByteBuf(data);
|
||||
try {
|
||||
Object minecraftKey = NMSUtils.generateMinecraftKey(channelName);
|
||||
Object dataSerializer = packetDataSerializerConstructor.newInstance(byteBufObject);
|
||||
|
||||
+6
-2
@@ -27,7 +27,6 @@ package io.github.retrooper.packetevents.packetwrappers.login.out.disconnect;
|
||||
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.play.out.chat.WrappedPacketOutChat;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
|
||||
public class WrappedPacketLoginOutDisconnect extends WrappedPacket {
|
||||
@@ -37,7 +36,12 @@ public class WrappedPacketLoginOutDisconnect extends WrappedPacket {
|
||||
|
||||
public String getReason() {
|
||||
Object iChatBaseComponent = readObject(0, NMSUtils.iChatBaseComponentClass);
|
||||
return WrappedPacketOutChat.toStringFromIChatBaseComponent(iChatBaseComponent);
|
||||
return NMSUtils.readIChatBaseComponent(iChatBaseComponent);
|
||||
}
|
||||
|
||||
public void setReason(String reason) {
|
||||
Object iChatBaseComponent = NMSUtils.generateIChatBaseComponent(reason);
|
||||
writeObject(0, iChatBaseComponent);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+15
-3
@@ -39,14 +39,26 @@ public class WrappedPacketLoginOutEncryptionBegin extends WrappedPacket {
|
||||
return readString(0);
|
||||
}
|
||||
|
||||
public PublicKey getPublicKey() {
|
||||
return (PublicKey) readObject(1, PublicKey.class);
|
||||
public void setEncodedString(String encodedString) {
|
||||
writeString(0, encodedString);
|
||||
}
|
||||
|
||||
public byte[] getByteArray() {
|
||||
public PublicKey getPublicKey() {
|
||||
return readObject(1, PublicKey.class);
|
||||
}
|
||||
|
||||
public void setPublicKey(PublicKey key) {
|
||||
writeObject(0, key);
|
||||
}
|
||||
|
||||
public byte[] getVerifyToken() {
|
||||
return readByteArray(0);
|
||||
}
|
||||
|
||||
public void setVerifyToken(byte[] verifyToken) {
|
||||
writeByteArray(0, verifyToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported() {
|
||||
return PacketTypeClasses.Login.Server.ENCRYPTION_BEGIN != null;
|
||||
|
||||
+12
-3
@@ -26,8 +26,9 @@ package io.github.retrooper.packetevents.packetwrappers.login.out.setcompression
|
||||
|
||||
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.SendableWrapper;
|
||||
import io.github.retrooper.packetevents.packetwrappers.api.SendableWrapper;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.server.ServerVersion;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
@@ -68,10 +69,18 @@ public class WrappedPacketLoginOutSetCompression extends WrappedPacket implement
|
||||
return threshold;
|
||||
}
|
||||
|
||||
public void setThreshold(int threshold) {
|
||||
if (packet != null) {
|
||||
writeInt(0, threshold);
|
||||
} else {
|
||||
this.threshold = threshold;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object asNMSPacket() {
|
||||
try {
|
||||
return constructor.newInstance(threshold);
|
||||
return constructor.newInstance(getThreshold());
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -80,6 +89,6 @@ public class WrappedPacketLoginOutSetCompression extends WrappedPacket implement
|
||||
|
||||
@Override
|
||||
public boolean isSupported() {
|
||||
return PacketTypeClasses.Login.Server.SET_COMPRESSION != null;
|
||||
return version.isNewerThan(ServerVersion.v_1_7_10);
|
||||
}
|
||||
}
|
||||
+6
@@ -40,6 +40,12 @@ public class WrappedPacketLoginOutSuccess extends WrappedPacket {
|
||||
return GameProfileUtil.getWrappedGameProfile(readObject(0, NMSUtils.gameProfileClass));
|
||||
}
|
||||
|
||||
|
||||
public void setGameProfile(WrappedGameProfile wrappedGameProfile) {
|
||||
Object gameProfile = GameProfileUtil.getGameProfile(wrappedGameProfile.getId(), wrappedGameProfile.getName());
|
||||
write(NMSUtils.gameProfileClass, 0, gameProfile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported() {
|
||||
return PacketTypeClasses.Login.Server.SUCCESS != null;
|
||||
|
||||
+60
-52
@@ -28,6 +28,9 @@ import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.reflection.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.server.ServerVersion;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public final class WrappedPacketInAbilities extends WrappedPacket {
|
||||
private static boolean v_1_16_Mode;
|
||||
@@ -41,72 +44,77 @@ public final class WrappedPacketInAbilities extends WrappedPacket {
|
||||
v_1_16_Mode = Reflection.getField(PacketTypeClasses.Play.Client.ABILITIES, boolean.class, 1) == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This will return null if the server version is not available in 1.16.x and above
|
||||
*
|
||||
* @return Whether the player is vulnerable to damage or not.
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isVulnerable() throws UnsupportedOperationException {
|
||||
if (v_1_16_Mode) {
|
||||
throw new UnsupportedOperationException("This field does not exist on your version!");
|
||||
}
|
||||
return readBoolean(0);
|
||||
}
|
||||
|
||||
public boolean isFlying() {
|
||||
return readBoolean(v_1_16_Mode ? 0 : 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will return null if the server version is not available in 1.16.x and above
|
||||
*
|
||||
* @return Whether or not the player can fly.
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isFlightAllowed() {
|
||||
if (v_1_16_Mode) {
|
||||
throw new UnsupportedOperationException("This field does not exist on your version!");
|
||||
}
|
||||
return readBoolean(2);
|
||||
public void setFlying(boolean flying) {
|
||||
writeBoolean(v_1_16_Mode ? 0 : 1, flying);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will return null if the server version is not available in 1.16.x and above
|
||||
*
|
||||
* @return Whether or not the player can break blocks instantly.
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean canInstantlyBuild() {
|
||||
public Optional<Boolean> isVulnerable() {
|
||||
if (v_1_16_Mode) {
|
||||
throw new UnsupportedOperationException("This field does not exist on your version!");
|
||||
return Optional.empty();
|
||||
}
|
||||
return readBoolean(3);
|
||||
return Optional.of(readBoolean(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* This will return null if the server version is not available in 1.16.x and above
|
||||
*
|
||||
* @return The speed at which the player can fly, as a float.
|
||||
*/
|
||||
@Deprecated
|
||||
public float getFlySpeed() {
|
||||
if (v_1_16_Mode) {
|
||||
throw new UnsupportedOperationException("This field does not exist on your version!");
|
||||
public void setVulnerable(boolean vulnerable) {
|
||||
if (!v_1_16_Mode) {
|
||||
writeBoolean(0, vulnerable);
|
||||
}
|
||||
return readFloat(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will return null if the server version is not available in 1.16.x and above
|
||||
*
|
||||
* @return The speed at which the player can walk, as a float.
|
||||
*/
|
||||
@Deprecated
|
||||
public float getWalkSpeed() {
|
||||
|
||||
public Optional<Boolean> isFlightAllowed() {
|
||||
if (v_1_16_Mode) {
|
||||
throw new UnsupportedOperationException("This field does not exist on your version!");
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.of(readBoolean(2));
|
||||
}
|
||||
|
||||
public void setFlightAllowed(boolean flightAllowed) {
|
||||
if (!v_1_16_Mode) {
|
||||
writeBoolean(2, flightAllowed);
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<Boolean> canInstantlyBuild() {
|
||||
if (v_1_16_Mode) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.of(readBoolean(3));
|
||||
}
|
||||
|
||||
public void setCanInstantlyBuild(boolean canInstantlyBuild) {
|
||||
if (!v_1_16_Mode) {
|
||||
writeBoolean(3, canInstantlyBuild);
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<Float> getFlySpeed() {
|
||||
if (v_1_16_Mode) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.of(readFloat(0));
|
||||
}
|
||||
|
||||
public void setFlySpeed(float flySpeed) {
|
||||
if (!v_1_16_Mode) {
|
||||
writeFloat(0, flySpeed);
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<Float> getWalkSpeed() {
|
||||
if (v_1_16_Mode) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.of(readFloat(1));
|
||||
}
|
||||
|
||||
public void setWalkSpeed(float walkSpeed) {
|
||||
if (!v_1_16_Mode) {
|
||||
writeFloat(1, walkSpeed);
|
||||
}
|
||||
return readFloat(1);
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package io.github.retrooper.packetevents.packetwrappers.play.in.armanimation;
|
||||
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.enums.EnumUtil;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
import io.github.retrooper.packetevents.utils.player.Hand;
|
||||
import io.github.retrooper.packetevents.utils.server.ServerVersion;
|
||||
|
||||
public class WrappedPacketInArmAnimation extends WrappedPacket {
|
||||
public WrappedPacketInArmAnimation(NMSPacket packet) {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
public Hand getHand() {
|
||||
if (version.isOlderThan(ServerVersion.v_1_9)) {
|
||||
return Hand.MAIN_HAND;
|
||||
} else {
|
||||
Enum<?> enumConst = readEnumConstant(0, NMSUtils.enumHandClass);
|
||||
return Hand.valueOf(enumConst.name());
|
||||
}
|
||||
}
|
||||
|
||||
public void setHand(Hand hand) {
|
||||
//Optimize to do nothing on legacy versions. The protocol of the legacy versions only support one hand, the main hand.
|
||||
if (version.isNewerThan(ServerVersion.v_1_8_8)) {
|
||||
Enum<?> enumConst = EnumUtil.valueOf(NMSUtils.enumHandClass, hand.name());
|
||||
write(NMSUtils.enumHandClass, 0, enumConst);
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -12,7 +12,15 @@ public class WrappedPacketInBeacon extends WrappedPacket {
|
||||
return readInt(0);
|
||||
}
|
||||
|
||||
public void setPrimaryEffect(int primaryEffect) {
|
||||
writeInt(0, primaryEffect);
|
||||
}
|
||||
|
||||
public int getSecondaryEffect() {
|
||||
return readInt(1);
|
||||
}
|
||||
|
||||
public void setSecondaryEffect(int secondaryEffect) {
|
||||
writeInt(1, secondaryEffect);
|
||||
}
|
||||
}
|
||||
+52
-76
@@ -27,22 +27,18 @@ package io.github.retrooper.packetevents.packetwrappers.play.in.blockdig;
|
||||
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.enums.EnumUtil;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
import io.github.retrooper.packetevents.utils.player.Direction;
|
||||
import io.github.retrooper.packetevents.utils.reflection.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.reflection.SubclassUtil;
|
||||
import io.github.retrooper.packetevents.utils.server.ServerVersion;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import io.github.retrooper.packetevents.utils.vector.Vector3i;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public final class WrappedPacketInBlockDig extends WrappedPacket {
|
||||
private static Class<?> blockPositionClass;
|
||||
private static Class<?> enumDirectionClass;
|
||||
private static Class<?> digTypeClass;
|
||||
private static Class<? extends Enum<?>> digTypeClass;
|
||||
private static boolean isVersionLowerThan_v_1_8;
|
||||
private Object blockPosObj;
|
||||
private Object enumDirObj;
|
||||
|
||||
public WrappedPacketInBlockDig(NMSPacket packet) {
|
||||
super(packet);
|
||||
@@ -51,86 +47,47 @@ public final class WrappedPacketInBlockDig extends WrappedPacket {
|
||||
@Override
|
||||
protected void load() {
|
||||
Class<?> blockDigClass = PacketTypeClasses.Play.Client.BLOCK_DIG;
|
||||
try {
|
||||
if (version.isNewerThan(ServerVersion.v_1_7_10)) {
|
||||
blockPositionClass = NMSUtils.getNMSClass("BlockPosition");
|
||||
enumDirectionClass = NMSUtils.getNMSClass("EnumDirection");
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
isVersionLowerThan_v_1_8 = version.isOlderThan(ServerVersion.v_1_8);
|
||||
|
||||
if (version != ServerVersion.v_1_7_10) {
|
||||
try {
|
||||
digTypeClass = NMSUtils.getNMSClass("EnumPlayerDigType");
|
||||
digTypeClass = NMSUtils.getNMSEnumClass("EnumPlayerDigType");
|
||||
} catch (ClassNotFoundException e) {
|
||||
//It is probably a subclass
|
||||
digTypeClass = SubclassUtil.getSubClass(blockDigClass, "EnumPlayerDigType");
|
||||
digTypeClass = SubclassUtil.getEnumSubClass(blockDigClass, "EnumPlayerDigType");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get X position of the block
|
||||
*
|
||||
* @return Block Position X
|
||||
*/
|
||||
public int getX() {
|
||||
public Vector3i getBlockPosition() {
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int z = 0;
|
||||
if (isVersionLowerThan_v_1_8) {
|
||||
return readInt(0);
|
||||
x = readInt(0);
|
||||
y = readInt(1);
|
||||
z = readInt(2);
|
||||
} else {
|
||||
if (blockPosObj == null) {
|
||||
blockPosObj = readObject(0, blockPositionClass);
|
||||
}
|
||||
Object blockPosObj = readObject(0, NMSUtils.blockPosClass);
|
||||
try {
|
||||
return (int) Reflection.getMethod(blockPosObj.getClass().getSuperclass(), "getX", 0).invoke(blockPosObj);
|
||||
x = (int) NMSUtils.getBlockPosX.invoke(blockPosObj);
|
||||
y = (int) NMSUtils.getBlockPosY.invoke(blockPosObj);
|
||||
z = (int) NMSUtils.getBlockPosZ.invoke(blockPosObj);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return new Vector3i(x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Y position of the block
|
||||
*
|
||||
* @return Block Position Y
|
||||
*/
|
||||
public int getY() {
|
||||
public void setBlockPosition(Vector3i blockPos) {
|
||||
if (isVersionLowerThan_v_1_8) {
|
||||
return readInt(1);
|
||||
writeInt(0, blockPos.x);
|
||||
writeInt(1, blockPos.y);
|
||||
writeInt(2, blockPos.z);
|
||||
} else {
|
||||
if (blockPosObj == null) {
|
||||
blockPosObj = readObject(0, blockPositionClass);
|
||||
}
|
||||
try {
|
||||
return (int) Reflection.getMethod(blockPosObj.getClass().getSuperclass(), "getY", 0).invoke(blockPosObj);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Z position of the block
|
||||
*
|
||||
* @return Block Position Z
|
||||
*/
|
||||
public int getZ() {
|
||||
if (isVersionLowerThan_v_1_8) {
|
||||
return readInt(2);
|
||||
} else {
|
||||
if (blockPosObj == null) {
|
||||
blockPosObj = readObject(0, blockPositionClass);
|
||||
}
|
||||
try {
|
||||
return (int) Reflection.getMethod(blockPosObj.getClass().getSuperclass(), "getZ", 0).invoke(blockPosObj);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return -1;
|
||||
Object blockPosObj = NMSUtils.generateNMSBlockPos(blockPos.x, blockPos.y, blockPos.z);
|
||||
write(NMSUtils.blockPosClass, 0, blockPosObj);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,17 +96,21 @@ public final class WrappedPacketInBlockDig extends WrappedPacket {
|
||||
*
|
||||
* @return Direction
|
||||
*/
|
||||
public byte getDirection() {
|
||||
public Direction getDirection() {
|
||||
if (isVersionLowerThan_v_1_8) {
|
||||
return(byte) readInt(3);
|
||||
return Direction.getDirection(readInt(3));
|
||||
} else {
|
||||
if (enumDirObj == null) {
|
||||
enumDirObj = readObject(0, enumDirectionClass);
|
||||
if (enumDirObj == null) {
|
||||
return -1; //errorr
|
||||
}
|
||||
}
|
||||
return Direction.getByName(((Enum) enumDirObj).name());
|
||||
Enum<?> enumDir = readEnumConstant(0, NMSUtils.enumDirectionClass);
|
||||
return Direction.valueOf(enumDir.name());
|
||||
}
|
||||
}
|
||||
|
||||
public void setDirection(Direction direction) {
|
||||
if (isVersionLowerThan_v_1_8) {
|
||||
writeInt(3, direction.getFaceValue());
|
||||
} else {
|
||||
Enum<?> enumConst = EnumUtil.valueOf(NMSUtils.enumDirectionClass, direction.name());
|
||||
write(NMSUtils.enumDirectionClass, 0, enumConst);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +123,16 @@ public final class WrappedPacketInBlockDig extends WrappedPacket {
|
||||
if (isVersionLowerThan_v_1_8) {
|
||||
return PlayerDigType.values()[readInt(4)];
|
||||
} else {
|
||||
return PlayerDigType.valueOf(((Enum) readObject(0, digTypeClass)).name());
|
||||
return PlayerDigType.valueOf(readObject(0, digTypeClass).name());
|
||||
}
|
||||
}
|
||||
|
||||
public void setDigType(PlayerDigType type) {
|
||||
if (isVersionLowerThan_v_1_8) {
|
||||
writeInt(4, type.ordinal());
|
||||
} else {
|
||||
Enum<?> enumConst = EnumUtil.valueOf(digTypeClass, type.name());
|
||||
write(digTypeClass, 0, enumConst);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,7 +143,13 @@ public final class WrappedPacketInBlockDig extends WrappedPacket {
|
||||
DROP_ALL_ITEMS,
|
||||
DROP_ITEM,
|
||||
RELEASE_USE_ITEM,
|
||||
|
||||
/**
|
||||
* Doesn't exist on the newest versions.
|
||||
*/
|
||||
@Deprecated
|
||||
SWAP_HELD_ITEMS,
|
||||
|
||||
SWAP_ITEM_WITH_OFFHAND,
|
||||
UNKNOWN
|
||||
}
|
||||
|
||||
+112
-44
@@ -26,12 +26,21 @@ package io.github.retrooper.packetevents.packetwrappers.play.in.blockplace;
|
||||
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.enums.EnumUtil;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
import io.github.retrooper.packetevents.utils.player.Direction;
|
||||
import io.github.retrooper.packetevents.utils.player.Hand;
|
||||
import io.github.retrooper.packetevents.utils.server.ServerVersion;
|
||||
import io.github.retrooper.packetevents.utils.vector.Vector3f;
|
||||
import io.github.retrooper.packetevents.utils.vector.Vector3i;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
|
||||
public final class WrappedPacketInBlockPlace extends WrappedPacket {
|
||||
private static boolean isHigherThan_v_1_8_8, isHigherThan_v_1_7_10;
|
||||
private static boolean newerThan_v_1_8_8, newerThan_v_1_7_10;
|
||||
private static int handEnumIndex;
|
||||
|
||||
public WrappedPacketInBlockPlace(final NMSPacket packet) {
|
||||
super(packet);
|
||||
@@ -39,61 +48,120 @@ public final class WrappedPacketInBlockPlace extends WrappedPacket {
|
||||
|
||||
@Override
|
||||
protected void load() {
|
||||
isHigherThan_v_1_8_8 = version.isNewerThan(ServerVersion.v_1_8_8);
|
||||
isHigherThan_v_1_7_10 = version.isNewerThan(ServerVersion.v_1_7_10);
|
||||
}
|
||||
|
||||
public byte getDirection() {
|
||||
if (isHigherThan_v_1_8_8) {
|
||||
WrappedPacketInBlockPlace_1_9 blockPlace_1_9 = new WrappedPacketInBlockPlace_1_9(packet);
|
||||
return Direction.getByName(((Enum) blockPlace_1_9.getEnumDirectionObject()).name());
|
||||
} else if (isHigherThan_v_1_7_10) {
|
||||
WrappedPacketInBlockPlace_1_8 blockPlace_1_8 = new WrappedPacketInBlockPlace_1_8(packet);
|
||||
return (byte) blockPlace_1_8.getFace();
|
||||
} else {
|
||||
WrappedPacketInBlockPlace_1_7_10 blockPlace_1_7_10 = new WrappedPacketInBlockPlace_1_7_10(packet);
|
||||
return (byte) blockPlace_1_7_10.face;
|
||||
newerThan_v_1_7_10 = version.isNewerThan(ServerVersion.v_1_7_10);
|
||||
newerThan_v_1_8_8 = version.isNewerThan(ServerVersion.v_1_8_8);
|
||||
try {
|
||||
Object handEnum = readObject(1, NMSUtils.enumHandClass);
|
||||
handEnumIndex = 1;
|
||||
} catch (Exception ex) {
|
||||
handEnumIndex = 0;//Most likely a newer version
|
||||
}
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
if (isHigherThan_v_1_8_8) {
|
||||
WrappedPacketInBlockPlace_1_9 blockPlace_1_9 = new WrappedPacketInBlockPlace_1_9(packet);
|
||||
return blockPlace_1_9.getX();
|
||||
} else if (isHigherThan_v_1_7_10) {
|
||||
WrappedPacketInBlockPlace_1_8 blockPlace_1_8 = new WrappedPacketInBlockPlace_1_8(packet);
|
||||
return blockPlace_1_8.getX();
|
||||
public Hand getHand() {
|
||||
if (version.isOlderThan(ServerVersion.v_1_9)) {
|
||||
return Hand.MAIN_HAND;
|
||||
} else {
|
||||
WrappedPacketInBlockPlace_1_7_10 blockPlace_1_7_10 = new WrappedPacketInBlockPlace_1_7_10(packet);
|
||||
return blockPlace_1_7_10.x;
|
||||
Enum<?> enumConst = readEnumConstant(handEnumIndex, NMSUtils.enumHandClass);
|
||||
return Hand.valueOf(enumConst.name());
|
||||
}
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
if (isHigherThan_v_1_8_8) {
|
||||
WrappedPacketInBlockPlace_1_9 blockPlace_1_9 = new WrappedPacketInBlockPlace_1_9(packet);
|
||||
return blockPlace_1_9.getY();
|
||||
|
||||
} else if (isHigherThan_v_1_7_10) {
|
||||
WrappedPacketInBlockPlace_1_8 blockPlace_1_8 = new WrappedPacketInBlockPlace_1_8(packet);
|
||||
return blockPlace_1_8.getY();
|
||||
} else {
|
||||
WrappedPacketInBlockPlace_1_7_10 blockPlace_1_7_10 = new WrappedPacketInBlockPlace_1_7_10(packet);
|
||||
return blockPlace_1_7_10.y;
|
||||
public void setHand(Hand hand) {
|
||||
//Optimize to do nothing on legacy versions. The protocol of the legacy versions only support one hand, the main hand.
|
||||
if (version.isNewerThan(ServerVersion.v_1_8_8)) {
|
||||
Enum<?> enumConst = EnumUtil.valueOf(NMSUtils.enumHandClass, hand.name());
|
||||
write(NMSUtils.enumHandClass, handEnumIndex, enumConst);
|
||||
}
|
||||
}
|
||||
|
||||
public int getZ() {
|
||||
if (isHigherThan_v_1_8_8) {
|
||||
WrappedPacketInBlockPlace_1_9 blockPlace_1_9 = new WrappedPacketInBlockPlace_1_9(packet);
|
||||
return blockPlace_1_9.getZ();
|
||||
} else if (isHigherThan_v_1_7_10) {
|
||||
WrappedPacketInBlockPlace_1_8 blockPlace_1_8 = new WrappedPacketInBlockPlace_1_8(packet);
|
||||
return blockPlace_1_8.getZ();
|
||||
public Direction getDirection() {
|
||||
if (newerThan_v_1_8_8) {
|
||||
WrappedPacketInBlockPlace_1_9 blockPlace_1_9 = new WrappedPacketInBlockPlace_1_9(new NMSPacket(packet.getRawNMSPacket()));
|
||||
return blockPlace_1_9.getDirection();
|
||||
} else if (newerThan_v_1_7_10) {
|
||||
WrappedPacketInBlockPlace_1_8 blockPlace_1_8 = new WrappedPacketInBlockPlace_1_8(new NMSPacket(packet.getRawNMSPacket()));
|
||||
return Direction.getDirection(blockPlace_1_8.getFace());
|
||||
} else {
|
||||
WrappedPacketInBlockPlace_1_7_10 blockPlace_1_7_10 = new WrappedPacketInBlockPlace_1_7_10(packet);
|
||||
return blockPlace_1_7_10.z;
|
||||
WrappedPacketInBlockPlace_1_7_10 blockPlace_1_7_10 = new WrappedPacketInBlockPlace_1_7_10(new NMSPacket(packet.getRawNMSPacket()));
|
||||
return Direction.getDirection(blockPlace_1_7_10.getFace());
|
||||
}
|
||||
}
|
||||
|
||||
public void setDirection(Direction direction) {
|
||||
if (newerThan_v_1_8_8) {
|
||||
WrappedPacketInBlockPlace_1_9 blockPlace_1_9 = new WrappedPacketInBlockPlace_1_9(new NMSPacket(packet.getRawNMSPacket()));
|
||||
blockPlace_1_9.setDirection(direction);
|
||||
} else if (newerThan_v_1_7_10) {
|
||||
WrappedPacketInBlockPlace_1_8 blockPlace_1_8 = new WrappedPacketInBlockPlace_1_8(new NMSPacket(packet.getRawNMSPacket()));
|
||||
blockPlace_1_8.setFace(direction.getFaceValue());
|
||||
} else {
|
||||
WrappedPacketInBlockPlace_1_7_10 blockPlace_1_7_10 = new WrappedPacketInBlockPlace_1_7_10(new NMSPacket(packet.getRawNMSPacket()));
|
||||
blockPlace_1_7_10.setFace(direction.getFaceValue());
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3i getBlockPosition() {
|
||||
Vector3i blockPos;
|
||||
if (newerThan_v_1_8_8) {
|
||||
WrappedPacketInBlockPlace_1_9 blockPlace_1_9 = new WrappedPacketInBlockPlace_1_9(packet);
|
||||
blockPos = blockPlace_1_9.getBlockPosition();
|
||||
} else if (newerThan_v_1_7_10) {
|
||||
WrappedPacketInBlockPlace_1_8 blockPlace_1_8 = new WrappedPacketInBlockPlace_1_8(packet);
|
||||
blockPos = blockPlace_1_8.getBlockPosition();
|
||||
} else {
|
||||
WrappedPacketInBlockPlace_1_7_10 blockPlace_1_7_10 = new WrappedPacketInBlockPlace_1_7_10(packet);
|
||||
blockPos = blockPlace_1_7_10.getBlockPosition();
|
||||
}
|
||||
return blockPos;
|
||||
}
|
||||
|
||||
public Optional<Vector3f> getCursorPosition() {
|
||||
if (newerThan_v_1_8_8) {
|
||||
return Optional.empty();
|
||||
} else if (newerThan_v_1_7_10) {
|
||||
WrappedPacketInBlockPlace_1_8 blockPlace_1_8 = new WrappedPacketInBlockPlace_1_8(packet);
|
||||
return Optional.of(blockPlace_1_8.getCursorPosition());
|
||||
} else {
|
||||
WrappedPacketInBlockPlace_1_7_10 blockPlace_1_7_10 = new WrappedPacketInBlockPlace_1_7_10(packet);
|
||||
return Optional.of(blockPlace_1_7_10.getCursorPosition());
|
||||
}
|
||||
}
|
||||
|
||||
public void setCursorPosition(Vector3f cursorPos) {
|
||||
if (newerThan_v_1_8_8) {
|
||||
|
||||
} else if (newerThan_v_1_7_10) {
|
||||
WrappedPacketInBlockPlace_1_8 blockPlace_1_8 = new WrappedPacketInBlockPlace_1_8(packet);
|
||||
blockPlace_1_8.setCursorPosition(cursorPos);
|
||||
} else {
|
||||
WrappedPacketInBlockPlace_1_7_10 blockPlace_1_7_10 = new WrappedPacketInBlockPlace_1_7_10(packet);
|
||||
blockPlace_1_7_10.setCursorPosition(cursorPos);
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<ItemStack> getItemStack() {
|
||||
if (newerThan_v_1_8_8) {
|
||||
return Optional.empty();
|
||||
} else if (newerThan_v_1_7_10) {
|
||||
WrappedPacketInBlockPlace_1_8 blockPlace_1_8 = new WrappedPacketInBlockPlace_1_8(packet);
|
||||
return Optional.of(blockPlace_1_8.getItemStack());
|
||||
} else {
|
||||
WrappedPacketInBlockPlace_1_7_10 blockPlace_1_7_10 = new WrappedPacketInBlockPlace_1_7_10(packet);
|
||||
return Optional.of(blockPlace_1_7_10.getItemStack());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setItemStack(ItemStack stack) {
|
||||
if (newerThan_v_1_8_8) {
|
||||
|
||||
} else if (newerThan_v_1_7_10) {
|
||||
WrappedPacketInBlockPlace_1_8 blockPlace_1_8 = new WrappedPacketInBlockPlace_1_8(packet);
|
||||
blockPlace_1_8.setItemStack(stack);
|
||||
} else {
|
||||
WrappedPacketInBlockPlace_1_7_10 blockPlace_1_7_10 = new WrappedPacketInBlockPlace_1_7_10(packet);
|
||||
blockPlace_1_7_10.setItemStack(stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
+52
-10
@@ -26,25 +26,67 @@ package io.github.retrooper.packetevents.packetwrappers.play.in.blockplace;
|
||||
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.vector.Vector3f;
|
||||
import io.github.retrooper.packetevents.utils.vector.Vector3i;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
final class WrappedPacketInBlockPlace_1_7_10 extends WrappedPacket {
|
||||
public int x, y, z;
|
||||
public ItemStack itemStack;
|
||||
public int face;
|
||||
private final net.minecraft.server.v1_7_R4.PacketPlayInBlockPlace blockPlace;
|
||||
|
||||
WrappedPacketInBlockPlace_1_7_10(final NMSPacket packet) {
|
||||
super(packet);
|
||||
final net.minecraft.server.v1_7_R4.PacketPlayInBlockPlace blockPlace =
|
||||
blockPlace =
|
||||
(net.minecraft.server.v1_7_R4.PacketPlayInBlockPlace) packet.getRawNMSPacket();
|
||||
}
|
||||
|
||||
x = blockPlace.c();
|
||||
y = blockPlace.d();
|
||||
z = blockPlace.e();
|
||||
public Vector3i getBlockPosition() {
|
||||
return new Vector3i(blockPlace.c(), blockPlace.d(), blockPlace.e());
|
||||
}
|
||||
|
||||
this.face = blockPlace.d();
|
||||
public void setBlockPosition(Vector3i blockPos) {
|
||||
Vector3i currentBlockPos = getBlockPosition();
|
||||
if (blockPos.x != currentBlockPos.x) {
|
||||
writeInt(0, blockPos.x);
|
||||
}
|
||||
if (blockPos.y != currentBlockPos.y) {
|
||||
writeInt(1, blockPos.y);
|
||||
}
|
||||
if (blockPos.z != currentBlockPos.z) {
|
||||
writeInt(2, blockPos.z);
|
||||
}
|
||||
}
|
||||
|
||||
net.minecraft.server.v1_7_R4.ItemStack stack = blockPlace.getItemStack();
|
||||
this.itemStack = org.bukkit.craftbukkit.v1_7_R4.inventory.CraftItemStack.asBukkitCopy(stack);
|
||||
public int getFace() {
|
||||
return blockPlace.getFace();
|
||||
}
|
||||
|
||||
public void setFace(int face) {
|
||||
writeInt(3, face);
|
||||
}
|
||||
|
||||
public ItemStack getItemStack() {
|
||||
return org.bukkit.craftbukkit.v1_7_R4.inventory.CraftItemStack.asBukkitCopy(blockPlace.getItemStack());
|
||||
}
|
||||
|
||||
public void setItemStack(ItemStack stack) {
|
||||
Object nmsItemStack = org.bukkit.craftbukkit.v1_7_R4.inventory.CraftItemStack.asNMSCopy(stack);
|
||||
writeObject(0, nmsItemStack);
|
||||
}
|
||||
|
||||
public Vector3f getCursorPosition() {
|
||||
return new Vector3f(blockPlace.h(), blockPlace.i(), blockPlace.j());
|
||||
}
|
||||
|
||||
public void setCursorPosition(Vector3f cursorPos) {
|
||||
Vector3f currentCursorPos = getCursorPosition();
|
||||
if (cursorPos.x != currentCursorPos.x) {
|
||||
writeFloat(0, cursorPos.x);
|
||||
}
|
||||
if (cursorPos.y != currentCursorPos.y) {
|
||||
writeFloat(1, cursorPos.y);
|
||||
}
|
||||
if (cursorPos.z != currentCursorPos.z) {
|
||||
writeFloat(2, cursorPos.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
+32
-31
@@ -27,60 +27,61 @@ package io.github.retrooper.packetevents.packetwrappers.play.in.blockplace;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
import io.github.retrooper.packetevents.utils.reflection.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.vector.Vector3f;
|
||||
import io.github.retrooper.packetevents.utils.vector.Vector3i;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
final class WrappedPacketInBlockPlace_1_8 extends WrappedPacket {
|
||||
private Object blockPosObj;
|
||||
|
||||
WrappedPacketInBlockPlace_1_8(final NMSPacket packet) {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
if (blockPosObj == null) {
|
||||
blockPosObj = readObject(1, NMSUtils.blockPosClass);
|
||||
}
|
||||
public Vector3i getBlockPosition() {
|
||||
Vector3i blockPos = new Vector3i();
|
||||
|
||||
Object blockPosObj = readObject(1, NMSUtils.blockPosClass);
|
||||
try {
|
||||
return (int) Reflection.getMethod(blockPosObj.getClass().getSuperclass(), "getX", 0).invoke(blockPosObj);
|
||||
blockPos.x = (int)NMSUtils.getBlockPosX.invoke(blockPosObj);
|
||||
blockPos.y = (int)NMSUtils.getBlockPosY.invoke(blockPosObj);
|
||||
blockPos.z = (int)NMSUtils.getBlockPosZ.invoke(blockPosObj);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return 0;
|
||||
return blockPos;
|
||||
}
|
||||
|
||||
|
||||
public int getY() {
|
||||
if (blockPosObj == null) {
|
||||
blockPosObj = readObject(1, NMSUtils.blockPosClass);
|
||||
}
|
||||
try {
|
||||
return (int) Reflection.getMethod(blockPosObj.getClass().getSuperclass(), "getY", 0).invoke(blockPosObj);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getZ() {
|
||||
if (blockPosObj == null) {
|
||||
blockPosObj = readObject(1, NMSUtils.blockPosClass);
|
||||
}
|
||||
try {
|
||||
return (int) Reflection.getMethod(blockPosObj.getClass().getSuperclass(), "getZ", 0).invoke(blockPosObj);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return 0;
|
||||
public void setBlockPosition(Vector3i blockPos) {
|
||||
Object blockPosObj = NMSUtils.generateNMSBlockPos(blockPos.z, blockPos.y, blockPos.z);
|
||||
write(NMSUtils.blockPosClass, 1, blockPosObj);
|
||||
}
|
||||
|
||||
public ItemStack getItemStack() {
|
||||
return NMSUtils.toBukkitItemStack(readObject(0, NMSUtils.nmsItemStackClass));
|
||||
}
|
||||
|
||||
public void setItemStack(ItemStack stack) {
|
||||
Object nmsItemStack = NMSUtils.toNMSItemStack(stack);
|
||||
write(NMSUtils.nmsItemStackClass, 0, nmsItemStack);
|
||||
}
|
||||
|
||||
public int getFace() {
|
||||
return readInt(0);
|
||||
}
|
||||
|
||||
public void setFace(int face) {
|
||||
writeInt(0, face);
|
||||
}
|
||||
|
||||
public Vector3f getCursorPosition() {
|
||||
return new Vector3f(readFloat(0), readFloat(1), readFloat(2));
|
||||
}
|
||||
|
||||
public void setCursorPosition(Vector3f cursorPos) {
|
||||
writeFloat(0, cursorPos.x);
|
||||
writeFloat(1, cursorPos.y);
|
||||
writeFloat(2, cursorPos.z);
|
||||
}
|
||||
}
|
||||
+61
-61
@@ -27,14 +27,16 @@ package io.github.retrooper.packetevents.packetwrappers.play.in.blockplace;
|
||||
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.enums.EnumUtil;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
import io.github.retrooper.packetevents.utils.reflection.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.player.Direction;
|
||||
import io.github.retrooper.packetevents.utils.vector.Vector3i;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
final class WrappedPacketInBlockPlace_1_9 extends WrappedPacket {
|
||||
private static Class<?> movingObjectPositionBlockClass;
|
||||
private Object blockPosObj;
|
||||
private Object movingObjPos;
|
||||
|
||||
public WrappedPacketInBlockPlace_1_9(final NMSPacket packet) {
|
||||
super(packet);
|
||||
@@ -45,67 +47,65 @@ final class WrappedPacketInBlockPlace_1_9 extends WrappedPacket {
|
||||
movingObjectPositionBlockClass = NMSUtils.getNMSClassWithoutException("MovingObjectPositionBlock");
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
if (blockPosObj == null) {
|
||||
if (movingObjectPositionBlockClass == null) {
|
||||
blockPosObj = readObject(0, NMSUtils.blockPosClass);
|
||||
} else {
|
||||
Object movingObjectPos = readObject(0, movingObjectPositionBlockClass);
|
||||
WrappedPacket movingObjectPosWrapper = new WrappedPacket(new NMSPacket(movingObjectPos));
|
||||
blockPosObj = movingObjectPosWrapper.readObject(0, NMSUtils.blockPosClass);
|
||||
}
|
||||
}
|
||||
try {
|
||||
return (int) Reflection.getMethod(blockPosObj.getClass().getSuperclass(), "getX", 0).invoke(blockPosObj);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
if (blockPosObj == null) {
|
||||
if (movingObjectPositionBlockClass == null) {
|
||||
blockPosObj = readObject(0, NMSUtils.blockPosClass);
|
||||
} else {
|
||||
Object movingObjectPos = readObject(0, movingObjectPositionBlockClass);
|
||||
WrappedPacket movingObjectPosWrapper = new WrappedPacket(new NMSPacket(movingObjectPos));
|
||||
blockPosObj = movingObjectPosWrapper.readObject(0, NMSUtils.blockPosClass);
|
||||
}
|
||||
}
|
||||
try {
|
||||
return (int) Reflection.getMethod(blockPosObj.getClass().getSuperclass(), "getY", 0).invoke(blockPosObj);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getZ() {
|
||||
if (blockPosObj == null) {
|
||||
if (movingObjectPositionBlockClass == null) {
|
||||
blockPosObj = readObject(0, NMSUtils.blockPosClass);
|
||||
} else {
|
||||
Object movingObjectPos = readObject(0, movingObjectPositionBlockClass);
|
||||
WrappedPacket movingObjectPosWrapper = new WrappedPacket(new NMSPacket(movingObjectPos));
|
||||
blockPosObj = movingObjectPosWrapper.readObject(0, NMSUtils.blockPosClass);
|
||||
}
|
||||
}
|
||||
try {
|
||||
return (int) Reflection.getMethod(blockPosObj.getClass().getSuperclass(), "getZ", 0).invoke(blockPosObj);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public Object getEnumDirectionObject() {
|
||||
public Vector3i getBlockPosition() {
|
||||
Vector3i blockPos = new Vector3i();
|
||||
Object blockPosObj;
|
||||
if (movingObjectPositionBlockClass == null) {
|
||||
return readObject(0, NMSUtils.enumDirectionClass);
|
||||
blockPosObj = readObject(0, NMSUtils.blockPosClass);
|
||||
} else {
|
||||
Object movingObjectPos = readObject(0, movingObjectPositionBlockClass);
|
||||
WrappedPacket movingObjectPosWrapper = new WrappedPacket(new NMSPacket(movingObjectPos));
|
||||
return movingObjectPosWrapper.readObject(0, NMSUtils.enumDirectionClass);
|
||||
if (movingObjPos == null) {
|
||||
movingObjPos = readObject(0, movingObjectPositionBlockClass);
|
||||
}
|
||||
WrappedPacket movingObjectPosWrapper = new WrappedPacket(new NMSPacket(movingObjPos));
|
||||
blockPosObj = movingObjectPosWrapper.readObject(0, NMSUtils.blockPosClass);
|
||||
}
|
||||
try {
|
||||
blockPos.x = (int) NMSUtils.getBlockPosX.invoke(blockPosObj);
|
||||
blockPos.y = (int) NMSUtils.getBlockPosY.invoke(blockPosObj);
|
||||
blockPos.z = (int) NMSUtils.getBlockPosZ.invoke(blockPosObj);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return blockPos;
|
||||
}
|
||||
|
||||
public void setBlockPosition(Vector3i blockPos) {
|
||||
Object blockPosObj = NMSUtils.generateNMSBlockPos(blockPos.x, blockPos.y, blockPos.z);
|
||||
if (movingObjectPositionBlockClass == null) {
|
||||
write(NMSUtils.blockPosClass, 0, blockPosObj);
|
||||
} else {
|
||||
if (movingObjPos == null) {
|
||||
movingObjPos = readObject(0, movingObjectPositionBlockClass);
|
||||
}
|
||||
WrappedPacket movingObjectPosWrapper = new WrappedPacket(new NMSPacket(movingObjPos));
|
||||
movingObjectPosWrapper.write(NMSUtils.blockPosClass, 0, blockPos);
|
||||
}
|
||||
}
|
||||
|
||||
public Direction getDirection() {
|
||||
Enum<?> enumConst;
|
||||
if (movingObjectPositionBlockClass == null) {
|
||||
enumConst = readEnumConstant(0, NMSUtils.enumDirectionClass);
|
||||
} else {
|
||||
if (movingObjPos == null) {
|
||||
movingObjPos = readObject(0, movingObjectPositionBlockClass);
|
||||
}
|
||||
WrappedPacket movingObjectPosWrapper = new WrappedPacket(new NMSPacket(movingObjPos));
|
||||
enumConst = movingObjectPosWrapper.readEnumConstant(0, NMSUtils.enumDirectionClass);
|
||||
}
|
||||
return Direction.valueOf(enumConst.name());
|
||||
}
|
||||
|
||||
public void setDirection(Direction direction) {
|
||||
Enum<?> enumConst = EnumUtil.valueOf(NMSUtils.enumDirectionClass, direction.name());
|
||||
if (movingObjectPositionBlockClass == null) {
|
||||
writeEnumConstant(0, enumConst);
|
||||
} else {
|
||||
if (movingObjPos == null) {
|
||||
movingObjPos = readObject(0, movingObjectPositionBlockClass);
|
||||
}
|
||||
WrappedPacket movingObjectPosWrapper = new WrappedPacket(new NMSPacket(movingObjPos));
|
||||
movingObjectPosWrapper.writeEnumConstant(0, enumConst);
|
||||
}
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.packetwrappers.play.in.boatmove;
|
||||
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.server.ServerVersion;
|
||||
|
||||
/**
|
||||
* Wrapper for the BoatMove packet.
|
||||
*
|
||||
* @author Tecnio
|
||||
* @since 1.8
|
||||
*/
|
||||
public final class WrappedPacketInBoatMove extends WrappedPacket {
|
||||
public WrappedPacketInBoatMove(NMSPacket packet) {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
public boolean getLeftPaddle() {
|
||||
return readBoolean(0);
|
||||
}
|
||||
|
||||
public void setLeftPaddle(boolean turning) {
|
||||
writeBoolean(0, turning);
|
||||
}
|
||||
|
||||
public boolean getRightPaddle() {
|
||||
return readBoolean(1);
|
||||
}
|
||||
|
||||
public void setRightPaddle(boolean turning) {
|
||||
writeBoolean(1, turning);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported() {
|
||||
return version.isNewerThan(ServerVersion.v_1_8);
|
||||
}
|
||||
}
|
||||
+10
-6
@@ -28,16 +28,20 @@ import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
|
||||
public final class WrappedPacketInChat extends WrappedPacket {
|
||||
private String message = null;
|
||||
public WrappedPacketInChat(NMSPacket packet) {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message.
|
||||
*
|
||||
* @return Chat Message
|
||||
*/
|
||||
public String getMessage() {
|
||||
return readString(0);
|
||||
if (message != null) {
|
||||
return message;
|
||||
}
|
||||
return message = readString(0);
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
writeString(0, message);
|
||||
}
|
||||
}
|
||||
+18
-13
@@ -27,12 +27,13 @@ package io.github.retrooper.packetevents.packetwrappers.play.in.clientcommand;
|
||||
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.enums.EnumUtil;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
import io.github.retrooper.packetevents.utils.reflection.SubclassUtil;
|
||||
import io.github.retrooper.packetevents.utils.server.ServerVersion;
|
||||
|
||||
public final class WrappedPacketInClientCommand extends WrappedPacket {
|
||||
private static Class<?> enumClientCommandClass;
|
||||
private Object enumObj;
|
||||
private static Class<? extends Enum<?>> enumClientCommandClass;
|
||||
|
||||
public WrappedPacketInClientCommand(NMSPacket packet) {
|
||||
super(packet);
|
||||
@@ -42,30 +43,34 @@ public final class WrappedPacketInClientCommand extends WrappedPacket {
|
||||
protected void load() {
|
||||
Class<?> packetClass = PacketTypeClasses.Play.Client.CLIENT_COMMAND;
|
||||
try {
|
||||
enumClientCommandClass = NMSUtils.getNMSClass("EnumClientCommand");
|
||||
enumClientCommandClass = NMSUtils.getNMSEnumClass("EnumClientCommand");
|
||||
} catch (ClassNotFoundException e) {
|
||||
//Probably a subclass
|
||||
enumClientCommandClass = SubclassUtil.getSubClass(packetClass, "EnumClientCommand");
|
||||
enumClientCommandClass = SubclassUtil.getEnumSubClass(packetClass, "EnumClientCommand");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Client Command enum sent in the packet
|
||||
*
|
||||
* @return ClientCommand
|
||||
*/
|
||||
|
||||
public ClientCommand getClientCommand() {
|
||||
if (enumObj == null) {
|
||||
enumObj = readObject(0, enumClientCommandClass);
|
||||
Enum<?> emumConst = readEnumConstant(0, enumClientCommandClass);
|
||||
return ClientCommand.valueOf(emumConst.name());
|
||||
}
|
||||
|
||||
public void setClientCommand(ClientCommand command) throws UnsupportedOperationException {
|
||||
if (command == ClientCommand.OPEN_INVENTORY_ACHIEVEMENT && version.isNewerThan(ServerVersion.v_1_16)) {
|
||||
throwUnsupportedOperation(command);
|
||||
}
|
||||
return ClientCommand.valueOf(enumObj.toString());
|
||||
Enum<?> enumConst = EnumUtil.valueOf(enumClientCommandClass, command.name());
|
||||
writeEnumConstant(0, enumConst);
|
||||
}
|
||||
|
||||
public enum ClientCommand {
|
||||
PERFORM_RESPAWN,
|
||||
REQUEST_STATS,
|
||||
|
||||
//This field doesn't exist on 1.16
|
||||
//This enum constant only exists on 1.7.10 -> 1.15.2
|
||||
@SupportedVersions(ranges = {ServerVersion.v_1_7_10, ServerVersion.v_1_15_2})
|
||||
@Deprecated
|
||||
OPEN_INVENTORY_ACHIEVEMENT
|
||||
}
|
||||
|
||||
|
||||
+4
@@ -36,4 +36,8 @@ public class WrappedPacketInCloseWindow extends WrappedPacket {
|
||||
public int getWindowId() {
|
||||
return readInt(0);
|
||||
}
|
||||
|
||||
public void setWindowId(int windowID) {
|
||||
writeInt(0, windowID);
|
||||
}
|
||||
}
|
||||
+38
-14
@@ -32,8 +32,6 @@ import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
import io.github.retrooper.packetevents.utils.reflection.Reflection;
|
||||
|
||||
public final class WrappedPacketInCustomPayload extends WrappedPacket {
|
||||
private static Class<?> packetDataSerializerClass, byteBufClass;
|
||||
|
||||
private static boolean strPresent, byteArrayPresent;
|
||||
|
||||
public WrappedPacketInCustomPayload(NMSPacket packet) {
|
||||
@@ -45,12 +43,6 @@ public final class WrappedPacketInCustomPayload extends WrappedPacket {
|
||||
Class<?> packetClass = PacketTypeClasses.Play.Client.CUSTOM_PAYLOAD;
|
||||
strPresent = Reflection.getField(packetClass, String.class, 0) != null;
|
||||
byteArrayPresent = Reflection.getField(packetClass, byte[].class, 0) != null;
|
||||
packetDataSerializerClass = NMSUtils.getNMSClassWithoutException("PacketDataSerializer");
|
||||
try {
|
||||
byteBufClass = NMSUtils.getNettyClass("buffer.ByteBuf");
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public String getTag() {
|
||||
@@ -62,16 +54,48 @@ public final class WrappedPacketInCustomPayload extends WrappedPacket {
|
||||
}
|
||||
}
|
||||
|
||||
public void setTag(String tag) {
|
||||
if (strPresent) {
|
||||
writeString(0, tag);
|
||||
} else {
|
||||
Object minecraftKey = NMSUtils.generateMinecraftKey(tag);
|
||||
write(NMSUtils.minecraftKeyClass, 0, minecraftKey);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
if (byteArrayPresent) {
|
||||
return readByteArray(0);
|
||||
} else {
|
||||
Object dataSerializer = readObject(0, packetDataSerializerClass);
|
||||
WrappedPacket byteBufWrapper = new WrappedPacket(new NMSPacket(dataSerializer));
|
||||
|
||||
Object byteBuf = byteBufWrapper.readObject(0, byteBufClass);
|
||||
|
||||
return PacketEvents.get().getByteBufUtil().getBytes(byteBuf);
|
||||
return PacketEvents.get().getByteBufUtil().getBytes(getBuffer());
|
||||
}
|
||||
}
|
||||
|
||||
public void setData(byte[] data) {
|
||||
if (byteArrayPresent) {
|
||||
writeByteArray(0, data);
|
||||
} else {
|
||||
PacketEvents.get().getByteBufUtil().setBytes(getBuffer(), data);
|
||||
}
|
||||
}
|
||||
|
||||
private Object getBuffer() {
|
||||
Object dataSerializer = readObject(0, NMSUtils.packetDataSerializerClass);
|
||||
WrappedPacket dataSerializerWrapper = new WrappedPacket(new NMSPacket(dataSerializer));
|
||||
|
||||
return dataSerializerWrapper.readObject(0, NMSUtils.byteBufClass);
|
||||
}
|
||||
|
||||
public void retain() {
|
||||
if (!byteArrayPresent) {
|
||||
PacketEvents.get().getByteBufUtil().retain(getBuffer());
|
||||
}
|
||||
}
|
||||
|
||||
public void release() {
|
||||
if (!byteArrayPresent) {
|
||||
PacketEvents.get().getByteBufUtil().release(getBuffer());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+65
@@ -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.packetwrappers.play.in.difficultychange;
|
||||
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.enums.EnumUtil;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
import io.github.retrooper.packetevents.utils.world.Difficulty;
|
||||
|
||||
/**
|
||||
* Wrapper for the DifficultyChange packet.
|
||||
*
|
||||
* @author Tecnio
|
||||
* @since 1.8
|
||||
*/
|
||||
public final class WrappedPacketInDifficultyChange extends WrappedPacket {
|
||||
|
||||
private static Class<? extends Enum<?>> enumDifficultyClass;
|
||||
|
||||
public WrappedPacketInDifficultyChange(NMSPacket packet) {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void load() {
|
||||
try {
|
||||
enumDifficultyClass = NMSUtils.getNMSEnumClass("EnumDifficulty");
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public Difficulty getDifficulty() {
|
||||
Enum<?> enumConstant = readEnumConstant(0, enumDifficultyClass);
|
||||
return Difficulty.values()[enumConstant.ordinal()];
|
||||
}
|
||||
|
||||
public void setDifficulty(Difficulty difficulty) {
|
||||
Enum<?> enumConstant = EnumUtil.valueByIndex(enumDifficultyClass, difficulty.ordinal());
|
||||
writeEnumConstant(0, enumConstant);
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.packetwrappers.play.in.difficultylock;
|
||||
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.server.ServerVersion;
|
||||
|
||||
/**
|
||||
* Wrapper for the DifficultyLock packet.
|
||||
*
|
||||
* @author Tecnio
|
||||
* @since 1.8
|
||||
*/
|
||||
public final class WrappedPacketInDifficultyLock extends WrappedPacket {
|
||||
public WrappedPacketInDifficultyLock(NMSPacket packet) {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
public boolean isLocked() {
|
||||
return readBoolean(0);
|
||||
}
|
||||
|
||||
public void setLocked(boolean locked) {
|
||||
writeBoolean(0, locked);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported() {
|
||||
return version.isNewerThan(ServerVersion.v_1_15_2);
|
||||
}
|
||||
}
|
||||
+8
@@ -36,7 +36,15 @@ public class WrappedPacketInEnchantItem extends WrappedPacket {
|
||||
return readInt(0);
|
||||
}
|
||||
|
||||
public void setWindowId(int windowID) {
|
||||
writeInt(0, windowID);
|
||||
}
|
||||
|
||||
public int getButton() {
|
||||
return readInt(1);
|
||||
}
|
||||
|
||||
public void setButton(int button) {
|
||||
writeInt(1, button);
|
||||
}
|
||||
}
|
||||
+107
-79
@@ -27,20 +27,17 @@ package io.github.retrooper.packetevents.packetwrappers.play.in.entityaction;
|
||||
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.enums.EnumUtil;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
import io.github.retrooper.packetevents.utils.reflection.SubclassUtil;
|
||||
import io.github.retrooper.packetevents.utils.server.ServerVersion;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
import java.util.HashMap;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public final class WrappedPacketInEntityAction extends WrappedPacket {
|
||||
private static final HashMap<String, PlayerAction> cachedPlayerActionNames = new HashMap<>();
|
||||
private static final HashMap<Integer, PlayerAction> cachedPlayerActionIDs = new HashMap<>();
|
||||
private static Class<?> enumPlayerActionClass;
|
||||
private static boolean isLowerThan_v_1_8;
|
||||
private Entity entity;
|
||||
private int entityId = -1;
|
||||
private static Class<? extends Enum<?>> enumPlayerActionClass;
|
||||
private static boolean newerThan_v_1_8_8;
|
||||
|
||||
public WrappedPacketInEntityAction(final NMSPacket packet) {
|
||||
super(packet);
|
||||
@@ -48,94 +45,125 @@ public final class WrappedPacketInEntityAction extends WrappedPacket {
|
||||
|
||||
@Override
|
||||
protected void load() {
|
||||
isLowerThan_v_1_8 = version.isOlderThan(ServerVersion.v_1_8);
|
||||
if (!isLowerThan_v_1_8) {
|
||||
enumPlayerActionClass = SubclassUtil.getSubClass(PacketTypeClasses.Play.Client.ENTITY_ACTION, "EnumPlayerAction");
|
||||
newerThan_v_1_8_8 = version.isNewerThan(ServerVersion.v_1_8_8);
|
||||
enumPlayerActionClass = NMSUtils.getNMSEnumClassWithoutException("EnumPlayerAction");
|
||||
if (enumPlayerActionClass == null) {
|
||||
enumPlayerActionClass = SubclassUtil.getEnumSubClass(PacketTypeClasses.Play.Client.ENTITY_ACTION, "EnumPlayerAction");
|
||||
}
|
||||
//All the already existing values
|
||||
for (PlayerAction val : PlayerAction.values()) {
|
||||
cachedPlayerActionNames.put(val.name(), val);
|
||||
}
|
||||
|
||||
cachedPlayerActionNames.put("PRESS_SHIFT_KEY", PlayerAction.START_SNEAKING);
|
||||
cachedPlayerActionNames.put("RELEASE_SHIFT_KEY", PlayerAction.STOP_SNEAKING);
|
||||
cachedPlayerActionNames.put("RIDING_JUMP", PlayerAction.START_RIDING_JUMP);
|
||||
|
||||
cachedPlayerActionIDs.put(1, PlayerAction.START_SNEAKING);
|
||||
cachedPlayerActionIDs.put(2, PlayerAction.STOP_SNEAKING);
|
||||
cachedPlayerActionIDs.put(3, PlayerAction.STOP_SLEEPING);
|
||||
cachedPlayerActionIDs.put(4, PlayerAction.START_SPRINTING);
|
||||
cachedPlayerActionIDs.put(5, PlayerAction.STOP_SPRINTING);
|
||||
cachedPlayerActionIDs.put(6, PlayerAction.START_RIDING_JUMP); //riding jump
|
||||
cachedPlayerActionIDs.put(7, PlayerAction.OPEN_INVENTORY); //horse interaction
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup the associated entity by the ID that was sent in the packet.
|
||||
*
|
||||
* @return Entity
|
||||
*/
|
||||
public Entity getEntity() {
|
||||
if (entity == null) {
|
||||
return entity = NMSUtils.getEntityById(getEntityId());
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ID of the entity.
|
||||
* If you do not want to use {@link #getEntity()},
|
||||
* you lookup the entity by yourself with this entity ID.
|
||||
*
|
||||
* @return Entity ID
|
||||
*/
|
||||
public int getEntityId() {
|
||||
if (entityId == -1) {
|
||||
entityId = readInt(0);
|
||||
}
|
||||
return entityId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player action.
|
||||
*
|
||||
* @return Player Action
|
||||
*/
|
||||
public PlayerAction getAction() {
|
||||
if (isLowerThan_v_1_8) {
|
||||
int animationIndex = readInt(1);
|
||||
return cachedPlayerActionIDs.get(animationIndex);
|
||||
if (enumPlayerActionClass == null) {
|
||||
int animationIndex = readInt(1) - 1;
|
||||
return PlayerAction.getByActionValue((byte) (animationIndex));
|
||||
} else {
|
||||
final Object enumObj = readObject(0, enumPlayerActionClass);
|
||||
final String enumValueName = enumObj.toString();
|
||||
return cachedPlayerActionNames.get(enumValueName);
|
||||
Enum<?> enumConst = readEnumConstant(0, enumPlayerActionClass);
|
||||
return PlayerAction.getByName(enumConst.name());
|
||||
}
|
||||
}
|
||||
|
||||
public void setAction(PlayerAction action) throws UnsupportedOperationException {
|
||||
if (enumPlayerActionClass == null) {
|
||||
byte animationIndex = action.actionID;
|
||||
writeInt(1, animationIndex + 1);
|
||||
} else {
|
||||
Enum<?> enumConst;
|
||||
if (newerThan_v_1_8_8) {
|
||||
if (action == PlayerAction.RIDING_JUMP) {
|
||||
throwUnsupportedOperation(action);
|
||||
}
|
||||
enumConst = EnumUtil.valueByIndex(enumPlayerActionClass, action.ordinal());
|
||||
|
||||
} else {
|
||||
enumConst = EnumUtil.valueOf(enumPlayerActionClass, action.name());
|
||||
if (enumConst == null) {
|
||||
enumConst = EnumUtil.valueOf(enumPlayerActionClass, action.alias);
|
||||
}
|
||||
}
|
||||
writeEnumConstant(0, enumConst);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the jump boost integer.
|
||||
*
|
||||
* @return Jump Boost
|
||||
*/
|
||||
public int getJumpBoost() {
|
||||
if (isLowerThan_v_1_8) {
|
||||
if (enumPlayerActionClass == null) {
|
||||
return readInt(2);
|
||||
} else {
|
||||
return readInt(1);
|
||||
}
|
||||
}
|
||||
|
||||
public void setJumpBoost(int jumpBoost) {
|
||||
if (enumPlayerActionClass == null) {
|
||||
writeInt(2, jumpBoost);
|
||||
} else {
|
||||
writeInt(1, jumpBoost);
|
||||
}
|
||||
}
|
||||
|
||||
public enum PlayerAction {
|
||||
START_SNEAKING,
|
||||
STOP_SNEAKING,
|
||||
STOP_SLEEPING,
|
||||
START_SPRINTING,
|
||||
STOP_SPRINTING,
|
||||
START_RIDING_JUMP,
|
||||
STOP_RIDING_JUMP,
|
||||
OPEN_INVENTORY,
|
||||
START_FALL_FLYING
|
||||
START_SNEAKING((byte) 0, "PRESS_SHIFT_KEY"),
|
||||
STOP_SNEAKING((byte) 1, "RELEASE_SHIFT_KEY"),
|
||||
STOP_SLEEPING((byte) 2),
|
||||
START_SPRINTING((byte) 3),
|
||||
STOP_SPRINTING((byte) 4),
|
||||
START_RIDING_JUMP((byte) 5),
|
||||
STOP_RIDING_JUMP((byte) 6),
|
||||
OPEN_INVENTORY((byte) 7),
|
||||
START_FALL_FLYING((byte) 8),
|
||||
|
||||
/**
|
||||
* Removed in minecraft server version 1.9.
|
||||
* This constant will only work on 1.7.10-1.8
|
||||
*/
|
||||
@SupportedVersions(ranges = {ServerVersion.v_1_7_10, ServerVersion.v_1_8_8})
|
||||
@Deprecated
|
||||
RIDING_JUMP((byte) 5);
|
||||
|
||||
final byte actionID;
|
||||
final String alias;
|
||||
|
||||
PlayerAction(byte actionID) {
|
||||
this.actionID = actionID;
|
||||
this.alias = "empty";
|
||||
}
|
||||
|
||||
PlayerAction(byte actionID, String alias) {
|
||||
this.actionID = actionID;
|
||||
this.alias = alias;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PlayerAction getByActionValue(byte value) {
|
||||
if (version.isOlderThan(ServerVersion.v_1_9)) {
|
||||
if (value == RIDING_JUMP.actionID) {
|
||||
return RIDING_JUMP;
|
||||
} else {
|
||||
for (PlayerAction action : values()) {
|
||||
if (action.actionID == value) {
|
||||
return action;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return values()[value];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PlayerAction getByName(String name) {
|
||||
for (PlayerAction action : values()) {
|
||||
if (action.name().equals(name) || action.alias.equals(name)) {
|
||||
return action;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public byte getActionValue() {
|
||||
return actionID;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+34
-2
@@ -37,31 +37,63 @@ public class WrappedPacketInFlying extends WrappedPacket {
|
||||
return readDouble(0);
|
||||
}
|
||||
|
||||
public void setX(double x) {
|
||||
writeDouble(0, x);
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return readDouble(1);
|
||||
}
|
||||
|
||||
public void setY(double y) {
|
||||
writeDouble(1, y);
|
||||
}
|
||||
|
||||
public double getZ() {
|
||||
return readDouble(2);
|
||||
}
|
||||
|
||||
public void setZ(double z) {
|
||||
writeDouble(2, z);
|
||||
}
|
||||
|
||||
public float getYaw() {
|
||||
return readFloat(0);
|
||||
}
|
||||
|
||||
public void setYaw(float yaw) {
|
||||
writeFloat(0, yaw);
|
||||
}
|
||||
|
||||
public float getPitch() {
|
||||
return readFloat(1);
|
||||
}
|
||||
|
||||
public void setPitch(float pitch) {
|
||||
writeFloat(1, pitch);
|
||||
}
|
||||
|
||||
public boolean isOnGround() {
|
||||
return readBoolean(0);
|
||||
}
|
||||
|
||||
public final boolean isPosition() {
|
||||
public void setOnGround(boolean onGround) {
|
||||
writeBoolean(0, onGround);
|
||||
}
|
||||
|
||||
public boolean isPosition() {
|
||||
return readBoolean(1);
|
||||
}
|
||||
|
||||
public final boolean isLook() {
|
||||
public void setIsPosition(boolean isPosition) {
|
||||
writeBoolean(1, isPosition);
|
||||
}
|
||||
|
||||
public boolean isLook() {
|
||||
return readBoolean(2);
|
||||
}
|
||||
|
||||
public void setIsLook(boolean isLook) {
|
||||
writeBoolean(2, isLook);
|
||||
}
|
||||
}
|
||||
+3
-5
@@ -32,13 +32,11 @@ public final class WrappedPacketInHeldItemSlot extends WrappedPacket {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the index of the item we currently have in hand.
|
||||
*
|
||||
* @return Item in hand Index
|
||||
*/
|
||||
public int getCurrentSelectedSlot() {
|
||||
return readInt(0);
|
||||
}
|
||||
|
||||
public void setCurrentSelectedSlot(int slot) {
|
||||
writeInt(0, slot);
|
||||
}
|
||||
}
|
||||
+4
@@ -11,4 +11,8 @@ public class WrappedPacketInItemName extends WrappedPacket {
|
||||
public String getItemName() {
|
||||
return readString(0);
|
||||
}
|
||||
|
||||
public void setItemName(String itemName) {
|
||||
writeString(0, itemName);
|
||||
}
|
||||
}
|
||||
+14
-8
@@ -42,14 +42,6 @@ public final class WrappedPacketInKeepAlive extends WrappedPacket {
|
||||
integerPresentInIndex0 = Reflection.getField(packetClass, int.class, 0) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ID response from the client.
|
||||
* <p>
|
||||
* You may cast this down to an int if you are on 1.7.10 - 1.12.2.
|
||||
* On 1.13.2 - 1.16.3 a long is sent.
|
||||
*
|
||||
* @return response ID
|
||||
*/
|
||||
public long getId() {
|
||||
if (!integerPresentInIndex0) {
|
||||
return readLong(0);
|
||||
@@ -57,4 +49,18 @@ public final class WrappedPacketInKeepAlive extends WrappedPacket {
|
||||
return readInt(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
if (!integerPresentInIndex0) {
|
||||
writeLong(0, id);
|
||||
} else {
|
||||
if (id > Integer.MAX_VALUE) {
|
||||
id = Integer.MAX_VALUE;
|
||||
}
|
||||
else if (id < Integer.MIN_VALUE) {
|
||||
id = Integer.MIN_VALUE;
|
||||
}
|
||||
writeInt(0, (int) id);
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
@@ -11,4 +11,8 @@ public class WrappedPacketInPickItem extends WrappedPacket {
|
||||
public int getSlot() {
|
||||
return readInt(0);
|
||||
}
|
||||
|
||||
public void setSlot(int slot) {
|
||||
writeInt(0, slot);
|
||||
}
|
||||
}
|
||||
+15
-9
@@ -27,11 +27,12 @@ package io.github.retrooper.packetevents.packetwrappers.play.in.resourcepackstat
|
||||
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.enums.EnumUtil;
|
||||
import io.github.retrooper.packetevents.utils.reflection.SubclassUtil;
|
||||
import io.github.retrooper.packetevents.utils.server.ServerVersion;
|
||||
|
||||
public class WrappedPacketInResourcePackStatus extends WrappedPacket {
|
||||
private static Class<?> enumResourcePackStatusClass;
|
||||
private static Class<? extends Enum<?>> enumResourcePackStatusClass;
|
||||
|
||||
public WrappedPacketInResourcePackStatus(NMSPacket packet) {
|
||||
super(packet);
|
||||
@@ -39,12 +40,22 @@ public class WrappedPacketInResourcePackStatus extends WrappedPacket {
|
||||
|
||||
@Override
|
||||
protected void load() {
|
||||
enumResourcePackStatusClass = SubclassUtil.getSubClass(PacketTypeClasses.Play.Client.RESOURCE_PACK_STATUS, "EnumResourcePackStatus");
|
||||
enumResourcePackStatusClass = SubclassUtil.getEnumSubClass(PacketTypeClasses.Play.Client.RESOURCE_PACK_STATUS, "EnumResourcePackStatus");
|
||||
}
|
||||
|
||||
public ResourcePackStatus getStatus() {
|
||||
Object enumObj = readObject(0, enumResourcePackStatusClass);
|
||||
return ResourcePackStatus.valueOf(enumObj.toString());
|
||||
Enum<?> enumConst = readEnumConstant(0, enumResourcePackStatusClass);
|
||||
return ResourcePackStatus.valueOf(enumConst.name());
|
||||
}
|
||||
|
||||
public void setStatus(ResourcePackStatus status) {
|
||||
Enum<?> enumConst = EnumUtil.valueOf(enumResourcePackStatusClass, status.name());
|
||||
writeEnumConstant(0, enumConst);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported() {
|
||||
return version.isNewerThan(ServerVersion.v_1_7_10);
|
||||
}
|
||||
|
||||
public enum ResourcePackStatus {
|
||||
@@ -53,9 +64,4 @@ public class WrappedPacketInResourcePackStatus extends WrappedPacket {
|
||||
FAILED_DOWNLOAD,
|
||||
ACCEPTED
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported() {
|
||||
return version.isNewerThan(ServerVersion.v_1_7_10);
|
||||
}
|
||||
}
|
||||
+2
-16
@@ -35,35 +35,21 @@ public class WrappedPacketInSetCreativeSlot extends WrappedPacket {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the clicked slot
|
||||
*
|
||||
* @return the slot
|
||||
*/
|
||||
public int getSlot() {
|
||||
return readInt(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the clicked slot
|
||||
*
|
||||
* @param value the slot
|
||||
*/
|
||||
public void setSlot(int value) {
|
||||
writeInt(0, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the clicked item
|
||||
*
|
||||
* @return the clicked item
|
||||
*/
|
||||
public ItemStack getClickedItem() {
|
||||
Object nmsItemStack = readObject(0, NMSUtils.nmsItemStackClass);
|
||||
return NMSUtils.toBukkitItemStack(nmsItemStack);
|
||||
}
|
||||
|
||||
public void setClickedItem(ItemStack stack) {
|
||||
write(NMSUtils.nmsItemStackClass, 0, NMSUtils.toNMSItemStack(stack));
|
||||
Object nmsItemStack = NMSUtils.toNMSItemStack(stack);
|
||||
write(NMSUtils.nmsItemStackClass, 0, nmsItemStack);
|
||||
}
|
||||
}
|
||||
+81
-90
@@ -26,18 +26,19 @@ package io.github.retrooper.packetevents.packetwrappers.play.in.settings;
|
||||
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.enums.EnumUtil;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
import io.github.retrooper.packetevents.utils.reflection.SubclassUtil;
|
||||
import io.github.retrooper.packetevents.utils.server.ServerVersion;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class WrappedPacketInSettings extends WrappedPacket {
|
||||
private static Class<?> chatVisibilityEnumClass;
|
||||
private static Class<? extends Enum<?>> chatVisibilityEnumClass;
|
||||
|
||||
private static boolean isLowerThan_v_1_8;
|
||||
private Object chatVisibilityEnumObj;
|
||||
private HashMap<DisplayedSkinPart, Boolean> displayedSkinParts = new HashMap<>();
|
||||
|
||||
public WrappedPacketInSettings(final NMSPacket packet) {
|
||||
super(packet);
|
||||
@@ -45,126 +46,116 @@ public class WrappedPacketInSettings extends WrappedPacket {
|
||||
|
||||
@Override
|
||||
protected void load() {
|
||||
|
||||
isLowerThan_v_1_8 = version.isOlderThan(ServerVersion.v_1_8);
|
||||
|
||||
try {
|
||||
chatVisibilityEnumClass = NMSUtils.getNMSClass("EnumChatVisibility");
|
||||
chatVisibilityEnumClass = NMSUtils.getNMSEnumClass("EnumChatVisibility");
|
||||
} catch (ClassNotFoundException e) {
|
||||
Class<?> entityHumanClass = NMSUtils.getNMSClassWithoutException("EntityHuman");
|
||||
//They are just on an outdated version
|
||||
assert entityHumanClass != null;
|
||||
chatVisibilityEnumClass = SubclassUtil.getSubClass(entityHumanClass, "EnumChatVisibility");
|
||||
chatVisibilityEnumClass = SubclassUtil.getEnumSubClass(entityHumanClass, "EnumChatVisibility");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get language client setting
|
||||
*
|
||||
* @return String Locale
|
||||
*/
|
||||
public String getLocale() {
|
||||
return readString(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get client view distance.
|
||||
*
|
||||
* @return View Distance
|
||||
*/
|
||||
public void setLocale(String locale) {
|
||||
writeString(0, locale);
|
||||
}
|
||||
|
||||
public int getViewDistance() {
|
||||
return readInt(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Chat Visibility
|
||||
*
|
||||
* @return Chat Visibility
|
||||
*/
|
||||
public ChatVisibility getChatVisibility() {
|
||||
if (chatVisibilityEnumObj == null) {
|
||||
chatVisibilityEnumObj = readObject(0, chatVisibilityEnumClass);
|
||||
}
|
||||
String enumValueAsString = chatVisibilityEnumObj.toString();
|
||||
if (enumValueAsString.equals("FULL")) {
|
||||
return ChatVisibility.ENABLED;
|
||||
} else if (enumValueAsString.equals("SYSTEM")) {
|
||||
return ChatVisibility.COMMANDS_ONLY;
|
||||
} else {
|
||||
return ChatVisibility.HIDDEN;
|
||||
}
|
||||
public void setViewDistance(int viewDistance) {
|
||||
writeInt(0, viewDistance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is chat colors
|
||||
*
|
||||
* @return Chat Colors
|
||||
*/
|
||||
public boolean isChatColors() {
|
||||
public ChatVisibility getChatVisibility() {
|
||||
Enum<?> enumConst = readEnumConstant(0, chatVisibilityEnumClass);
|
||||
return ChatVisibility.valueOf(enumConst.name());
|
||||
}
|
||||
|
||||
public void setChatVisibility(ChatVisibility visibility) {
|
||||
Enum<?> enumConst = EnumUtil.valueByIndex(chatVisibilityEnumClass, visibility.ordinal()); //Ordinal is faster than name comparison.
|
||||
writeEnumConstant(0, enumConst);
|
||||
}
|
||||
|
||||
public boolean isChatColored() {
|
||||
return readBoolean(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Displayed skin parts.
|
||||
* <p>
|
||||
* It is possible for some keys to not exist.
|
||||
* If that is the case, the server version is 1.7.10.
|
||||
* 1.7.10 only sends the cape skin part.
|
||||
*
|
||||
* @return A map with a Skin Parts as a key, and a boolean as a value.
|
||||
*/
|
||||
public HashMap<DisplayedSkinPart, Boolean> getDisplayedSkinPartsMap() {
|
||||
if (displayedSkinParts.isEmpty()) {
|
||||
if (isLowerThan_v_1_8) {
|
||||
//in 1.7.10 only the cape display skin part is sent
|
||||
boolean capeEnabled = readBoolean(1);
|
||||
displayedSkinParts.put(DisplayedSkinPart.CAPE, capeEnabled);
|
||||
} else {
|
||||
//in 1.8, all the skin parts are sent
|
||||
int skinPartFlags = readInt(1);
|
||||
displayedSkinParts.put(DisplayedSkinPart.CAPE, (skinPartFlags & 0x01) != 0);
|
||||
displayedSkinParts.put(DisplayedSkinPart.JACKET, (skinPartFlags & 0x02) != 0);
|
||||
displayedSkinParts.put(DisplayedSkinPart.LEFT_SLEEVE, (skinPartFlags & 0x04) != 0);
|
||||
displayedSkinParts.put(DisplayedSkinPart.RIGHT_SLEEVE, (skinPartFlags & 0x08) != 0);
|
||||
displayedSkinParts.put(DisplayedSkinPart.LEFT_PANTS, (skinPartFlags & 0x10) != 0);
|
||||
displayedSkinParts.put(DisplayedSkinPart.RIGHT_PANTS, (skinPartFlags & 0x20) != 0);
|
||||
displayedSkinParts.put(DisplayedSkinPart.HAT, (skinPartFlags & 0x40) != 0);
|
||||
public void setChatColored(boolean chatColors) {
|
||||
writeBoolean(0, chatColors);
|
||||
}
|
||||
|
||||
public byte getDisplaySkinPartsMask() {
|
||||
byte mask = 0;
|
||||
if (isLowerThan_v_1_8) {
|
||||
boolean capeEnabled = readBoolean(1);
|
||||
if (capeEnabled) {
|
||||
mask |= 0x01;
|
||||
}
|
||||
} else {
|
||||
mask = (byte) readInt(1);
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
public void setDisplaySkinPartsMask(byte mask) {
|
||||
if (isLowerThan_v_1_8) {
|
||||
boolean capeEnabled = (mask & 0x01) == 0x01;
|
||||
writeBoolean(1, capeEnabled);
|
||||
} else {
|
||||
writeInt(1, mask);
|
||||
}
|
||||
}
|
||||
|
||||
public Set<DisplayedSkinPart> getDisplayedSkinParts() {
|
||||
Set<DisplayedSkinPart> displayedSkinParts = new HashSet<>();
|
||||
byte mask = getDisplaySkinPartsMask();
|
||||
for (DisplayedSkinPart part : DisplayedSkinPart.values()) {
|
||||
if ((mask & part.maskFlag) == part.maskFlag) {
|
||||
displayedSkinParts.add(part);
|
||||
}
|
||||
}
|
||||
return displayedSkinParts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the skin part enabled.
|
||||
* <p>
|
||||
* On 1.7.10, some skin parts will default to 'false' as 1.7.10
|
||||
* only sends the 'cape' skin part.
|
||||
*
|
||||
* @param part The skin part to check the status of.
|
||||
* @return Is the skin part enabled
|
||||
*/
|
||||
public boolean isDisplaySkinPartEnabled(DisplayedSkinPart part) {
|
||||
if (displayedSkinParts.isEmpty()) {
|
||||
displayedSkinParts = getDisplayedSkinPartsMap();
|
||||
public void setDisplayedSkinParts(Set<DisplayedSkinPart> displayedSkinParts) {
|
||||
byte mask = 0;
|
||||
for (DisplayedSkinPart part : displayedSkinParts) {
|
||||
mask |= part.maskFlag;
|
||||
}
|
||||
//1.7.10, we will default the other skin parts to return false.
|
||||
if (!displayedSkinParts.containsKey(part)) {
|
||||
return false;
|
||||
}
|
||||
return displayedSkinParts.get(part);
|
||||
setDisplaySkinPartsMask(mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum for the client chat visibility setting
|
||||
*/
|
||||
public enum ChatVisibility {
|
||||
ENABLED, COMMANDS_ONLY, HIDDEN
|
||||
FULL, SYSTEM, HIDDEN
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum for the client displayed skin parts settings
|
||||
*/
|
||||
public enum DisplayedSkinPart {
|
||||
CAPE, JACKET, LEFT_SLEEVE, RIGHT_SLEEVE, LEFT_PANTS, RIGHT_PANTS, HAT
|
||||
CAPE(0x01),
|
||||
|
||||
@SupportedVersions(ranges = {ServerVersion.v_1_8, ServerVersion.ERROR})
|
||||
JACKET(0x02),
|
||||
@SupportedVersions(ranges = {ServerVersion.v_1_8, ServerVersion.ERROR})
|
||||
LEFT_SLEEVE(0x04),
|
||||
@SupportedVersions(ranges = {ServerVersion.v_1_8, ServerVersion.ERROR})
|
||||
RIGHT_SLEEVE(0x08),
|
||||
@SupportedVersions(ranges = {ServerVersion.v_1_8, ServerVersion.ERROR})
|
||||
LEFT_PANTS(0x10),
|
||||
@SupportedVersions(ranges = {ServerVersion.v_1_8, ServerVersion.ERROR})
|
||||
RIGHT_PANTS(0x20),
|
||||
@SupportedVersions(ranges = {ServerVersion.v_1_8, ServerVersion.ERROR})
|
||||
HAT(0x40);
|
||||
|
||||
final byte maskFlag;
|
||||
|
||||
DisplayedSkinPart(int maskFlag) {
|
||||
this.maskFlag = (byte) maskFlag;
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-1
@@ -35,6 +35,10 @@ public class WrappedPacketInSpectate extends WrappedPacket {
|
||||
}
|
||||
|
||||
public UUID getUUID() {
|
||||
return (UUID) readObject(0, UUID.class);
|
||||
return readObject(0, UUID.class);
|
||||
}
|
||||
|
||||
public void setUUID(UUID uuid) {
|
||||
writeObject(0, uuid);
|
||||
}
|
||||
}
|
||||
+17
-25
@@ -32,43 +32,35 @@ public class WrappedPacketInSteerVehicle extends WrappedPacket {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the side value.
|
||||
* <p>
|
||||
* If positive, they are moving to the left, if negative, they are moving to the right.
|
||||
*
|
||||
* @return Side Value
|
||||
*/
|
||||
public float getSideValue() {
|
||||
return readFloat(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the forward value.
|
||||
* <p>
|
||||
* If positive, they are moving forward, if negative, they are moving backwards.
|
||||
*
|
||||
* @return Forward Value
|
||||
*/
|
||||
public void setSideValue(float value) {
|
||||
writeFloat(0, value);
|
||||
}
|
||||
|
||||
public float getForwardValue() {
|
||||
return readFloat(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is a Jump
|
||||
*
|
||||
* @return Is Jump
|
||||
*/
|
||||
public void setForwardValue(float value) {
|
||||
writeFloat(1, value);
|
||||
}
|
||||
|
||||
public boolean isJump() {
|
||||
return readBoolean(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is an unmount
|
||||
*
|
||||
* @return Is Unmounting
|
||||
*/
|
||||
public boolean isUnmount() {
|
||||
public void setJump(boolean isJump) {
|
||||
writeBoolean(0, isJump);
|
||||
}
|
||||
|
||||
public boolean isDismount() {
|
||||
return readBoolean(1);
|
||||
}
|
||||
|
||||
public void setDismount(boolean isDismount) {
|
||||
writeBoolean(1, isDismount);
|
||||
}
|
||||
}
|
||||
+4
@@ -35,4 +35,8 @@ public class WrappedPacketInTabComplete extends WrappedPacket {
|
||||
public String getText() {
|
||||
return readString(0);
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
writeString(0, text);
|
||||
}
|
||||
}
|
||||
+28
@@ -1,3 +1,27 @@
|
||||
/*
|
||||
* 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.packetwrappers.play.in.teleportaccept;
|
||||
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
@@ -11,4 +35,8 @@ public class WrappedPacketInTeleportAccept extends WrappedPacket {
|
||||
public int getTeleportId() {
|
||||
return readInt(0);
|
||||
}
|
||||
|
||||
public void setTeleportId(int teleportId) {
|
||||
writeInt(0, teleportId);
|
||||
}
|
||||
}
|
||||
+12
-15
@@ -32,30 +32,27 @@ public final class WrappedPacketInTransaction extends WrappedPacket {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the window ID.
|
||||
*
|
||||
* @return Window ID
|
||||
*/
|
||||
public int getWindowId() {
|
||||
return readInt(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the action number.
|
||||
*
|
||||
* @return Action number
|
||||
*/
|
||||
public void setWindowId(int windowID) {
|
||||
writeInt(0, windowID);
|
||||
}
|
||||
|
||||
public short getActionNumber() {
|
||||
return readShort(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is transaction accepted.
|
||||
*
|
||||
* @return Transaction Accepted
|
||||
*/
|
||||
public void setActionNumber(short actionNumber) {
|
||||
writeShort(0, actionNumber);
|
||||
}
|
||||
|
||||
public boolean isAccepted() {
|
||||
return readBoolean(0);
|
||||
}
|
||||
|
||||
public void setAccepted(boolean isAccepted) {
|
||||
writeBoolean(0, isAccepted);
|
||||
}
|
||||
}
|
||||
+4
@@ -35,4 +35,8 @@ public class WrappedPacketInTrSel extends WrappedPacket {
|
||||
public int getSlot() {
|
||||
return readInt(0);
|
||||
}
|
||||
|
||||
public void setSlot(int slot) {
|
||||
writeInt(0, slot);
|
||||
}
|
||||
}
|
||||
+36
-50
@@ -27,9 +27,9 @@ package io.github.retrooper.packetevents.packetwrappers.play.in.updatesign;
|
||||
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.play.out.chat.WrappedPacketOutChat;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
import io.github.retrooper.packetevents.utils.reflection.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.vector.Vector3i;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
@@ -37,8 +37,6 @@ public class WrappedPacketInUpdateSign extends WrappedPacket {
|
||||
private static boolean v_1_7_mode, strArrayMode;
|
||||
private static Class<?> blockPosClass;
|
||||
|
||||
private Object blockPosObj;
|
||||
|
||||
public WrappedPacketInUpdateSign(NMSPacket packet) {
|
||||
super(packet);
|
||||
}
|
||||
@@ -47,77 +45,65 @@ public class WrappedPacketInUpdateSign extends WrappedPacket {
|
||||
protected void load() {
|
||||
v_1_7_mode = Reflection.getField(PacketTypeClasses.Play.Client.UPDATE_SIGN, int.class, 0) != null;
|
||||
strArrayMode = Reflection.getField(PacketTypeClasses.Play.Client.UPDATE_SIGN, String[].class, 0) != null;
|
||||
|
||||
try {
|
||||
blockPosClass = NMSUtils.getNMSClass("BlockPosition");
|
||||
} catch (ClassNotFoundException e) {
|
||||
if (!v_1_7_mode) {
|
||||
if (!v_1_7_mode) {
|
||||
try {
|
||||
blockPosClass = NMSUtils.getNMSClass("BlockPosition");
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
public Vector3i getBlockPosition() {
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int z = 0;
|
||||
if (v_1_7_mode) {
|
||||
return readInt(0);
|
||||
x = readInt(0);
|
||||
y = readInt(1);
|
||||
z = readInt(2);
|
||||
|
||||
} else {
|
||||
if (blockPosObj == null) {
|
||||
blockPosObj = readObject(0, blockPosClass);
|
||||
}
|
||||
Object blockPosObj = readObject(0, blockPosClass);
|
||||
try {
|
||||
return (int) Reflection.getMethod(blockPosObj.getClass().getSuperclass(), "getX", 0).invoke(blockPosObj);
|
||||
x = (int) NMSUtils.getBlockPosX.invoke(blockPosObj);
|
||||
y = (int) NMSUtils.getBlockPosY.invoke(blockPosObj);
|
||||
z = (int) NMSUtils.getBlockPosZ.invoke(blockPosObj);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return new Vector3i(x, y, z);
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
public void setBlockPosition(Vector3i blockPos) {
|
||||
if (v_1_7_mode) {
|
||||
return readInt(1);
|
||||
writeInt(0, blockPos.x);
|
||||
writeInt(1, blockPos.y);
|
||||
writeInt(2, blockPos.z);
|
||||
} else {
|
||||
if (blockPosObj == null) {
|
||||
blockPosObj = readObject(0, blockPosClass);
|
||||
}
|
||||
try {
|
||||
return (int) Reflection.getMethod(blockPosObj.getClass().getSuperclass(), "getY", 0).invoke(blockPosObj);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public int getZ() {
|
||||
if (v_1_7_mode) {
|
||||
return readInt(2);
|
||||
} else {
|
||||
if (blockPosObj == null) {
|
||||
blockPosObj = readObject(0, blockPosClass);
|
||||
}
|
||||
try {
|
||||
return (int) Reflection.getMethod(blockPosObj.getClass().getSuperclass(), "getZ", 0).invoke(blockPosObj);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return -1;
|
||||
Object blockPosObj = NMSUtils.generateNMSBlockPos(blockPos.x, blockPos.y, blockPos.z);
|
||||
write(NMSUtils.blockPosClass, 0, blockPosObj);
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getTextLines() {
|
||||
if (strArrayMode) {
|
||||
//1.7.10 and the newest versions use this
|
||||
//1.7.10
|
||||
return readStringArray(0);
|
||||
} else {
|
||||
//1.8 uses this for example
|
||||
//1.8 and above
|
||||
Object[] iChatComponents = (Object[]) readAnyObject(1);
|
||||
String[] lines = new String[iChatComponents.length];
|
||||
for (int i = 0; i < iChatComponents.length; i++) {
|
||||
lines[i] = WrappedPacketOutChat.
|
||||
toStringFromIChatBaseComponent(iChatComponents[i]);
|
||||
}
|
||||
return lines;
|
||||
return NMSUtils.readIChatBaseComponents(iChatComponents);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTextLines(String[] lines) {
|
||||
if (strArrayMode) {
|
||||
writeStringArray(0, lines);
|
||||
} else {
|
||||
Object[] iChatComponents = NMSUtils.generateIChatBaseComponents(lines);
|
||||
writeAnyObject(1, iChatComponents);
|
||||
}
|
||||
}
|
||||
}
|
||||
+38
-47
@@ -27,20 +27,20 @@ package io.github.retrooper.packetevents.packetwrappers.play.in.useentity;
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.api.helper.WrappedPacketEntityAbstraction;
|
||||
import io.github.retrooper.packetevents.utils.enums.EnumUtil;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
import io.github.retrooper.packetevents.utils.player.Hand;
|
||||
import io.github.retrooper.packetevents.utils.reflection.SubclassUtil;
|
||||
import io.github.retrooper.packetevents.utils.server.ServerVersion;
|
||||
import io.github.retrooper.packetevents.utils.vector.Vector3d;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
public final class WrappedPacketInUseEntity extends WrappedPacket {
|
||||
private static Class<?> enumEntityUseActionClass, enumHandClass;
|
||||
private Entity entity;
|
||||
public final class WrappedPacketInUseEntity extends WrappedPacketEntityAbstraction {
|
||||
private static Class<? extends Enum<?>> enumEntityUseActionClass, enumHandClass;
|
||||
private EntityUseAction action;
|
||||
private int entityId = -1;
|
||||
|
||||
public WrappedPacketInUseEntity(final NMSPacket packet) {
|
||||
super(packet);
|
||||
@@ -50,72 +50,54 @@ public final class WrappedPacketInUseEntity extends WrappedPacket {
|
||||
protected void load() {
|
||||
Class<?> useEntityClass = NMSUtils.getNMSClassWithoutException("PacketPlayInUseEntity");
|
||||
try {
|
||||
enumHandClass = NMSUtils.getNMSClass("EnumHand");
|
||||
enumHandClass = NMSUtils.getNMSEnumClass("EnumHand");
|
||||
} catch (ClassNotFoundException e) {
|
||||
//Probably a 1.7.10 or 1.8.x server
|
||||
}
|
||||
try {
|
||||
enumEntityUseActionClass = NMSUtils.getNMSClass("EnumEntityUseAction");
|
||||
enumEntityUseActionClass = NMSUtils.getNMSEnumClass("EnumEntityUseAction");
|
||||
} catch (ClassNotFoundException e) {
|
||||
//That is fine, it is probably a subclass
|
||||
enumEntityUseActionClass = SubclassUtil.getSubClass(Objects.requireNonNull(useEntityClass), "EnumEntityUseAction");
|
||||
enumEntityUseActionClass = SubclassUtil.getEnumSubClass(useEntityClass, "EnumEntityUseAction");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Lookup the associated entity by the ID that was sent in the packet.
|
||||
*
|
||||
* @return Entity
|
||||
*/
|
||||
public Entity getEntity() {
|
||||
if (entity != null) {
|
||||
return entity;
|
||||
public Optional<Vector3d> getTarget() {
|
||||
if (PacketEvents.get().getServerUtils().getVersion() == ServerVersion.v_1_7_10
|
||||
|| getAction() != EntityUseAction.INTERACT_AT) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return entity = NMSUtils.getEntityById(getEntityId());
|
||||
Object vec3DObj = readObject(0, NMSUtils.vec3DClass);
|
||||
WrappedPacket vec3DWrapper = new WrappedPacket(new NMSPacket(vec3DObj));
|
||||
return Optional.of(new Vector3d(vec3DWrapper.readDouble(0), vec3DWrapper.readDouble(1), vec3DWrapper.readDouble(2)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ID of the entity.
|
||||
* If you do not want to use {@link #getEntity()},
|
||||
* you lookup the entity by yourself with this entity ID.
|
||||
*
|
||||
* @return Entity ID
|
||||
*/
|
||||
public int getEntityId() {
|
||||
if (entityId != -1) {
|
||||
return entityId;
|
||||
public void setTarget(Vector3d target) {
|
||||
if (PacketEvents.get().getServerUtils().getVersion() != ServerVersion.v_1_7_10
|
||||
&& getAction() == EntityUseAction.INTERACT_AT) {
|
||||
Object vec3DObj = NMSUtils.generateVec3D(target.x, target.y, target.z);
|
||||
write(NMSUtils.vec3DClass, 0, vec3DObj);
|
||||
}
|
||||
return entityId = readInt(0);
|
||||
}
|
||||
|
||||
public Vector3d getTarget() {
|
||||
if (getAction() == EntityUseAction.INTERACT_AT
|
||||
&& PacketEvents.get().getServerUtils().getVersion() != ServerVersion.v_1_7_10) {
|
||||
Object vec3DObj = readObject(0, NMSUtils.vec3DClass);
|
||||
WrappedPacket vec3DWrapper = new WrappedPacket(new NMSPacket(vec3DObj));
|
||||
return new Vector3d(vec3DWrapper.readDouble(0), vec3DWrapper.readDouble(1), vec3DWrapper.readDouble(2));
|
||||
}
|
||||
return Vector3d.INVALID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the associated action.
|
||||
*
|
||||
* @return Get EntityUseAction
|
||||
*/
|
||||
public EntityUseAction getAction() {
|
||||
if (action == null) {
|
||||
final Object useActionEnum = readObject(0, enumEntityUseActionClass);
|
||||
Enum<?> useActionEnum = readEnumConstant(0, enumEntityUseActionClass);
|
||||
if (useActionEnum == null) {
|
||||
//ur spigot sucks bruh, unfortunately some spigots have such a bug?
|
||||
//This happens on some weird spigots apparently? Not sure why this field is null.
|
||||
return EntityUseAction.INTERACT;
|
||||
}
|
||||
return action = EntityUseAction.valueOf(useActionEnum.toString());
|
||||
return action = EntityUseAction.valueOf(useActionEnum.name());
|
||||
}
|
||||
return action;
|
||||
}
|
||||
|
||||
public void setAction(EntityUseAction action) {
|
||||
this.action = action;
|
||||
Enum<?> enumConst = EnumUtil.valueOf(enumEntityUseActionClass, action.name());
|
||||
writeEnumConstant(0, enumConst);
|
||||
}
|
||||
|
||||
public Hand getHand() {
|
||||
if ((getAction() == EntityUseAction.INTERACT || getAction() == EntityUseAction.INTERACT_AT)
|
||||
&& PacketEvents.get().getServerUtils().getVersion().isNewerThan(ServerVersion.v_1_8_8)) {
|
||||
@@ -129,6 +111,15 @@ public final class WrappedPacketInUseEntity extends WrappedPacket {
|
||||
return Hand.MAIN_HAND;
|
||||
}
|
||||
|
||||
public void setHand(Hand hand) {
|
||||
if (PacketEvents.get().getServerUtils().getVersion().isNewerThanOrEquals(ServerVersion.v_1_9) &&
|
||||
(getAction() == EntityUseAction.INTERACT || getAction() == EntityUseAction.INTERACT_AT)) {
|
||||
|
||||
Enum<?> enumConst = EnumUtil.valueOf(enumHandClass, hand.name());
|
||||
writeEnumConstant(0, enumConst);
|
||||
}
|
||||
}
|
||||
|
||||
public enum EntityUseAction {
|
||||
INTERACT, INTERACT_AT, ATTACK
|
||||
}
|
||||
|
||||
Loaded 100 of 204 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user