Compare commits
132
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>io.github.retrooper</groupId>
|
||||
<artifactId>packetevents</artifactId>
|
||||
<version>1.8-PRE-2</version>
|
||||
<version>1.8-pre-10</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,63 @@ 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.reflection.Reflection;
|
||||
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 org.spigotmc.SpigotConfig;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.UUID;
|
||||
import java.lang.reflect.Field;
|
||||
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, 10);
|
||||
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() {
|
||||
@@ -112,88 +117,107 @@ public final class PacketEvents implements Listener, EventManager {
|
||||
WrappedPacket.version = version;
|
||||
NMSUtils.version = version;
|
||||
EntityFinderUtils.version = version;
|
||||
|
||||
handlerName = "pe-" + plugin.getName();
|
||||
try {
|
||||
Field lateBindField = Reflection.getField(SpigotConfig.class, "lateBind");
|
||||
if (lateBindField != null && lateBindField.getBoolean(null)) {
|
||||
throw new IllegalStateException("Please disable late-bind in your Spigot config, late-bind is not supported!");
|
||||
}
|
||||
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 +225,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 +233,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 +295,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,39 @@
|
||||
|
||||
package io.github.retrooper.packetevents;
|
||||
|
||||
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
|
||||
import io.github.retrooper.packetevents.event.impl.PacketPlayReceiveEvent;
|
||||
import io.github.retrooper.packetevents.packettype.PacketType;
|
||||
import io.github.retrooper.packetevents.settings.PacketEventsSettings;
|
||||
import io.github.retrooper.packetevents.utils.gameprofile.WrappedGameProfile;
|
||||
import io.github.retrooper.packetevents.utils.gameprofile.WrappedProperty;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public class PacketEventsPlugin extends JavaPlugin {
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.util.UUID;
|
||||
|
||||
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.compatInjector(false);
|
||||
settings.checkForUpdates(false);
|
||||
instance.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 PacketListenerDynamic listener) {
|
||||
listener.onPacketEventExternal(this);
|
||||
}
|
||||
|
||||
public boolean isInbuilt() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ 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;
|
||||
|
||||
/**
|
||||
* Dynamic packet event listener.
|
||||
@@ -37,31 +38,144 @@ import io.github.retrooper.packetevents.event.priority.PacketEventPriority;
|
||||
*/
|
||||
public abstract class PacketListenerDynamic {
|
||||
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 PacketListenerDynamic(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 PacketListenerDynamic() {
|
||||
this(PacketEventPriority.NORMAL);
|
||||
}
|
||||
|
||||
public PacketEventPriority getPriority() {
|
||||
public final PacketEventPriority getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
public void onPacketStatusReceive(PacketStatusReceiveEvent 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<>();
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -77,7 +191,6 @@ public abstract class PacketListenerDynamic {
|
||||
}
|
||||
|
||||
public void onPostPlayerInject(PostPlayerInjectEvent event) {
|
||||
|
||||
}
|
||||
|
||||
public void onPlayerInject(PlayerInjectEvent event) {
|
||||
@@ -86,6 +199,6 @@ public abstract class PacketListenerDynamic {
|
||||
public void onPlayerEject(PlayerEjectEvent event) {
|
||||
}
|
||||
|
||||
public void onPacketEvent(PacketEvent event) {
|
||||
public void onPacketEventExternal(PacketEvent event) {
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ import io.github.retrooper.packetevents.event.impl.PacketPlayReceiveEvent;
|
||||
* The {@link PacketEvent} implements this interface.
|
||||
* Every inbuilt event should implement the {@link #call(PacketListenerDynamic)} 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 PacketListenerDynamic#onPacketEventExternal(PacketEvent)} method is called for every event that is not in-built.
|
||||
* including custom events.
|
||||
*
|
||||
* @author retrooper
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package io.github.retrooper.packetevents.event.impl;
|
||||
|
||||
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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(PacketListenerDynamic listener) {
|
||||
if (listener.clientSidedLoginAllowance == null || listener.clientSidedLoginAllowance.contains(getPacketId())) {
|
||||
listener.onPacketHandshakeReceive(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-15
@@ -50,22 +50,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);
|
||||
if (listener.clientSidedLoginAllowance == null || listener.clientSidedLoginAllowance.contains(getPacketId())) {
|
||||
listener.onPacketLoginReceive(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -50,13 +50,10 @@ public class PacketLoginSendEvent extends CancellableNMSPacketEvent {
|
||||
super(address, packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getPacketId() {
|
||||
return PacketType.Login.Server.packetIds.getOrDefault(packet.getRawNMSPacket().getClass(), PacketType.INVALID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void call(PacketListenerDynamic listener) {
|
||||
listener.onPacketLoginSend(this);
|
||||
if (listener.serverSidedLoginAllowance == null || listener.serverSidedLoginAllowance.contains(getPacketId())) {
|
||||
listener.onPacketLoginSend(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-25
@@ -45,7 +45,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 +62,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);
|
||||
if (listener.clientSidedPlayAllowance == null || listener.clientSidedPlayAllowance.contains(getPacketId())) {
|
||||
listener.onPacketPlayReceive(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,9 +29,12 @@ import io.github.retrooper.packetevents.event.eventtypes.CancellableNMSPacketEve
|
||||
import io.github.retrooper.packetevents.event.eventtypes.PlayerEvent;
|
||||
import io.github.retrooper.packetevents.packettype.PacketType;
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* The {@code PacketPlaySendEvent} event is fired whenever the a PLAY packet is about to be sent.
|
||||
* Cancelling this event will result in preventing minecraft from sending the packet.
|
||||
@@ -61,23 +64,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);
|
||||
if (listener.serverSidedPlayAllowance == null || listener.serverSidedPlayAllowance.contains(getPacketId())) {
|
||||
listener.onPacketPlaySend(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-15
@@ -50,22 +50,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);
|
||||
if (listener.clientSidedStatusAllowance == null || listener.clientSidedStatusAllowance.contains(getPacketId())) {
|
||||
listener.onPacketStatusReceive(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-14
@@ -52,22 +52,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);
|
||||
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.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) {
|
||||
listener.onPlayerEject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInbuilt() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -29,10 +29,8 @@ 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.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) {
|
||||
listener.onPlayerInject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInbuilt() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+3
-18
@@ -30,7 +30,6 @@ 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 +53,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);
|
||||
if (listener.clientSidedPlayAllowance == null || listener.clientSidedPlayAllowance.contains(getPacketId())) {
|
||||
listener.onPostPacketPlayReceive(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-18
@@ -30,7 +30,6 @@ 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 +53,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);
|
||||
if (listener.serverSidedPlayAllowance == null || listener.serverSidedPlayAllowance.contains(getPacketId())) {
|
||||
listener.onPostPacketPlaySend(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -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
|
||||
@@ -107,4 +107,9 @@ public class PostPlayerInjectEvent extends PacketEvent implements PlayerEvent {
|
||||
public void call(PacketListenerDynamic listener) {
|
||||
listener.onPostPlayerInject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInbuilt() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -136,29 +136,6 @@ public interface EventManager {
|
||||
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);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister all registered event listeners.
|
||||
* All the deprecated and the dynamic listeners will be unregistered.
|
||||
|
||||
+35
-68
@@ -30,16 +30,13 @@ 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.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
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<>();
|
||||
private final Map<Byte, HashSet<PacketListenerDynamic>> listenersMap = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Call the PacketEvent.
|
||||
@@ -58,26 +55,28 @@ class EventManagerDynamic {
|
||||
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();
|
||||
for (byte priority = PacketEventPriority.LOWEST.getPriorityValue(); priority <= PacketEventPriority.MONITOR.getPriorityValue(); priority++) {
|
||||
HashSet<PacketListenerDynamic> listeners = listenersMap.get(priority);
|
||||
if (listeners != null) {
|
||||
for (PacketListenerDynamic 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (event instanceof CancellableEvent) {
|
||||
CancellableEvent ce = (CancellableEvent) event;
|
||||
ce.setCancelled(cancel);
|
||||
}
|
||||
|
||||
PEEventManager.EVENT_MANAGER_LEGACY.callEvent(event, highestReachedPriority);
|
||||
}
|
||||
|
||||
@@ -86,26 +85,14 @@ class EventManagerDynamic {
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
public synchronized void registerListener(final PacketListenerDynamic listener) {
|
||||
byte priority = listener.getPriority().getPriorityValue();
|
||||
HashSet<PacketListenerDynamic> listenerSet = listenersMap.get(priority);
|
||||
if (listenerSet == null) {
|
||||
listenerSet = new HashSet<>();
|
||||
}
|
||||
listenerSet.add(listener);
|
||||
listenersMap.put(priority, listenerSet);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -113,36 +100,16 @@ class EventManagerDynamic {
|
||||
*
|
||||
* @param listeners {@link PacketListenerDynamic}
|
||||
*/
|
||||
public void registerListeners(PacketListenerDynamic... listeners) {
|
||||
public synchronized 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();
|
||||
public synchronized void unregisterAllListeners() {
|
||||
listenersMap.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -163,4 +163,4 @@ class EventManagerLegacy {
|
||||
public void unregisterAllListeners() {
|
||||
staticRegisteredMethods.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
-19
@@ -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);
|
||||
}
|
||||
+49
-34
@@ -1,65 +1,80 @@
|
||||
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.earlyinjector.EarlyInjector;
|
||||
import io.github.retrooper.packetevents.injector.earlyinjector.legacy.EarlyChannelInjectorLegacy;
|
||||
import io.github.retrooper.packetevents.injector.earlyinjector.modern.EarlyChannelInjectorModern;
|
||||
import io.github.retrooper.packetevents.injector.lateinjector.legacy.LateChannelInjectorLegacy;
|
||||
import io.github.retrooper.packetevents.injector.lateinjector.modern.LateChannelInjectorModern;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
-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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
-6
@@ -1,13 +1,34 @@
|
||||
/*
|
||||
* 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.injector.ChannelInjector;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public interface EarlyInjector extends ChannelInjector {
|
||||
void prepare();
|
||||
void updatePlayerObject(Player player, Object channel);
|
||||
|
||||
void cleanup();
|
||||
|
||||
Object injectChannel(Object channel);
|
||||
|
||||
void ejectChannel(Object channel);
|
||||
boolean isBound();
|
||||
}
|
||||
+318
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
* 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.legacy;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.injector.earlyinjector.EarlyInjector;
|
||||
import io.github.retrooper.packetevents.injector.handler.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 io.github.retrooper.packetevents.utils.reflection.Reflection;
|
||||
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.
|
||||
Reflection.updateFinalField(bootstrapAcceptorField, 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) {
|
||||
Reflection.updateFinalField(childHandlerField, bootstrapAcceptor, oldInit);
|
||||
Reflection.updateFinalField(childHandlerField,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.earlyinjector.legacy;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.injector.handler.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+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.earlyinjector.modern;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.injector.earlyinjector.EarlyInjector;
|
||||
import io.github.retrooper.packetevents.injector.handler.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.github.retrooper.packetevents.utils.reflection.Reflection;
|
||||
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.
|
||||
Reflection.updateFinalField(bootstrapAcceptorField, 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) {
|
||||
Reflection.updateFinalField(childHandlerField, bootstrapAcceptor, oldInit);
|
||||
Reflection.updateFinalField(childHandlerField, 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.earlyinjector.modern;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.injector.handler.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.handler.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;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.handler.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;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
-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);
|
||||
}
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.legacy;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.injector.handler.legacy.PlayerChannelHandlerLegacy;
|
||||
import io.github.retrooper.packetevents.injector.lateinjector.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();
|
||||
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);
|
||||
}
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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.modern;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.injector.handler.modern.PlayerChannelHandlerModern;
|
||||
import io.github.retrooper.packetevents.injector.lateinjector.LateInjector;
|
||||
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 LateChannelInjectorModern implements LateInjector {
|
||||
@Override
|
||||
public void inject() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eject() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectPlayer(Player player) {
|
||||
PlayerChannelHandlerModern playerChannelHandlerModern = new PlayerChannelHandlerModern();
|
||||
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
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import io.github.retrooper.packetevents.utils.server.ServerVersion;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Packet Type IDs.
|
||||
@@ -43,7 +44,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 HashMap<>();
|
||||
|
||||
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 +82,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 +97,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 +143,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 +159,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 +186,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 +289,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 +303,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,26 @@
|
||||
|
||||
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.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 +51,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 +76,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 +97,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 +243,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 +251,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 +269,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 +284,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 +334,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 +403,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 +425,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 {};
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -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);
|
||||
}
|
||||
+21
-2
@@ -25,8 +25,6 @@
|
||||
package io.github.retrooper.packetevents.packetwrappers;
|
||||
|
||||
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);
|
||||
}
|
||||
+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);
|
||||
}
|
||||
}
|
||||
+11
-3
@@ -30,9 +30,6 @@ 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;
|
||||
@@ -54,6 +51,10 @@ public class WrappedPacketLoginInCustomPayload extends WrappedPacket {
|
||||
return readInt(0);
|
||||
}
|
||||
|
||||
public void setMessageId(int id) {
|
||||
writeInt(0, id);
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
Object dataSerializer = readObject(0, packetDataSerializerClass);
|
||||
WrappedPacket byteBufWrapper = new WrappedPacket(new NMSPacket(dataSerializer));
|
||||
@@ -61,6 +62,13 @@ public class WrappedPacketLoginInCustomPayload extends WrappedPacket {
|
||||
return PacketEvents.get().getByteBufUtil().getBytes(byteBuf);
|
||||
}
|
||||
|
||||
public void setData(byte[] data) {
|
||||
Object dataSerializer = readObject(0, packetDataSerializerClass);
|
||||
WrappedPacket dataSerializerWrapper = new WrappedPacket(new NMSPacket(dataSerializer));
|
||||
Object byteBuf = dataSerializerWrapper.readObject(0, byteBufClass);
|
||||
PacketEvents.get().getByteBufUtil().setBytes(byteBuf, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported() {
|
||||
return version.isNewerThan(ServerVersion.v_1_12_2);
|
||||
|
||||
+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;
|
||||
|
||||
+25
-1
@@ -81,14 +81,31 @@ 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);
|
||||
@@ -99,6 +116,13 @@ public class WrappedPacketLoginOutCustomPayload extends WrappedPacket implements
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(byte[] data) {
|
||||
Object dataSerializer = readObject(0, packetDataSerializerClass);
|
||||
WrappedPacket dataSerializerWrapper = new WrappedPacket(new NMSPacket(dataSerializer));
|
||||
Object byteBuf = dataSerializerWrapper.readObject(0, byteBufClass);
|
||||
PacketEvents.get().getByteBufUtil().setBytes(byteBuf, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object asNMSPacket() {
|
||||
Object byteBufObject = PacketEvents.get().getByteBufUtil().wrappedBuffer(data);
|
||||
|
||||
+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;
|
||||
|
||||
+11
-2
@@ -28,6 +28,7 @@ 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.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;
|
||||
|
||||
+66
-11
@@ -28,6 +28,7 @@ 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;
|
||||
|
||||
public final class WrappedPacketInAbilities extends WrappedPacket {
|
||||
private static boolean v_1_16_Mode;
|
||||
@@ -41,21 +42,35 @@ public final class WrappedPacketInAbilities extends WrappedPacket {
|
||||
v_1_16_Mode = Reflection.getField(PacketTypeClasses.Play.Client.ABILITIES, boolean.class, 1) == null;
|
||||
}
|
||||
|
||||
public boolean isFlying() {
|
||||
return readBoolean(v_1_16_Mode ? 0 : 1);
|
||||
}
|
||||
|
||||
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 the player is vulnerable to damage or not.
|
||||
*/
|
||||
@SupportedVersions(ranges = {ServerVersion.v_1_7_10, ServerVersion.v_1_15_2})
|
||||
@Deprecated
|
||||
public boolean isVulnerable() throws UnsupportedOperationException {
|
||||
if (v_1_16_Mode) {
|
||||
throw new UnsupportedOperationException("This field does not exist on your version!");
|
||||
throwUnsupportedOperation();
|
||||
}
|
||||
return readBoolean(0);
|
||||
}
|
||||
|
||||
public boolean isFlying() {
|
||||
return readBoolean(v_1_16_Mode ? 0 : 1);
|
||||
@SupportedVersions(ranges = {ServerVersion.v_1_7_10, ServerVersion.v_1_15_2})
|
||||
@Deprecated
|
||||
public void setVulnerable(boolean vulnerable) throws UnsupportedOperationException {
|
||||
if (v_1_16_Mode) {
|
||||
throwUnsupportedOperation();
|
||||
}
|
||||
writeBoolean(0, vulnerable);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,50 +78,90 @@ public final class WrappedPacketInAbilities extends WrappedPacket {
|
||||
*
|
||||
* @return Whether or not the player can fly.
|
||||
*/
|
||||
@SupportedVersions(ranges = {ServerVersion.v_1_7_10, ServerVersion.v_1_15_2})
|
||||
@Deprecated
|
||||
public boolean isFlightAllowed() {
|
||||
public boolean isFlightAllowed() throws UnsupportedOperationException {
|
||||
if (v_1_16_Mode) {
|
||||
throw new UnsupportedOperationException("This field does not exist on your version!");
|
||||
throwUnsupportedOperation();
|
||||
}
|
||||
return readBoolean(2);
|
||||
}
|
||||
|
||||
@SupportedVersions(ranges = {ServerVersion.v_1_7_10, ServerVersion.v_1_15_2})
|
||||
@Deprecated
|
||||
public void setFlightAllowed(boolean flightAllowed) throws UnsupportedOperationException {
|
||||
if (v_1_16_Mode) {
|
||||
throwUnsupportedOperation();
|
||||
}
|
||||
writeBoolean(2, flightAllowed);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@SupportedVersions(ranges = {ServerVersion.v_1_7_10, ServerVersion.v_1_15_2})
|
||||
@Deprecated
|
||||
public boolean canInstantlyBuild() {
|
||||
public boolean canInstantlyBuild() throws UnsupportedOperationException {
|
||||
if (v_1_16_Mode) {
|
||||
throw new UnsupportedOperationException("This field does not exist on your version!");
|
||||
throwUnsupportedOperation();
|
||||
}
|
||||
return readBoolean(3);
|
||||
}
|
||||
|
||||
@SupportedVersions(ranges = {ServerVersion.v_1_7_10, ServerVersion.v_1_15_2})
|
||||
@Deprecated
|
||||
public void setCanInstantlyBuild(boolean canInstantlyBuild) throws UnsupportedOperationException {
|
||||
if (v_1_16_Mode) {
|
||||
throwUnsupportedOperation();
|
||||
}
|
||||
writeBoolean(3, canInstantlyBuild);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@SupportedVersions(ranges = {ServerVersion.v_1_7_10, ServerVersion.v_1_15_2})
|
||||
@Deprecated
|
||||
public float getFlySpeed() {
|
||||
public float getFlySpeed() throws UnsupportedOperationException {
|
||||
if (v_1_16_Mode) {
|
||||
throw new UnsupportedOperationException("This field does not exist on your version!");
|
||||
throwUnsupportedOperation();
|
||||
}
|
||||
return readFloat(0);
|
||||
}
|
||||
|
||||
@SupportedVersions(ranges = {ServerVersion.v_1_7_10, ServerVersion.v_1_15_2})
|
||||
@Deprecated
|
||||
public void setFlySpeed(float flySpeed) throws UnsupportedOperationException {
|
||||
if (v_1_16_Mode) {
|
||||
throwUnsupportedOperation();
|
||||
}
|
||||
writeFloat(0, flySpeed);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@SupportedVersions(ranges = {ServerVersion.v_1_7_10, ServerVersion.v_1_15_2})
|
||||
@Deprecated
|
||||
public float getWalkSpeed() {
|
||||
public float getWalkSpeed() throws UnsupportedOperationException {
|
||||
if (v_1_16_Mode) {
|
||||
throw new UnsupportedOperationException("This field does not exist on your version!");
|
||||
throwUnsupportedOperation();
|
||||
}
|
||||
return readFloat(1);
|
||||
}
|
||||
|
||||
@SupportedVersions(ranges = {ServerVersion.v_1_7_10, ServerVersion.v_1_15_2})
|
||||
@Deprecated
|
||||
public void setWalkSpeed(float walkSpeed) throws UnsupportedOperationException {
|
||||
if (v_1_16_Mode) {
|
||||
throwUnsupportedOperation();
|
||||
}
|
||||
writeFloat(1, walkSpeed);
|
||||
}
|
||||
}
|
||||
+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
|
||||
}
|
||||
|
||||
+117
-44
@@ -26,12 +26,19 @@ 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;
|
||||
|
||||
|
||||
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 +46,127 @@ 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 = read(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 = new Vector3i();
|
||||
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;
|
||||
}
|
||||
|
||||
@SupportedVersions(ranges = {ServerVersion.v_1_7_10, ServerVersion.v_1_8_8})
|
||||
@Deprecated
|
||||
public Vector3f getCursorPosition() throws UnsupportedOperationException {
|
||||
if (newerThan_v_1_8_8) {
|
||||
throwUnsupportedOperation();
|
||||
return Vector3f.INVALID;
|
||||
} else if (newerThan_v_1_7_10) {
|
||||
WrappedPacketInBlockPlace_1_8 blockPlace_1_8 = new WrappedPacketInBlockPlace_1_8(packet);
|
||||
return blockPlace_1_8.getCursorPosition();
|
||||
} else {
|
||||
WrappedPacketInBlockPlace_1_7_10 blockPlace_1_7_10 = new WrappedPacketInBlockPlace_1_7_10(packet);
|
||||
return blockPlace_1_7_10.getCursorPosition();
|
||||
}
|
||||
}
|
||||
|
||||
@SupportedVersions(ranges = {ServerVersion.v_1_7_10, ServerVersion.v_1_8_8})
|
||||
@Deprecated
|
||||
public void setCursorPosition(Vector3f cursorPos) throws UnsupportedOperationException {
|
||||
if (newerThan_v_1_8_8) {
|
||||
throwUnsupportedOperation();
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
||||
@SupportedVersions(ranges = {ServerVersion.v_1_7_10, ServerVersion.v_1_8_8})
|
||||
public ItemStack getItemStack() throws UnsupportedOperationException {
|
||||
if (newerThan_v_1_8_8) {
|
||||
throwUnsupportedOperation();
|
||||
return null;
|
||||
} else if (newerThan_v_1_7_10) {
|
||||
WrappedPacketInBlockPlace_1_8 blockPlace_1_8 = new WrappedPacketInBlockPlace_1_8(packet);
|
||||
return blockPlace_1_8.getItemStack();
|
||||
} else {
|
||||
WrappedPacketInBlockPlace_1_7_10 blockPlace_1_7_10 = new WrappedPacketInBlockPlace_1_7_10(packet);
|
||||
return blockPlace_1_7_10.getItemStack();
|
||||
}
|
||||
}
|
||||
|
||||
@SupportedVersions(ranges = {ServerVersion.v_1_7_10, ServerVersion.v_1_8_8})
|
||||
public void setItemStack(ItemStack stack) throws UnsupportedOperationException {
|
||||
if (newerThan_v_1_8_8) {
|
||||
throwUnsupportedOperation();
|
||||
} 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.x, 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);
|
||||
}
|
||||
}
|
||||
+4
-5
@@ -32,12 +32,11 @@ public final class WrappedPacketInChat extends WrappedPacket {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message.
|
||||
*
|
||||
* @return Chat Message
|
||||
*/
|
||||
public String getMessage() {
|
||||
return readString(0);
|
||||
}
|
||||
|
||||
public void setMessage(String 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);
|
||||
}
|
||||
}
|
||||
+23
-2
@@ -62,16 +62,37 @@ 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));
|
||||
WrappedPacket dataSerializerWrapper = new WrappedPacket(new NMSPacket(dataSerializer));
|
||||
|
||||
Object byteBuf = byteBufWrapper.readObject(0, byteBufClass);
|
||||
Object byteBuf = dataSerializerWrapper.readObject(0, byteBufClass);
|
||||
|
||||
return PacketEvents.get().getByteBufUtil().getBytes(byteBuf);
|
||||
}
|
||||
}
|
||||
|
||||
public void setData(byte[] data) {
|
||||
if (byteArrayPresent) {
|
||||
writeByteArray(0, data);
|
||||
} else {
|
||||
Object dataSerializer = readObject(0, packetDataSerializerClass);
|
||||
WrappedPacket dataSerializerWrapper = new WrappedPacket(new NMSPacket(dataSerializer));
|
||||
|
||||
Object byteBuf = dataSerializerWrapper.readObject(0, byteBufClass);
|
||||
PacketEvents.get().getByteBufUtil().setBytes(byteBuf, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
+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);
|
||||
}
|
||||
}
|
||||
+128
-68
@@ -27,20 +27,19 @@ 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 static Class<? extends Enum<?>> enumPlayerActionClass;
|
||||
private static boolean newerThan_v_1_8_8;
|
||||
private Entity entity;
|
||||
private int entityId = -1;
|
||||
private int entityID = -1;
|
||||
|
||||
public WrappedPacketInEntityAction(final NMSPacket packet) {
|
||||
super(packet);
|
||||
@@ -48,94 +47,155 @@ 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
|
||||
*/
|
||||
@Nullable
|
||||
public Entity getEntity() {
|
||||
return getEntity(null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Entity getEntity(@Nullable World world) {
|
||||
if (entity == null) {
|
||||
return entity = NMSUtils.getEntityById(getEntityId());
|
||||
entity = NMSUtils.getEntityById(world, 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 void setEntity(Entity entity) {
|
||||
setEntityId(entity.getEntityId());
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
public int getEntityId() {
|
||||
if (entityId == -1) {
|
||||
entityId = readInt(0);
|
||||
if (entityID == -1) {
|
||||
entityID = readInt(0);
|
||||
}
|
||||
return entityId;
|
||||
return entityID;
|
||||
}
|
||||
|
||||
public void setEntityId(int entityID) {
|
||||
writeInt(0, this.entityID = entityID);
|
||||
this.entity = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
+11
-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,15 @@ public final class WrappedPacketInKeepAlive extends WrappedPacket {
|
||||
return readInt(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void setId(long id) throws UnsupportedOperationException {
|
||||
if (!integerPresentInIndex0) {
|
||||
writeLong(0, id);
|
||||
} else {
|
||||
if (id > Integer.MAX_VALUE || id < Integer.MAX_VALUE) {
|
||||
throw new UnsupportedOperationException("PacketEvents failed to set the Keep Alive ID in WrappedPacketInKeepAlive. Your server version does not support IDs outside the range of an int primitive type. Your Keep Alive ID seems to be in the range of a long primitive type.");
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+72
-37
@@ -27,20 +27,23 @@ 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.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.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public final class WrappedPacketInUseEntity extends WrappedPacket {
|
||||
private static Class<?> enumEntityUseActionClass, enumHandClass;
|
||||
private static Class<? extends Enum<?>> enumEntityUseActionClass, enumHandClass;
|
||||
private Entity entity;
|
||||
private EntityUseAction action;
|
||||
private int entityId = -1;
|
||||
private int entityID = -1;
|
||||
|
||||
public WrappedPacketInUseEntity(final NMSPacket packet) {
|
||||
super(packet);
|
||||
@@ -50,72 +53,94 @@ 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
|
||||
*/
|
||||
@Nullable
|
||||
public Entity getEntity() {
|
||||
if (entity != null) {
|
||||
return entity;
|
||||
}
|
||||
return entity = NMSUtils.getEntityById(getEntityId());
|
||||
return getEntity(null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Entity getEntity(@Nullable World world) {
|
||||
if (entity == null) {
|
||||
entity = NMSUtils.getEntityById(world, getEntityId());
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
public void setEntity(Entity entity) {
|
||||
setEntityId(entity.getEntityId());
|
||||
this.entity = 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) {
|
||||
return entityId;
|
||||
if (entityID != -1) {
|
||||
return entityID;
|
||||
}
|
||||
return entityId = readInt(0);
|
||||
return entityID = readInt(0);
|
||||
}
|
||||
|
||||
public Vector3d getTarget() {
|
||||
if (getAction() == EntityUseAction.INTERACT_AT
|
||||
&& PacketEvents.get().getServerUtils().getVersion() != ServerVersion.v_1_7_10) {
|
||||
public void setEntityId(int entityID) {
|
||||
writeInt(0, this.entityID = entityID);
|
||||
this.entity = null;
|
||||
}
|
||||
|
||||
@SupportedVersions(ranges = {ServerVersion.v_1_8, ServerVersion.ERROR})
|
||||
public Vector3d getTarget() throws UnsupportedOperationException {
|
||||
if (PacketEvents.get().getServerUtils().getVersion() == ServerVersion.v_1_7_10) {
|
||||
throwUnsupportedOperation();
|
||||
return Vector3d.INVALID;
|
||||
}
|
||||
//We are certain we are on a 1.8 (or higher) server.
|
||||
if (getAction() == EntityUseAction.INTERACT_AT) {
|
||||
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));
|
||||
} else {
|
||||
return Vector3d.INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
@SupportedVersions(ranges = {ServerVersion.v_1_8, ServerVersion.ERROR})
|
||||
public void setTarget(Vector3d target) throws UnsupportedOperationException {
|
||||
if (PacketEvents.get().getServerUtils().getVersion() == ServerVersion.v_1_7_10) {
|
||||
throwUnsupportedOperation();
|
||||
}
|
||||
//We are certain we are on a 1.8 (or higher) server.
|
||||
if (getAction() == EntityUseAction.INTERACT_AT) {
|
||||
Object vec3DObj = NMSUtils.generateVec3D(target.x, target.y, target.z);
|
||||
write(NMSUtils.vec3DClass, 0, vec3DObj);
|
||||
}
|
||||
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 +154,16 @@ public final class WrappedPacketInUseEntity extends WrappedPacket {
|
||||
return Hand.MAIN_HAND;
|
||||
}
|
||||
|
||||
@SupportedVersions(ranges = {ServerVersion.v_1_9, ServerVersion.ERROR})
|
||||
public void setHand(Hand hand) throws UnsupportedOperationException {
|
||||
if (PacketEvents.get().getServerUtils().getVersion().isOlderThan(ServerVersion.v_1_9)) {
|
||||
throwUnsupportedOperation();
|
||||
} else if (getAction() == EntityUseAction.INTERACT || getAction() == EntityUseAction.INTERACT_AT) {
|
||||
Enum<?> enumConst = EnumUtil.valueOf(enumHandClass, hand.name());
|
||||
writeEnumConstant(0, enumConst);
|
||||
}
|
||||
}
|
||||
|
||||
public enum EntityUseAction {
|
||||
INTERACT, INTERACT_AT, ATTACK
|
||||
}
|
||||
|
||||
+20
@@ -36,19 +36,39 @@ public class WrappedPacketInVehicleMove 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);
|
||||
}
|
||||
}
|
||||
+44
-50
@@ -27,6 +27,7 @@ package io.github.retrooper.packetevents.packetwrappers.play.in.windowclick;
|
||||
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.Reflection;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@@ -36,9 +37,8 @@ import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class WrappedPacketInWindowClick extends WrappedPacket {
|
||||
private static final HashMap<String, Integer> INV_CLICK_TYPE_CACHE = new HashMap<>();
|
||||
private static final HashMap<Integer, ArrayList<WindowClickType>> WINDOW_CLICK_TYPE_CACHE = new HashMap<>();
|
||||
private static Class<?> invClickTypeClass;
|
||||
private static Class<? extends Enum<?>> invClickTypeClass;
|
||||
private static boolean isClickModePrimitive;
|
||||
|
||||
|
||||
@@ -46,18 +46,16 @@ public class WrappedPacketInWindowClick extends WrappedPacket {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
private static ArrayList<WindowClickType> getArrayListOfWindowClickTypes(WindowClickType... types) {
|
||||
ArrayList<WindowClickType> arrayList = new ArrayList<>(types.length);
|
||||
arrayList.addAll(Arrays.asList(types));
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void load() {
|
||||
Class<?> packetClass = PacketTypeClasses.Play.Client.WINDOW_CLICK;
|
||||
invClickTypeClass = NMSUtils.getNMSClassWithoutException("InventoryClickType");
|
||||
|
||||
INV_CLICK_TYPE_CACHE.put("PICKUP", 0);
|
||||
INV_CLICK_TYPE_CACHE.put("QUICK_MOVE", 1);
|
||||
INV_CLICK_TYPE_CACHE.put("SWAP", 2);
|
||||
INV_CLICK_TYPE_CACHE.put("CLONE", 3);
|
||||
INV_CLICK_TYPE_CACHE.put("THROW", 4);
|
||||
INV_CLICK_TYPE_CACHE.put("QUICK_CRAFT", 5);
|
||||
INV_CLICK_TYPE_CACHE.put("PICKUP_ALL", 6);
|
||||
invClickTypeClass = NMSUtils.getNMSEnumClassWithoutException("InventoryClickType");
|
||||
|
||||
//MODE 0
|
||||
WINDOW_CLICK_TYPE_CACHE.put(0, getArrayListOfWindowClickTypes(WindowClickType.LEFT_MOUSE_CLICK,
|
||||
@@ -100,56 +98,41 @@ public class WrappedPacketInWindowClick extends WrappedPacket {
|
||||
|
||||
WINDOW_CLICK_TYPE_CACHE.put(6, getArrayListOfWindowClickTypes(WindowClickType.DOUBLE_CLICK));
|
||||
isClickModePrimitive = Reflection.getField(packetClass, int.class, 3) != null;
|
||||
invClickTypeClass = NMSUtils.getNMSClassWithoutException("InventoryClickType");
|
||||
}
|
||||
|
||||
private static ArrayList<WindowClickType> getArrayListOfWindowClickTypes(WindowClickType... types) {
|
||||
ArrayList<WindowClickType> arrayList = new ArrayList<WindowClickType>(types.length);
|
||||
arrayList.addAll(Arrays.asList(types));
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Window ID.
|
||||
*
|
||||
* @return Get Window ID
|
||||
*/
|
||||
public int getWindowId() {
|
||||
return readInt(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Window slot.
|
||||
*
|
||||
* @return Get Window Slot
|
||||
*/
|
||||
public void setWindowId(int windowID) {
|
||||
writeInt(0, windowID);
|
||||
}
|
||||
|
||||
public int getWindowSlot() {
|
||||
return readInt(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Window button.
|
||||
*
|
||||
* @return Get Window Button
|
||||
*/
|
||||
public void setWindowSlot(int slot) {
|
||||
writeInt(1, slot);
|
||||
}
|
||||
|
||||
public int getWindowButton() {
|
||||
return readInt(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the action number.
|
||||
*
|
||||
* @return Get Action Number
|
||||
*/
|
||||
public void setWindowButton(int button) {
|
||||
writeInt(2, button);
|
||||
}
|
||||
|
||||
public short getActionNumber() {
|
||||
return readShort(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the window click type.
|
||||
*
|
||||
* @return Get Window Click Type
|
||||
*/
|
||||
public void setActionNumber(short actionNumber) {
|
||||
writeShort(0, actionNumber);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public WindowClickType getWindowClickType() {
|
||||
int mode = getMode();
|
||||
if (WINDOW_CLICK_TYPE_CACHE.get(mode) == null) {
|
||||
@@ -173,16 +156,21 @@ public class WrappedPacketInWindowClick extends WrappedPacket {
|
||||
return WINDOW_CLICK_TYPE_CACHE.get(mode).get(windowButton);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Window mode.
|
||||
*
|
||||
* @return Get Window Mode.
|
||||
*/
|
||||
public int getMode() {
|
||||
if (isClickModePrimitive) {
|
||||
return readInt(3);
|
||||
} else {
|
||||
return INV_CLICK_TYPE_CACHE.get(readObject(5, invClickTypeClass).toString());
|
||||
Enum<?> enumConst = readEnumConstant(0, invClickTypeClass);
|
||||
return enumConst.ordinal();
|
||||
}
|
||||
}
|
||||
|
||||
public void setMode(int mode) {
|
||||
if (isClickModePrimitive) {
|
||||
writeInt(3, mode);
|
||||
} else {
|
||||
Enum<?> enumConst = EnumUtil.valueByIndex(invClickTypeClass, mode);
|
||||
writeEnumConstant(0, enumConst);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,11 +179,17 @@ public class WrappedPacketInWindowClick extends WrappedPacket {
|
||||
*
|
||||
* @return Get Clicked ItemStack
|
||||
*/
|
||||
public ItemStack getClickedItem() {
|
||||
public ItemStack getClickedItemStack() {
|
||||
Object nmsItemStack = readObject(0, NMSUtils.nmsItemStackClass);
|
||||
return NMSUtils.toBukkitItemStack(nmsItemStack);
|
||||
}
|
||||
|
||||
public void setClickedItemStack(ItemStack stack) {
|
||||
Object nmsItemStack = NMSUtils.toNMSItemStack(stack);
|
||||
write(NMSUtils.nmsItemStackClass, 0, nmsItemStack);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public enum WindowClickType {
|
||||
LEFT_MOUSE_CLICK, RIGHT_MOUSE_CLICK,
|
||||
SHIFT_LEFT_MOUSE_CLICK, SHIFT_RIGHT_MOUSE_CLICK,
|
||||
|
||||
-66
@@ -1,66 +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.packetwrappers.play.out.abilities;
|
||||
|
||||
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Objects;
|
||||
|
||||
final class PlayerAbilitiesUtils {
|
||||
public static Class<?> playerAbilitiesClass;
|
||||
public static Constructor<?> playerAbilitiesConstructor;
|
||||
|
||||
public static Object getPlayerAbilities(final boolean isVulnerable, final boolean isFlying, final boolean allowFlight, final boolean canBuildInstantly,
|
||||
final float flySpeed, final float walkSpeed) throws IllegalAccessException, InvocationTargetException, InstantiationException {
|
||||
|
||||
if (playerAbilitiesClass == null) {
|
||||
try {
|
||||
playerAbilitiesClass = NMSUtils.getNMSClass("PlayerAbilities");
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (playerAbilitiesConstructor == null && playerAbilitiesClass != null) {
|
||||
try {
|
||||
playerAbilitiesConstructor = playerAbilitiesClass.getConstructor();
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
final Object instance = Objects.requireNonNull(playerAbilitiesConstructor).newInstance();
|
||||
WrappedPacket wrapper = new WrappedPacket(new NMSPacket(instance));
|
||||
wrapper.writeBoolean(0, isVulnerable);
|
||||
wrapper.writeBoolean(1, isFlying);
|
||||
wrapper.writeBoolean(2, allowFlight);
|
||||
wrapper.writeBoolean(3, canBuildInstantly);
|
||||
wrapper.writeFloat(0, flySpeed);
|
||||
wrapper.writeFloat(1, walkSpeed);
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
+84
-34
@@ -28,12 +28,14 @@ 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.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public final class WrappedPacketOutAbilities extends WrappedPacket implements SendableWrapper {
|
||||
private static Constructor<?> packetConstructor;
|
||||
private static Constructor<?> packetConstructor, playerAbilitiesConstructor;
|
||||
private static Class<?> playerAbilitiesClass;
|
||||
private boolean vulnerable, flying, allowFlight, instantBuild;
|
||||
private float flySpeed, walkSpeed;
|
||||
|
||||
@@ -54,19 +56,27 @@ public final class WrappedPacketOutAbilities extends WrappedPacket implements Se
|
||||
@Override
|
||||
protected void load() {
|
||||
Class<?> packetClass = PacketTypeClasses.Play.Server.ABILITIES;
|
||||
try {
|
||||
playerAbilitiesClass = NMSUtils.getNMSClass("PlayerAbilities");
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (playerAbilitiesClass != null) {
|
||||
try {
|
||||
playerAbilitiesConstructor = playerAbilitiesClass.getConstructor();
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
packetConstructor = packetClass.getConstructor(PlayerAbilitiesUtils.playerAbilitiesClass);
|
||||
packetConstructor = packetClass.getConstructor(playerAbilitiesClass);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the client be vulnerable?
|
||||
*
|
||||
* @return Is Vulnerable
|
||||
*/
|
||||
public boolean isVulnerable() {
|
||||
if (packet != null) {
|
||||
return readBoolean(0);
|
||||
@@ -75,11 +85,14 @@ public final class WrappedPacketOutAbilities extends WrappedPacket implements Se
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the client be flying?
|
||||
*
|
||||
* @return Is Flying
|
||||
*/
|
||||
public void setVulnerable(boolean isVulnerable) {
|
||||
if (packet != null) {
|
||||
writeBoolean(0, isVulnerable);
|
||||
} else {
|
||||
this.vulnerable = isVulnerable;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFlying() {
|
||||
if (packet != null) {
|
||||
return readBoolean(1);
|
||||
@@ -88,11 +101,14 @@ public final class WrappedPacketOutAbilities extends WrappedPacket implements Se
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the client be allowed to fly?
|
||||
*
|
||||
* @return Is Allowed To Fly
|
||||
*/
|
||||
public void setFlying(boolean isFlying) {
|
||||
if (packet != null) {
|
||||
writeBoolean(1, isFlying);
|
||||
} else {
|
||||
this.flying = isFlying;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFlightAllowed() {
|
||||
if (packet != null) {
|
||||
return readBoolean(2);
|
||||
@@ -101,12 +117,15 @@ public final class WrappedPacketOutAbilities extends WrappedPacket implements Se
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the client be able to build instantly?
|
||||
*
|
||||
* @return Is Allowed To Build Instantly
|
||||
*/
|
||||
public boolean canInstantlyBuild() {
|
||||
public void setFlightAllowed(boolean isFlightAllowed) {
|
||||
if (packet != null) {
|
||||
writeBoolean(2, isFlightAllowed);
|
||||
} else {
|
||||
this.allowFlight = isFlightAllowed;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canBuildInstantly() {
|
||||
if (packet != null) {
|
||||
return readBoolean(3);
|
||||
} else {
|
||||
@@ -114,11 +133,14 @@ public final class WrappedPacketOutAbilities extends WrappedPacket implements Se
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the client's defined fly speed.
|
||||
*
|
||||
* @return Get Fly Speed
|
||||
*/
|
||||
public void setCanBuildInstantly(boolean canBuildInstantly) {
|
||||
if (packet != null) {
|
||||
writeBoolean(3, canBuildInstantly);
|
||||
} else {
|
||||
this.instantBuild = canBuildInstantly;
|
||||
}
|
||||
}
|
||||
|
||||
public float getFlySpeed() {
|
||||
if (packet != null) {
|
||||
return readFloat(0);
|
||||
@@ -127,11 +149,14 @@ public final class WrappedPacketOutAbilities extends WrappedPacket implements Se
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the client's defined walk speed.
|
||||
*
|
||||
* @return Get Walk Speed
|
||||
*/
|
||||
public void setFlySpeed(float flySpeed) {
|
||||
if (packet != null) {
|
||||
writeFloat(0, flySpeed);
|
||||
} else {
|
||||
this.flySpeed = flySpeed;
|
||||
}
|
||||
}
|
||||
|
||||
public float getWalkSpeed() {
|
||||
if (packet != null) {
|
||||
return readFloat(1);
|
||||
@@ -140,10 +165,35 @@ public final class WrappedPacketOutAbilities extends WrappedPacket implements Se
|
||||
}
|
||||
}
|
||||
|
||||
public void setWalkSpeed(float walkSpeed) {
|
||||
if (packet != null) {
|
||||
writeFloat(1, walkSpeed);
|
||||
} else {
|
||||
this.walkSpeed = walkSpeed;
|
||||
}
|
||||
}
|
||||
|
||||
private Object getPlayerAbilities(boolean vulnerable, boolean flying, boolean flightAllowed, boolean canBuildInstantly, float flySpeed, float walkSpeed) {
|
||||
Object instance = null;
|
||||
try {
|
||||
instance = playerAbilitiesConstructor.newInstance();
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
WrappedPacket wrapper = new WrappedPacket(new NMSPacket(instance));
|
||||
wrapper.writeBoolean(0, vulnerable);
|
||||
wrapper.writeBoolean(1, flying);
|
||||
wrapper.writeBoolean(2, flightAllowed);
|
||||
wrapper.writeBoolean(3, canBuildInstantly);
|
||||
wrapper.writeFloat(0, flySpeed);
|
||||
wrapper.writeFloat(1, walkSpeed);
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object asNMSPacket() {
|
||||
try {
|
||||
return packetConstructor.newInstance(PlayerAbilitiesUtils.getPlayerAbilities(isVulnerable(), isFlying(), isFlightAllowed(), canInstantlyBuild(), getFlySpeed(), getWalkSpeed()));
|
||||
return packetConstructor.newInstance(getPlayerAbilities(isVulnerable(), isFlying(), isFlightAllowed(), canBuildInstantly(), getFlySpeed(), getWalkSpeed()));
|
||||
} catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
+43
-34
@@ -29,7 +29,9 @@ import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.SendableWrapper;
|
||||
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.Nullable;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
@@ -67,50 +69,63 @@ public final class WrappedPacketOutAnimation extends WrappedPacket implements Se
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup the associated entity by the ID that was sent in the packet.
|
||||
*
|
||||
* @return Entity
|
||||
*/
|
||||
@Nullable
|
||||
public Entity getEntity() {
|
||||
if (entity != null) {
|
||||
return entity;
|
||||
}
|
||||
return entity = NMSUtils.getEntityById(getEntityId());
|
||||
return getEntity(null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Entity getEntity(@Nullable World world) {
|
||||
if (entity == null) {
|
||||
entity = NMSUtils.getEntityById(world, getEntityId());
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
public void setEntity(Entity entity) {
|
||||
setEntityId(entity.getEntityId());
|
||||
this.entity = 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);
|
||||
if (packet != null) {
|
||||
if (entityID == -1) {
|
||||
entityID = readInt(0);
|
||||
}
|
||||
}
|
||||
return entityID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the entity animation type.
|
||||
*
|
||||
* @return Get Entity Animation Type
|
||||
*/
|
||||
public void setEntityId(int entityID) {
|
||||
if (packet != null) {
|
||||
writeInt(0, this.entityID = entityID);
|
||||
} else {
|
||||
this.entityID = entityID;
|
||||
}
|
||||
this.entity = null;
|
||||
}
|
||||
|
||||
public EntityAnimationType getAnimationType() {
|
||||
if (packet != null) {
|
||||
byte id = (byte)readInt(1);
|
||||
byte id = (byte) readInt(1);
|
||||
return EntityAnimationType.getById(id);
|
||||
} else {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
public void setAnimationType(EntityAnimationType type) {
|
||||
if (packet != null) {
|
||||
writeInt(1, type.ordinal());
|
||||
} else {
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object asNMSPacket() {
|
||||
final Object nmsEntity = NMSUtils.getNMSEntity(getEntity());
|
||||
final int index = getAnimationType().id;
|
||||
final int index = getAnimationType().ordinal();
|
||||
try {
|
||||
return animationConstructor.newInstance(nmsEntity, index);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
@@ -120,17 +135,11 @@ public final class WrappedPacketOutAnimation extends WrappedPacket implements Se
|
||||
}
|
||||
|
||||
public enum EntityAnimationType {
|
||||
SWING_MAIN_ARM((byte) 0), TAKE_DAMAGE((byte) 1), LEAVE_BED((byte) 2),
|
||||
SWING_OFFHAND((byte) 3), CRITICAL_EFFECT((byte) 4), MAGIC_CRITICAL_EFFECT((byte) 5);
|
||||
SWING_MAIN_ARM, TAKE_DAMAGE, LEAVE_BED,
|
||||
SWING_OFFHAND, CRITICAL_EFFECT, MAGIC_CRITICAL_EFFECT;
|
||||
|
||||
final byte id;
|
||||
EntityAnimationType() {
|
||||
|
||||
EntityAnimationType(byte id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public byte getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public static EntityAnimationType getById(byte id) {
|
||||
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
package io.github.retrooper.packetevents.packetwrappers.play.out.blockbreakanimation;
|
||||
|
||||
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.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
|
||||
import io.github.retrooper.packetevents.utils.server.ServerVersion;
|
||||
import io.github.retrooper.packetevents.utils.vector.Vector3i;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
//TODO test
|
||||
public class WrappedPacketOutBlockBreakAnimation extends WrappedPacket implements SendableWrapper {
|
||||
private static Constructor<?> packetConstructor;
|
||||
private int entityID;
|
||||
private Entity entity;
|
||||
private Vector3i blockPosition;
|
||||
private int destroyStage;
|
||||
|
||||
public WrappedPacketOutBlockBreakAnimation(NMSPacket packet) {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
public WrappedPacketOutBlockBreakAnimation(int entityID, Vector3i blockPosition, int destroyStage) {
|
||||
this.entityID = entityID;
|
||||
this.blockPosition = blockPosition;
|
||||
this.destroyStage = destroyStage;
|
||||
}
|
||||
|
||||
public WrappedPacketOutBlockBreakAnimation(Entity entity, Vector3i blockPosition, int destroyStage) {
|
||||
this.entityID = entity.getEntityId();
|
||||
this.entity = entity;
|
||||
this.blockPosition = blockPosition;
|
||||
this.destroyStage = destroyStage;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void load() {
|
||||
try {
|
||||
packetConstructor = PacketTypeClasses.Play.Server.BLOCK_BREAK_ANIMATION.getConstructor(int.class, int.class, int.class, int.class, int.class);
|
||||
} catch (NoSuchMethodException e) {
|
||||
try {
|
||||
packetConstructor = PacketTypeClasses.Play.Server.BLOCK_BREAK_ANIMATION.getConstructor(int.class, NMSUtils.blockPosClass, int.class);
|
||||
} catch (NoSuchMethodException e2) {
|
||||
e2.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getEntityId() {
|
||||
if (entityID != -1) {
|
||||
return entityID;
|
||||
}
|
||||
return entityID = readInt(0);
|
||||
}
|
||||
|
||||
public void setEntityId(int entityID) {
|
||||
if (packet != null) {
|
||||
writeInt(0, this.entityID = entityID);
|
||||
} else {
|
||||
this.entityID = entityID;
|
||||
}
|
||||
this.entity = null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Entity getEntity() {
|
||||
return getEntity(null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Entity getEntity(@Nullable World world) {
|
||||
if (entity == null) {
|
||||
entity = NMSUtils.getEntityById(world, getEntityId());
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
public void setEntity(Entity entity) {
|
||||
setEntityId(entity.getEntityId());
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
public Vector3i getBlockPosition() {
|
||||
if (packet != null) {
|
||||
Vector3i blockPosition = new Vector3i();
|
||||
if (version.isOlderThan(ServerVersion.v_1_8)) {
|
||||
this.blockPosition.x = readInt(1);
|
||||
this.blockPosition.y = readInt(2);
|
||||
this.blockPosition.z = readInt(3);
|
||||
} else {
|
||||
Object blockPos = readObject(0, NMSUtils.blockPosClass);
|
||||
this.blockPosition = NMSUtils.readBlockPos(blockPos);
|
||||
}
|
||||
return blockPosition;
|
||||
} else {
|
||||
return this.blockPosition;
|
||||
}
|
||||
}
|
||||
|
||||
public void setBlockPosition(Vector3i blockPosition) {
|
||||
if (packet != null) {
|
||||
if (version.isOlderThan(ServerVersion.v_1_8)) {
|
||||
writeInt(1, blockPosition.x);
|
||||
writeInt(2, blockPosition.y);
|
||||
writeInt(3, blockPosition.z);
|
||||
} else {
|
||||
Object blockPos = NMSUtils.generateNMSBlockPos(blockPosition.x, blockPosition.y, blockPosition.z);
|
||||
write(NMSUtils.blockPosClass, 0, blockPos);
|
||||
}
|
||||
} else {
|
||||
this.blockPosition = blockPosition;
|
||||
}
|
||||
}
|
||||
|
||||
public int getDestroyStage() {
|
||||
if (packet != null) {
|
||||
int index = version.isOlderThan(ServerVersion.v_1_8) ? 4 : 1;
|
||||
return readInt(index);
|
||||
} else {
|
||||
return this.destroyStage;
|
||||
}
|
||||
}
|
||||
|
||||
public void setDestroyStage(int destroyStage) {
|
||||
if (packet != null) {
|
||||
int index = version.isOlderThan(ServerVersion.v_1_8) ? 4 : 1;
|
||||
writeInt(index, destroyStage);
|
||||
} else {
|
||||
this.destroyStage = destroyStage;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object asNMSPacket() {
|
||||
Vector3i blockPosition = getBlockPosition();
|
||||
try {
|
||||
if (version.isOlderThan(ServerVersion.v_1_8)) {
|
||||
return packetConstructor.newInstance(getEntityId(), blockPosition.x, blockPosition.y, blockPosition.z, getDestroyStage());
|
||||
} else {
|
||||
Object nmsBlockPos = NMSUtils.generateNMSBlockPos(blockPosition.x, blockPosition.y, blockPosition.z);
|
||||
return packetConstructor.newInstance(getEntityId(), nmsBlockPos, getDestroyStage());
|
||||
}
|
||||
} catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+87
-63
@@ -31,33 +31,37 @@ 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.server.ServerVersion;
|
||||
import io.github.retrooper.packetevents.utils.vector.Vector3i;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
//TODO TEST ON 1.7.10
|
||||
public class WrappedPacketOutBlockChange extends WrappedPacket implements SendableWrapper {
|
||||
private static Constructor<?> packetConstructor;
|
||||
private static Method getBlockIdMethodCache = null;
|
||||
private static Method getNMSBlockMethodCache = null;
|
||||
private static Method getNMSWorldTypeMethodCache = null;
|
||||
|
||||
|
||||
private Object blockPosObj = null;
|
||||
|
||||
private int blockPosX;
|
||||
private int blockPosY;
|
||||
private int blockPosZ;
|
||||
private World world;
|
||||
private Material material;
|
||||
|
||||
public WrappedPacketOutBlockChange(NMSPacket packet) {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
public WrappedPacketOutBlockChange(World world, int blockPosX, int blockPosY, int blockPosZ) {
|
||||
this.blockPosX = blockPosX;
|
||||
this.blockPosY = blockPosY;
|
||||
this.blockPosZ = blockPosZ;
|
||||
public WrappedPacketOutBlockChange(World world, Vector3i blockPos) {
|
||||
this.blockPosX = blockPos.x;
|
||||
this.blockPosY = blockPos.y;
|
||||
this.blockPosZ = blockPos.z;
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
@@ -68,13 +72,19 @@ public class WrappedPacketOutBlockChange extends WrappedPacket implements Sendab
|
||||
this.world = location.getWorld();
|
||||
}
|
||||
|
||||
public WrappedPacketOutBlockChange(World world, Vector3i blockPos, Material material) {
|
||||
this(world, blockPos);
|
||||
this.material = material;
|
||||
}
|
||||
|
||||
public WrappedPacketOutBlockChange(Location location, Material material) {
|
||||
this(location);
|
||||
this.material = material;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void load() {
|
||||
getBlockIdMethodCache = Reflection.getMethod(NMSUtils.blockClass, "getCombinedId", int.class, NMSUtils.iBlockDataClass);
|
||||
if (getBlockIdMethodCache == null) {
|
||||
//1.7.10
|
||||
getBlockIdMethodCache = Reflection.getMethod(NMSUtils.blockClass, "getId", int.class, NMSUtils.blockClass);
|
||||
}
|
||||
getNMSBlockMethodCache = Reflection.getMethod(NMSUtils.iBlockDataClass, "getBlock", 0);
|
||||
getNMSWorldTypeMethodCache = Reflection.getMethod(NMSUtils.nmsWorldClass, "getType", 0);
|
||||
if (version.equals(ServerVersion.v_1_7_10)) {
|
||||
try {
|
||||
@@ -91,108 +101,122 @@ public class WrappedPacketOutBlockChange extends WrappedPacket implements Sendab
|
||||
}
|
||||
}
|
||||
|
||||
public int getBlockX() {
|
||||
public Vector3i getBlockPosition() {
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int z = 0;
|
||||
if (packet != null) {
|
||||
if (version.isOlderThan(ServerVersion.v_1_8)) {
|
||||
return readInt(0);
|
||||
x = readInt(0);
|
||||
y = readInt(1);
|
||||
z = readInt(2);
|
||||
} else {
|
||||
if (blockPosObj == null) {
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
return blockPosX;
|
||||
x = blockPosX;
|
||||
y = blockPosY;
|
||||
z = blockPosZ;
|
||||
}
|
||||
return new Vector3i(x, y, z);
|
||||
}
|
||||
|
||||
public int getBlockY() {
|
||||
public void setBlockPosition(Vector3i blockPos) {
|
||||
if (packet != null) {
|
||||
if (version.equals(ServerVersion.v_1_7_10)) {
|
||||
return readInt(1);
|
||||
if (version.isOlderThan(ServerVersion.v_1_8)) {
|
||||
writeInt(0, blockPos.x);
|
||||
writeInt(1, blockPos.y);
|
||||
writeInt(2, blockPos.z);
|
||||
} else {
|
||||
if (blockPosObj == null) {
|
||||
blockPosObj = readObject(0, NMSUtils.blockPosClass);
|
||||
}
|
||||
try {
|
||||
return (int) Reflection.getMethod(blockPosObj.getClass().getSuperclass(), "getY", 0).invoke(blockPosObj);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return -1;
|
||||
blockPosObj = NMSUtils.generateNMSBlockPos(blockPos.x, blockPos.y, blockPos.z);
|
||||
write(NMSUtils.blockPosClass, 0, blockPosObj);
|
||||
}
|
||||
} else {
|
||||
return blockPosY;
|
||||
blockPosX = blockPos.x;
|
||||
blockPosY = blockPos.y;
|
||||
blockPosZ = blockPos.z;
|
||||
}
|
||||
}
|
||||
|
||||
public int getBlockZ() {
|
||||
public Material getMaterial() {
|
||||
if (packet != null) {
|
||||
if (version.equals(ServerVersion.v_1_7_10)) {
|
||||
return readInt(2);
|
||||
Object nmsBlock = null;
|
||||
if (version.isOlderThan(ServerVersion.v_1_8)) {
|
||||
nmsBlock = readObject(0, NMSUtils.blockClass);
|
||||
} else {
|
||||
if (blockPosObj == null) {
|
||||
blockPosObj = readObject(0, NMSUtils.blockPosClass);
|
||||
}
|
||||
Object iBlockDataObj = readObject(0, NMSUtils.iBlockDataClass);
|
||||
try {
|
||||
return (int) Reflection.getMethod(blockPosObj.getClass().getSuperclass(), "getZ", 0).invoke(blockPosObj);
|
||||
nmsBlock = getNMSBlockMethodCache.invoke(iBlockDataObj);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return NMSUtils.getMaterialFromNMSBlock(nmsBlock);
|
||||
} else {
|
||||
return blockPosZ;
|
||||
return material;
|
||||
}
|
||||
}
|
||||
|
||||
public int getBlockId() {
|
||||
if (version.isOlderThan(ServerVersion.v_1_8)) {
|
||||
Object nmsBlock = readObject(0, NMSUtils.blockClass);
|
||||
try {
|
||||
return (int) getBlockIdMethodCache.invoke(null, nmsBlock);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
public void setMaterial(Material material) {
|
||||
if (packet != null) {
|
||||
Object nmsBlock = NMSUtils.getNMSBlockFromMaterial(material);
|
||||
if (version.isOlderThan(ServerVersion.v_1_8)) {
|
||||
write(NMSUtils.blockClass, 0, nmsBlock);
|
||||
} else {
|
||||
WrappedPacket nmsBlockWrapper = new WrappedPacket(new NMSPacket(nmsBlock), NMSUtils.blockClass);
|
||||
Object iBlockData = nmsBlockWrapper.readObject(0, NMSUtils.iBlockDataClass);
|
||||
write(NMSUtils.iBlockDataClass, 0, iBlockData);
|
||||
}
|
||||
} else {
|
||||
Object iBlockDataObj = readObject(0, NMSUtils.iBlockDataClass);
|
||||
try {
|
||||
return (int) getBlockIdMethodCache.invoke(null, iBlockDataObj);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.material = material;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object asNMSPacket() {
|
||||
Object packetPlayOutBlockChangeInstance = null;
|
||||
WrappedPacketOutBlockChange blockChange;
|
||||
Vector3i blockPosition = getBlockPosition();
|
||||
if (version.isOlderThan(ServerVersion.v_1_8)) {
|
||||
try {
|
||||
Object nmsWorld = NMSUtils.convertBukkitWorldToNMSWorld(world);
|
||||
return packetConstructor.newInstance(getBlockX(), getBlockY(), getBlockZ(), nmsWorld);
|
||||
Object nmsWorld = NMSUtils.convertBukkitWorldToWorldServer(world);
|
||||
packetPlayOutBlockChangeInstance = packetConstructor.newInstance(blockPosition.x, blockPosition.y, blockPosition.z, nmsWorld);
|
||||
blockChange = new WrappedPacketOutBlockChange(new NMSPacket(packetPlayOutBlockChangeInstance));
|
||||
if (getMaterial() != null) {
|
||||
blockChange.setMaterial(getMaterial());
|
||||
}
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
} else {
|
||||
try {
|
||||
Object packetInstance = packetConstructor.newInstance();
|
||||
WrappedPacket packetWrapper = new WrappedPacket(new NMSPacket(packetInstance));
|
||||
Object nmsBlockPos = NMSUtils.generateNMSBlockPos(getBlockX(), getBlockY(), getBlockZ());
|
||||
Object nmsWorld = NMSUtils.convertBukkitWorldToNMSWorld(world);
|
||||
Object nmsBlockData = getNMSWorldTypeMethodCache.invoke(nmsWorld, nmsBlockPos);
|
||||
packetWrapper.write(NMSUtils.blockPosClass, 0, nmsBlockPos);
|
||||
packetWrapper.write(NMSUtils.iBlockDataClass, 0, nmsBlockData);
|
||||
return packetInstance;
|
||||
packetPlayOutBlockChangeInstance = packetConstructor.newInstance();
|
||||
blockChange = new WrappedPacketOutBlockChange(new NMSPacket(packetPlayOutBlockChangeInstance));
|
||||
if (getMaterial() != null) {
|
||||
blockChange.setMaterial(getMaterial());
|
||||
} else {
|
||||
Object nmsBlockPos = NMSUtils.generateNMSBlockPos(blockPosition.x, blockPosition.y, blockPosition.z);
|
||||
Object worldServer = NMSUtils.convertBukkitWorldToWorldServer(world);
|
||||
Object nmsBlockData = getNMSWorldTypeMethodCache.invoke(worldServer, nmsBlockPos);
|
||||
blockChange.write(NMSUtils.iBlockDataClass, 0, nmsBlockData);
|
||||
}
|
||||
blockChange.setBlockPosition(blockPosition);
|
||||
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return packetPlayOutBlockChangeInstance;
|
||||
}
|
||||
}
|
||||
+8
@@ -61,6 +61,14 @@ public class WrappedPacketOutCamera extends WrappedPacket implements SendableWra
|
||||
return cameraID;
|
||||
}
|
||||
|
||||
public void setCameraId(int cameraID) {
|
||||
if (packet != null) {
|
||||
writeInt(0, cameraID);
|
||||
} else {
|
||||
this.cameraID = cameraID;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object asNMSPacket() {
|
||||
Object packetInstance = null;
|
||||
|
||||
+46
-72
@@ -30,22 +30,17 @@ import io.github.retrooper.packetevents.packetwrappers.SendableWrapper;
|
||||
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.reflection.SubclassUtil;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.chat.ComponentSerializer;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class WrappedPacketOutChat extends WrappedPacket implements SendableWrapper {
|
||||
private static final HashMap<ChatPosition, Byte> cachedChatPositions = new HashMap<>();
|
||||
private static final HashMap<Byte, ChatPosition> cachedChatPositionIntegers = new HashMap<>();
|
||||
private static final HashMap<String, Byte> cachedChatMessageTypeIntegers = new HashMap<>();
|
||||
private static Constructor<?> chatClassConstructor;
|
||||
private static Class<?> packetClass, iChatBaseComponentClass, chatSerializerClass, chatMessageTypeEnum;
|
||||
private static Class<?> packetClass, iChatBaseComponentClass, chatMessageTypeEnum;
|
||||
private static Method chatMessageTypeCreatorMethod;
|
||||
//0 = IChatBaseComponent, Byte
|
||||
//1 = IChatBaseComponent, Int
|
||||
@@ -64,6 +59,9 @@ public final class WrappedPacketOutChat extends WrappedPacket implements Sendabl
|
||||
this(message, ChatPosition.CHAT, uuid, isJson);
|
||||
}
|
||||
|
||||
public WrappedPacketOutChat(BaseComponent component, UUID uuid) {
|
||||
this(component, ChatPosition.CHAT, uuid);
|
||||
}
|
||||
|
||||
public WrappedPacketOutChat(BaseComponent component, ChatPosition pos, UUID uuid) {
|
||||
this(ComponentSerializer.toString(component), pos, uuid, true);
|
||||
@@ -71,7 +69,7 @@ public final class WrappedPacketOutChat extends WrappedPacket implements Sendabl
|
||||
|
||||
public WrappedPacketOutChat(String message, ChatPosition chatPosition, UUID uuid, boolean isJson) {
|
||||
this.uuid = uuid;
|
||||
this.message = isJson ? message : fromStringToJSON(message);
|
||||
this.message = isJson ? message : NMSUtils.fromStringToJSON(message);
|
||||
this.chatPosition = chatPosition;
|
||||
}
|
||||
|
||||
@@ -84,15 +82,6 @@ public final class WrappedPacketOutChat extends WrappedPacket implements Sendabl
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
//In 1.8.3+ the ChatSerializer class is declared in the IChatBaseComponent class, so we have to handle that
|
||||
try {
|
||||
chatSerializerClass = NMSUtils.getNMSClass("ChatSerializer");
|
||||
} catch (ClassNotFoundException e) {
|
||||
//That is fine, it is probably a subclass
|
||||
chatSerializerClass = SubclassUtil.getSubClass(iChatBaseComponentClass, "ChatSerializer");
|
||||
}
|
||||
|
||||
|
||||
boolean isVeryOutdated = false;
|
||||
try {
|
||||
chatMessageTypeEnum = NMSUtils.getNMSClass("ChatMessageType");
|
||||
@@ -126,84 +115,62 @@ public final class WrappedPacketOutChat extends WrappedPacket implements Sendabl
|
||||
chatClassConstructor = packetClass.getConstructor(iChatBaseComponentClass, int.class);
|
||||
constructorMode = 1;
|
||||
} catch (NoSuchMethodException e2) {
|
||||
e2.printStackTrace();
|
||||
try {
|
||||
//Some weird 1.7.10 spigots remove that int parameter for no reason, I won't keep adding support for any more spigots and might stop
|
||||
//accepting pull requests for support for spigots breaking things that normal spigot has.
|
||||
chatClassConstructor = packetClass.getConstructor(iChatBaseComponentClass);
|
||||
constructorMode = -1;
|
||||
} catch (NoSuchMethodException noSuchMethodException) {
|
||||
noSuchMethodException.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cachedChatPositions.put(ChatPosition.CHAT, (byte) 0);
|
||||
cachedChatPositions.put(ChatPosition.SYSTEM_MESSAGE, (byte) 1);
|
||||
cachedChatPositions.put(ChatPosition.GAME_INFO, (byte) 2);
|
||||
|
||||
cachedChatPositionIntegers.put((byte) 0, ChatPosition.CHAT);
|
||||
cachedChatPositionIntegers.put((byte) 1, ChatPosition.SYSTEM_MESSAGE);
|
||||
cachedChatPositionIntegers.put((byte) 2, ChatPosition.GAME_INFO);
|
||||
|
||||
|
||||
cachedChatMessageTypeIntegers.put("CHAT", (byte) 0);
|
||||
cachedChatMessageTypeIntegers.put("SYSTEM", (byte) 1);
|
||||
cachedChatMessageTypeIntegers.put("GAME_INFO", (byte) 2);
|
||||
|
||||
}
|
||||
|
||||
public static String fromStringToJSON(String message) {
|
||||
return "{\"text\": \"" + message + "\"}";
|
||||
}
|
||||
|
||||
public static String toStringFromIChatBaseComponent(Object obj) {
|
||||
try {
|
||||
return Reflection.getMethod(iChatBaseComponentClass, String.class, 0).invoke(obj).toString();
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object toIChatBaseComponent(String msg) {
|
||||
try {
|
||||
return Reflection.getMethod(chatSerializerClass, 0, String.class).invoke(null, msg);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object asNMSPacket() {
|
||||
int integerChatPos = cachedChatPositions.get(getChatPosition());
|
||||
byte chatPos = (byte) getChatPosition().ordinal();
|
||||
Object chatMessageTypeInstance = null;
|
||||
if (chatMessageTypeEnum != null) {
|
||||
try {
|
||||
chatMessageTypeInstance = chatMessageTypeCreatorMethod.invoke(null, (byte) integerChatPos);
|
||||
chatMessageTypeInstance = chatMessageTypeCreatorMethod.invoke(null, chatPos);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
switch (constructorMode) {
|
||||
case -1:
|
||||
try {
|
||||
return chatClassConstructor.newInstance(NMSUtils.generateIChatBaseComponent(getMessage()));
|
||||
} catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
case 0:
|
||||
try {
|
||||
return chatClassConstructor.newInstance(toIChatBaseComponent(getMessage()), (byte) integerChatPos);
|
||||
return chatClassConstructor.newInstance(NMSUtils.generateIChatBaseComponent(getMessage()), chatPos);
|
||||
} catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
try {
|
||||
return chatClassConstructor.newInstance(toIChatBaseComponent(getMessage()), integerChatPos);
|
||||
return chatClassConstructor.newInstance(NMSUtils.generateIChatBaseComponent(getMessage()), (int) chatPos);
|
||||
} catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
try {
|
||||
return chatClassConstructor.newInstance(toIChatBaseComponent(getMessage()), chatMessageTypeInstance);
|
||||
return chatClassConstructor.newInstance(NMSUtils.generateIChatBaseComponent(getMessage()), chatMessageTypeInstance);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
try {
|
||||
return chatClassConstructor.newInstance(toIChatBaseComponent(getMessage()), chatMessageTypeInstance, uuid);
|
||||
return chatClassConstructor.newInstance(NMSUtils.generateIChatBaseComponent(getMessage()), chatMessageTypeInstance, uuid);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -220,14 +187,7 @@ public final class WrappedPacketOutChat extends WrappedPacket implements Sendabl
|
||||
public String getMessage() {
|
||||
if (packet != null) {
|
||||
final Object iChatBaseObj = readObject(0, iChatBaseComponentClass);
|
||||
|
||||
try {
|
||||
Object contentString = Reflection.getMethod(iChatBaseComponentClass, String.class, 0).invoke(iChatBaseObj);
|
||||
return contentString.toString();
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
return NMSUtils.readIChatBaseComponent(iChatBaseObj);
|
||||
} else {
|
||||
return message;
|
||||
}
|
||||
@@ -243,27 +203,41 @@ public final class WrappedPacketOutChat extends WrappedPacket implements Sendabl
|
||||
*/
|
||||
public ChatPosition getChatPosition() {
|
||||
if (packet != null) {
|
||||
byte chatPosInteger = 0;
|
||||
byte chatPositionValue;
|
||||
switch (constructorMode) {
|
||||
case -1:
|
||||
chatPositionValue = (byte) ChatPosition.CHAT.ordinal();
|
||||
break;
|
||||
case 0:
|
||||
chatPosInteger = readByte(0);
|
||||
chatPositionValue = readByte(0);
|
||||
break;
|
||||
case 1:
|
||||
chatPosInteger = (byte) readInt(0);
|
||||
chatPositionValue = (byte) readInt(0);
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
Object chatTypeEnumInstance = readObject(0, chatMessageTypeEnum);
|
||||
chatPosInteger = cachedChatMessageTypeIntegers.get(chatTypeEnumInstance.toString());
|
||||
return ChatPosition.valueOf(chatTypeEnumInstance.toString());
|
||||
default:
|
||||
chatPositionValue = 0;
|
||||
break;
|
||||
}
|
||||
return cachedChatPositionIntegers.get(chatPosInteger);
|
||||
return ChatPosition.getByPositionValue(chatPositionValue);
|
||||
} else {
|
||||
return chatPosition;
|
||||
}
|
||||
}
|
||||
|
||||
public enum ChatPosition {
|
||||
CHAT, SYSTEM_MESSAGE, GAME_INFO
|
||||
CHAT,
|
||||
SYSTEM_MESSAGE,
|
||||
GAME_INFO;
|
||||
|
||||
ChatPosition() {
|
||||
}
|
||||
|
||||
public static ChatPosition getByPositionValue(byte position) {
|
||||
return values()[position];
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
-9
@@ -33,9 +33,16 @@ import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public class WrappedPacketOutCloseWindow extends WrappedPacket implements SendableWrapper {
|
||||
private static Constructor<?> constructor;
|
||||
private int windowID;
|
||||
|
||||
private static Constructor<?> constructor;
|
||||
public WrappedPacketOutCloseWindow(NMSPacket packet) {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
public WrappedPacketOutCloseWindow(int windowID) {
|
||||
this.windowID = windowID;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void load() {
|
||||
@@ -46,14 +53,6 @@ public class WrappedPacketOutCloseWindow extends WrappedPacket implements Sendab
|
||||
}
|
||||
}
|
||||
|
||||
public WrappedPacketOutCloseWindow(NMSPacket packet) {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
public WrappedPacketOutCloseWindow(int windowID) {
|
||||
this.windowID = windowID;
|
||||
}
|
||||
|
||||
public int getWindowId() {
|
||||
if (packet != null) {
|
||||
return readInt(0);
|
||||
@@ -61,6 +60,14 @@ public class WrappedPacketOutCloseWindow extends WrappedPacket implements Sendab
|
||||
return windowID;
|
||||
}
|
||||
|
||||
public void setWindowId(int windowID) {
|
||||
if (packet != null) {
|
||||
writeInt(0, windowID);
|
||||
} else {
|
||||
this.windowID = windowID;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object asNMSPacket() {
|
||||
try {
|
||||
|
||||
+34
@@ -122,6 +122,21 @@ public class WrappedPacketOutCustomPayload extends WrappedPacket implements Send
|
||||
return tag;
|
||||
}
|
||||
|
||||
public void setTag(String tag) {
|
||||
if (packet != null) {
|
||||
switch (constructorMode) {
|
||||
case 0:
|
||||
case 1:
|
||||
writeString(0, tag);
|
||||
case 2:
|
||||
Object minecraftKey = NMSUtils.generateMinecraftKey(tag);
|
||||
write(NMSUtils.minecraftKeyClass, minecraftKeyIndexInClass, minecraftKey);
|
||||
}
|
||||
} else {
|
||||
this.tag = tag;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
if (packet != null) {
|
||||
switch (constructorMode) {
|
||||
@@ -141,6 +156,25 @@ public class WrappedPacketOutCustomPayload extends WrappedPacket implements Send
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(byte[] data) {
|
||||
if (packet != null) {
|
||||
switch (constructorMode) {
|
||||
case 0:
|
||||
writeByteArray(0, data);
|
||||
case 1:
|
||||
case 2:
|
||||
Object dataSerializer = readObject(0, packetDataSerializerClass);
|
||||
WrappedPacket dataSerializerWrapper = new WrappedPacket(new NMSPacket(dataSerializer));
|
||||
|
||||
Object byteBuf = dataSerializerWrapper.readObject(0, byteBufClass);
|
||||
PacketEvents.get().getByteBufUtil().setBytes(byteBuf, data);
|
||||
}
|
||||
|
||||
} else {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object asNMSPacket() {
|
||||
byte[] data = getData();
|
||||
|
||||
Loaded 100 of 189 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user