Compare commits

..
85 Commits
Author SHA1 Message Date
retrooper e3a984ca72 Merge remote-tracking branch 'origin/master' 2024-07-18 00:09:35 +02:00
retrooper f8fad9607b Really... 2024-07-18 00:09:14 +02:00
retrooper a9e40c2abc Genuinely last push now 2024-07-17 23:47:20 +02:00
retrooper da12521d0b Final commit to this... 2024-07-17 23:38:28 +02:00
retrooper de1f91104d Now really should be the last commit for this ancient version. 2024-06-23 12:46:10 +02:00
retrooper f02b77c0ba Probably last commit but silence trivial uninjection error. 2024-06-21 00:32:07 +02:00
retrooper bf2e88ed8f minimal update for pe 1.8 (likely one of the last) 2024-06-19 14:49:43 +02:00
retrooper f04a3c75a9 fixes to attribute snapshot 2024-06-03 05:20:22 +02:00
retrooper 80408424dd fixes to attribute snapshot 2024-06-02 20:52:09 +02:00
retrooper cb897dabe5 fixes to client command 2024-05-31 19:47:02 +02:00
retrooper 92cb0d024d fixes 2 2024-05-30 23:17:08 +02:00
retrooper 72e617624a fixes 2024-05-30 22:52:04 +02:00
retrooper 239d712b5f Fixes entity effect 2024-05-30 19:40:18 +02:00
retrooper 9b9ab1ade6 Fixes 2024-05-30 01:00:52 +02:00
retrooper 63383579b4 fixes 2024-05-30 00:42:30 +02:00
retrooper a2e19f7020 Fix WrappedPacketInCustomPayload 2024-05-28 20:32:15 +02:00
retrooper 7ff578e1c6 Fix Bukkit package access code. 2024-05-28 06:42:37 +02:00
retrooper 95952588f1 * Added version constants for 1.20.5 & 1.20.6
* Updated minecraft internals to adapt to 1.20.5/1.20.6 (tested on paper experimental builds)
* Adapt to further breaking changes introduced by paper
* Updated custom payload wrapper for 1.20.5/1.20.6
2024-04-28 23:22:07 +02:00
retrooper 8d4d89f049 Fix WrappedPacketOutExplosion for 1.20.4 2023-12-27 15:24:04 +01:00
retrooper 74ddbacff5 1.20.3/1.20.4 support 2023-12-08 14:44:48 +01:00
retrooper 2b1d6c636d Update build.gradle 2023-11-19 17:50:47 +01:00
retrooper e47c10966e Fix build errors for jitpack 2023-11-04 23:42:12 +01:00
retrooper 9153aa6945 Attempt to replace spigot pt 3 2023-11-04 23:39:25 +01:00
retrooper 34e4007f7d Attempt to replace spigot pt 2 2023-11-04 23:33:51 +01:00
retrooper 0528eb7035 Attempt to replace spigot 2023-11-04 23:31:47 +01:00
retrooper 3a25a933ff Attempt to replace spigot 2023-11-04 23:30:44 +01:00
retrooper efa694c8e1 Fix the way we access network manager (for 1.20.2) 2023-11-04 23:11:27 +01:00
retrooper 289a71106a Fix WrappedPacketInCustomPayload and added CONFIG packet event 2023-10-07 21:24:07 +02:00
retrooper 012bcae2d5 Fix WrappedPacketHandshakingInSetProtocol implementation for 1.20.2 2023-10-03 00:18:52 +02:00
retrooper c84641cc83 Fix EntityEffect ID processing 2023-10-02 22:05:26 +02:00
retrooper baf93f527c Attempt to fix 2023-10-02 00:46:15 +02:00
retrooper d95d5394eb Bug fix for entity effect 2023-10-02 00:36:30 +02:00
retrooper 2675b41c3e 1.20.2 fix for entity effects 2023-10-02 00:25:22 +02:00
retrooper 4d27d6e967 1.20.2 should be working 2023-09-27 17:11:31 +02:00
retrooper 9ecadae4f9 Fix NPE when sending packets to null channels. 2023-09-16 18:20:23 +02:00
retrooper 5939573ee3 Able to detect 1.20.1 servers 2023-06-14 23:24:25 +02:00
retrooper 1bbc2cba77 Minimal 1.20 update for v1.8 packetevents 2023-06-12 17:59:24 +02:00
retrooper 1c35fe3b92 Ignore modern spoof players 2023-04-23 23:03:17 +02:00
retrooper e6a7b7a3b1 Fix weird entity player classes 2023-04-07 22:40:54 +02:00
retrooper 3581e23923 Minimal 1.19.4 update 2023-04-02 17:25:52 +02:00
MWHunter 33c0d9d934 fix multiple exceptions with update checker and clean up code 2023-02-25 23:25:56 -06:00
retrooper 70eaec04c7 Merge pull request #514 from FlorianMichael/master
fixed ArrayIndexOutOfBoundsException
2023-01-02 19:13:36 +01:00
JesseUwU be7aca69ef fixed ArrayIndexOutOfBoundsException
make WrappedPacketOutPlayerInfo#getPlayerInfo playerInfoArray big enough
2023-01-01 22:37:13 +01:00
retrooper 6777809d1c Update WrappedPacketOutEntityMetadata for 1.19.3 2022-12-12 18:33:36 +01:00
retrooper 39ec3dc117 WrappedPacketOutPlayerInfo was removed in 1.19.3 2022-12-11 00:07:06 +01:00
retrooper d52a96722d Minimal 1.19.3 update 2022-12-10 23:42:13 +01:00
retrooper 7e76aaa2af trying to fix spoofmc errors once again... 2022-12-10 23:37:56 +01:00
retrooper 022c081527 Cache channels for logged in players. 2022-10-03 19:32:06 +02:00
retrooper 0b3f49cc53 Ignore fake connections. 2022-10-03 18:12:13 +02:00
AoElite 54a68013f8 fix chat exception (#476) 2022-09-07 23:45:36 +02:00
retrooper 3b947e7b9a 1.19.2 support is ready 2022-08-05 17:07:04 +02:00
retrooper 01b201cef9 Fix for injection desync on late injectors. 2022-08-04 18:33:12 +02:00
retrooper 8fdd8e5676 Preparing for 1.19.2 update. 2022-08-04 18:31:02 +02:00
retrooper 7fd4015b4f Added dependency 2022-08-02 17:33:00 +02:00
retrooper 4f2f355a98 Minor fix for WrappedPacketOutChat on 1.19+ when loading. 2022-08-02 17:28:31 +02:00
Julianandretrooper 62afe05c28 1.19.1 Update (PE 1.8) (#453)
* feat: add 1.19.1 version support to Client-/ & Server version

* feat: added 1.19.1 support to CLIENT_VERSIONS array

* feat: updated ChatPosition and added little TODO comment

* feat: added `getPlayerUUID` and `setPlayerUUID` to WrappedPacketLoginInStart (still needs SignatureData)

* Added minimal 1.19.1 support, only wrapper complete 1.19.1 support is PlayerInfo.

Won't add the newly 1.19.1 created wrappers as this version is slowly dying

Co-authored-by: retrooper <retrooperdev@gmail.com>
2022-08-02 06:12:34 +02:00
retrooper b910cd189f Merge remote-tracking branch 'origin/master' 2022-07-18 08:31:22 +02:00
retrooper 1692451244 Support multiple channel types now. (IO_URING fix for you guys) & Fix SpoofMC 2022-07-18 08:31:10 +02:00
retrooper 26fde1e9a3 Fix WrappedPacketOutEntityEffect for 1.19 2022-06-22 14:43:34 +02:00
retrooper 5e42bef488 Minor changes to Main class 2022-06-20 05:49:17 +02:00
retrooper f7aacf1ad6 WrappedPacketOutEntityEffect 1.19 support,
SystemChat relocated
2022-06-20 05:42:17 +02:00
retrooper 87aedb23fd WrappedPacketOutEntity 1.19 support 2022-06-20 05:23:31 +02:00
retrooper bf60cb0543 No debugs. 2022-06-18 20:38:51 +02:00
retrooper 367f561eb3 WrappedPacketOutSystemChat created along with its PacketType 2022-06-18 20:38:35 +02:00
retrooper bb9132a673 WrappedPacketOutChat now minimally supports 1.19 (atleast reading) 2022-06-18 20:10:16 +02:00
retrooper b843499ac6 WrappedPacketInChat now has the 1.19 features 2022-06-18 20:00:31 +02:00
retrooper 8809088b66 Since our game profiles don't support texture property reading we're going to make login success packet unsendable. (Which means packetevents plugins can't send it using our API, please update to 2.0 if you need this feature) 2022-06-18 19:50:47 +02:00
retrooper d5d4a9bffc Fixed WrappedPacketOutSetSlot for 1.17.1+
Fixed WrappedPacketLoginInEncryptionBegin for 1.19+
2022-06-18 19:44:00 +02:00
retrooper 14f3d26630 Minor progress 2022-06-16 22:00:46 +02:00
retrooper dacf44dc29 Merge remote-tracking branch 'origin/master' 2022-06-16 08:14:37 +02:00
retrooper b2d7219105 Working on 1.19 support but its not working? 2022-06-16 08:14:22 +02:00
retrooper 362bb8dbe7 Merge pull request #413 from Jaren8r/patch-1
Fix GPLv3 badge link
2022-05-30 13:54:09 +02:00
Jaren 59935293a6 Fix GPLv3 badge link
It was going to a blob on the dev branch, which no longer exists.
2022-05-30 07:52:42 -04:00
retrooper 1c0d932c48 Bump up version to 1.8.4;
Deprecated the "async" loading methods in PacketEvents.java
2022-04-27 19:25:59 +02:00
retrooper c43d992619 Removed debugs. 2022-04-27 19:22:32 +02:00
retrooper c2e0fe6b4c More changes to README 2022-04-17 22:49:08 +02:00
retrooper 14a783560c Removed currently deleted pages 2022-04-17 22:42:04 +02:00
retrooper 2767b99479 We now don't discard packets sent by bytebuf packet plugins (for example beta 2.0 version of packetevents) 2022-04-15 22:43:54 +02:00
retrooper 3d7a0d901f WrappedPacketOutBlockChange hopefully now supports 1.18.1+ 2022-03-31 23:05:25 +02:00
retrooper 177e9b7f4e Releasing 1.8.3 2022-03-24 20:07:23 +01:00
retrooper 4711ede9bc Merge remote-tracking branch 'origin/master' 2022-03-22 23:03:22 +01:00
retrooper 6bd531efc0 Fixed 1.7 injector noclassdefined errors. 2022-03-22 23:03:11 +01:00
retrooper d6f1bf972e Updated bug report template. 2022-03-22 21:00:14 +01:00
retrooper 3295b1fc89 Update feature_request.md 2022-03-10 23:28:36 +01:00
retrooper f620e45a9c Update feature_request.md 2022-03-10 23:27:10 +01:00
65 changed files with 1668 additions and 394 deletions

No files matched your search

+15 -18
View File
@@ -1,7 +1,7 @@
---
name: Bug report
about: Report a bug to help us fix
title: "[BUG REPORT]"
about: Report bugs to help us improve our software.
title: ""
labels: bug
assignees: ''
@@ -10,11 +10,21 @@ assignees: ''
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
**Software brand**
Please let us know what software you are using.
Eg. Spigot 1.18.2, Paper 1.18.2, Tuinity 1.18.2, Pufferfish 1.18.2, etc...
Make sure to mention the version of the software.
**Plugins**
Please give us a list of your plugins. Sometimes we run into incompatibilities. Having an overview of the plugins on your server can really help identify the problem quicker.
Eg. ViaVersion, ProtocolLib, HolographicDisplays
You may also provide a screenshot.
**How To Reproduce**
Steps to reproduce the behavior:
*Example:*
1. Login on the 1.16.4 minecraft client.
2. Join the server while it is still starting up.
1. Join with the 1.18.2 vanilla minecraft client.
2. Spam
3. ....
4. See error
@@ -24,18 +34,5 @@ A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**About your server (please complete the following information):**
- Spigot: [eg. Paper or Tuinity]
We only accept reports that are reproducible
on one of the supported spigots.
- Server Version: [eg. 1.16.4]
Feel free to report bugs for versions newer than 1.7.10, even if we
don’t support them yet, but be aware that we might have already
found the bug and fixed it in a dev build, just before you reported it.
Please don’t get frustrated in such cases.
- Plugins List if possible: [eg. ViaVersion, ProtocolLib, HolographicDisplays]
**Additional context**
Add any other context about the problem here.
+2 -6
View File
@@ -1,9 +1,9 @@
# packetevents
[![](https://img.shields.io/badge/License-GPLv3-yellow.svg)](https://github.com/retrooper/packetevents/blob/dev/LICENSE)
[![](https://img.shields.io/badge/License-GPLv3-yellow.svg)](https://github.com/retrooper/packetevents/blob/master/LICENSE)
[![](https://jitpack.io/v/retrooper/packetevents.svg)](https://jitpack.io/#retrooper/packetevents)
PacketEvents is an open-source Packet API. It has many cross-version packet-wrappers. You can process incoming and outgoing packets on the server. You can even send packets with our packet-wrappers. We are here to save you a ton of time.
PacketEvents is a powerful packet library. Our packet wrappers are efficient and easy to use. We support many protocol versions. (1.8+)
### Resources
* [SpigotMC](https://www.spigotmc.org/resources/packetevents-api.80279/)
@@ -13,10 +13,6 @@ PacketEvents is an open-source Packet API. It has many cross-version packet-wrap
### Setup
[Learn more](https://github.com/retrooper/packetevents/wiki/1.-Setup)
### Contributing/Forking
[Learn more](https://github.com/retrooper/packetevents/wiki/2.-Contributing-and-Forking)\
Our discord server has a role for contributors and forkers.
### Sponsorships
[![](https://www.ej-technologies.com/images/product_banners/jprofiler_small.png)](https://www.ej-technologies.com/products/jprofiler/overview.html)
+6 -10
View File
@@ -34,10 +34,6 @@ repositories {
url = uri('https://jitpack.io/')
}
maven {
url = uri('https://nexus.funkemunky.cc/content/repositories/releases/')
}
maven {
url = uri('https://repo.viaversion.com/')
}
@@ -53,23 +49,23 @@ repositories {
}
dependencies {
implementation 'org.jetbrains:annotations:22.0.0'
implementation 'org.jetbrains:annotations:23.0.0'
compileOnly 'org.spigotmc:spigot-api:1.17-R0.1-SNAPSHOT'
compileOnly 'com.destroystokyo.paper:paper-api:1.16.5-R0.1-SNAPSHOT'
compileOnly 'com.viaversion:viaversion-api:4.0.1'
compileOnly 'com.github.ProtocolSupport:ProtocolSupport:3d24efeda6'
compileOnly 'org.github.spigot:1.16.2:1.16.2'
compileOnly 'org.github.spigot:1.8.8:1.8.8'
compileOnly 'org.github.spigot:1.7.10:1.7.10'
compileOnly group: 'com.github.azbh111', name: 'craftbukkit-1.14.3', version: 'R'
compileOnly group: 'com.github.azbh111', name: 'craftbukkit-1.8.8', version: 'R'
compileOnly group: 'com.github.azbh111', name: 'craftbukkit-1.7.10', version: 'R'
}
group = 'io.github.retrooper'
version = '1.8.2'
version = '1.8.4'
description = 'packetevents'
java.sourceCompatibility = JavaVersion.VERSION_1_8
java.targetCompatibility = JavaVersion.VERSION_1_8
publishing {
publications {
maven(MavenPublication) {
@@ -57,7 +57,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
public final class PacketEvents implements Listener, EventManager {
private static PacketEvents instance;
private static Plugin plugin;
private final PEVersion version = new PEVersion(1, 8, 2);
private final PEVersion version = new PEVersion(1, 8, 4);
private final EventManager eventManager = new PEEventManager();
private final PlayerUtils playerUtils = new PlayerUtils();
private final ServerUtils serverUtils = new ServerUtils();
@@ -161,10 +161,12 @@ public final class PacketEvents implements Listener, EventManager {
}
}
@Deprecated
public void loadAsyncNewThread() {
new Thread(this::load).start();
}
@Deprecated
public void loadAsync(ExecutorService executorService) {
executorService.execute(this::load);
}
@@ -18,17 +18,34 @@
package io.github.retrooper.packetevents;
import io.github.retrooper.packetevents.event.PacketListenerAbstract;
import io.github.retrooper.packetevents.event.impl.PacketConfigReceiveEvent;
import io.github.retrooper.packetevents.event.impl.PacketPlayReceiveEvent;
import io.github.retrooper.packetevents.event.impl.PacketPlaySendEvent;
import io.github.retrooper.packetevents.packettype.PacketType;
import io.github.retrooper.packetevents.packetwrappers.play.in.blockdig.WrappedPacketInBlockDig;
import io.github.retrooper.packetevents.packetwrappers.play.in.custompayload.WrappedPacketInCustomPayload;
import io.github.retrooper.packetevents.packetwrappers.play.in.entityaction.WrappedPacketInEntityAction;
import io.github.retrooper.packetevents.packetwrappers.play.in.flying.WrappedPacketInFlying;
import io.github.retrooper.packetevents.packetwrappers.play.in.useentity.WrappedPacketInUseEntity;
import io.github.retrooper.packetevents.packetwrappers.play.out.entity.WrappedPacketOutEntity;
import io.github.retrooper.packetevents.packetwrappers.play.out.entityeffect.WrappedPacketOutEntityEffect;
import io.github.retrooper.packetevents.packetwrappers.play.out.entityvelocity.WrappedPacketOutEntityVelocity;
import io.github.retrooper.packetevents.packetwrappers.play.out.setslot.WrappedPacketOutSetSlot;
import io.github.retrooper.packetevents.settings.PacketEventsSettings;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
import java.nio.charset.StandardCharsets;
public class PacketEventsPlugin extends JavaPlugin {
@Override
public void onLoad() {
PacketEventsSettings settings = PacketEvents.create(this).getSettings();
settings
.fallbackServerVersion(ServerVersion.getLatest())
.compatInjector(false)
.checkForUpdates(true)
.bStats(true);
PacketEvents.get().loadAsyncNewThread();
@@ -37,6 +54,59 @@ public class PacketEventsPlugin extends JavaPlugin {
@Override
public void onEnable() {
/*PacketEvents.get().getEventManager().registerListener(new PacketListenerAbstract() {
@Override
public void onPacketPlayReceive(PacketPlayReceiveEvent event) {
if (event.getPacketId() == PacketType.Play.Client.USE_ENTITY) {
System.out.println("Yes");
WrappedPacketInUseEntity ue = new WrappedPacketInUseEntity(event.getNMSPacket());
event.getPlayer().sendMessage("action: " + ue.getAction());
event.getPlayer().sendMessage("target: " + ue.getTarget());
ItemStack stack = new ItemStack(Material.STICK);
WrappedPacketOutSetSlot setSlot = new WrappedPacketOutSetSlot(0, 37, stack);
PacketEvents.get().getPlayerUtils().sendPacket(event.getPlayer(), setSlot);
} else if (event.getPacketId() == PacketType.Play.Client.CUSTOM_PAYLOAD) {
WrappedPacketInCustomPayload cp = new WrappedPacketInCustomPayload(event.getNMSPacket());
String name = cp.getChannelName();
System.out.println("name play: " + name);
System.out.println("Data: " + ((new String(cp.getData(), StandardCharsets.UTF_8))));
}
else if (event.getPacketId() == PacketType.Play.Client.ENTITY_ACTION) {
WrappedPacketInEntityAction ea = new WrappedPacketInEntityAction(event.getNMSPacket());
event.getPlayer().sendMessage("EA: " + ea.getAction());
} else if (PacketType.Play.Client.BLOCK_DIG == event.getPacketId()) {
WrappedPacketInBlockDig bd = new WrappedPacketInBlockDig(event.getNMSPacket());
event.getPlayer().sendMessage("bd: " + bd.getDigType());
}
else if (PacketType.Play.Client.Util.isInstanceOfFlying(event.getPacketId())) {
WrappedPacketInFlying f = new WrappedPacketInFlying(event.getNMSPacket());
System.out.println("flying: " + f.getPosition().toString() + ", pitch and yaw: " + f.getPitch() + ", " + f.getYaw());
}
}
@Override
public void onPacketConfigReceive(PacketConfigReceiveEvent event) {
if (event.getPacketId() == PacketType.Play.Client.CUSTOM_PAYLOAD) {
WrappedPacketInCustomPayload cp = new WrappedPacketInCustomPayload(event.getNMSPacket());
String name = cp.getChannelName();
System.out.println("name: " + name);
System.out.println("Data: " + ((new String(cp.getData(), StandardCharsets.UTF_8))));
}
}
@Override
public void onPacketPlaySend(PacketPlaySendEvent event) {
if (PacketType.Play.Server.Util.isInstanceOfEntity(event.getPacketId())) {
WrappedPacketOutEntity entity = new WrappedPacketOutEntity(event.getNMSPacket());
} else if (event.getPacketId() == PacketType.Play.Server.ENTITY_EFFECT) {
WrappedPacketOutEntityEffect eff = new WrappedPacketOutEntityEffect(event.getNMSPacket());
//TODO Broken on 1.20.5 eff.setEffectId(eff.getEffectId());
System.out.println("eff: " + eff.getEffectId() + ", ampl: " + eff.getAmplifier() + ", dur:" + eff.getDuration());
} else if (event.getPacketId() == PacketType.Play.Server.ENTITY_VELOCITY) {
WrappedPacketOutEntityVelocity ev = new WrappedPacketOutEntityVelocity(event.getNMSPacket());
}
}
});*/
PacketEvents.get().init();
}
@@ -80,6 +80,12 @@ public abstract class PacketListenerAbstract {
public void onPacketLoginSend(PacketLoginSendEvent event) {
}
public void onPacketConfigReceive(PacketConfigReceiveEvent event) {
}
public void onPacketConfigSend(PacketConfigSendEvent event) {
}
public void onPacketPlayReceive(PacketPlayReceiveEvent event) {
}
@@ -0,0 +1,44 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2021 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.PacketListenerAbstract;
import io.github.retrooper.packetevents.event.eventtypes.CancellableNMSPacketEvent;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
/**
* The {@code PacketConfigReceiveEvent} event is fired whenever the a CONFIG packet is received from a client.
* Use the {@link #getSocketAddress()} to identify who sends the packet.
*
* @author retrooper
* @see <a href="https://wiki.vg/Protocol#Configuration">https://wiki.vg/Protocol#Configuration</a>
* @since 1.8
*/
public class PacketConfigReceiveEvent extends CancellableNMSPacketEvent {
public PacketConfigReceiveEvent(Object channel, NMSPacket packet) {
super(channel, packet);
}
@Override
public void call(PacketListenerAbstract listener) {
if (listener.clientSidedLoginAllowance == null || listener.clientSidedLoginAllowance.contains(getPacketId())) {
listener.onPacketConfigReceive(this);
}
}
}
@@ -0,0 +1,62 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2021 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.PacketListenerAbstract;
import io.github.retrooper.packetevents.event.eventtypes.CancellableNMSPacketEvent;
import io.github.retrooper.packetevents.event.eventtypes.PostTaskEvent;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import org.jetbrains.annotations.NotNull;
/**
* The {@code PacketConfigSendEvent} event is fired whenever the a LOGIN packet is being planned to be sent to the client.
* Use the {@link #getSocketAddress()} to identify who sends the packet.
*
* @author retrooper
* @see <a href="https://wiki.vg/Protocol#Configuration">https://wiki.vg/Protocol#Configuration</a>
* @since 1.8
*/
public class PacketConfigSendEvent extends CancellableNMSPacketEvent implements PostTaskEvent {
private Runnable postTask;
public PacketConfigSendEvent(Object channel, NMSPacket packet) {
super(channel, packet);
}
@Override
public boolean isPostTaskAvailable() {
return postTask != null;
}
@Override
public Runnable getPostTask() {
return postTask;
}
@Override
public void setPostTask(@NotNull Runnable postTask) {
this.postTask = postTask;
}
@Override
public void call(PacketListenerAbstract listener) {
if (listener.serverSidedLoginAllowance == null || listener.serverSidedLoginAllowance.contains(getPacketId())) {
listener.onPacketConfigSend(this);
}
}
}
@@ -20,6 +20,7 @@ package io.github.retrooper.packetevents.injector.legacy;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.processor.PacketProcessorInternal;
import net.minecraft.util.io.netty.buffer.ByteBuf;
import net.minecraft.util.io.netty.channel.ChannelDuplexHandler;
import net.minecraft.util.io.netty.channel.ChannelHandler;
import net.minecraft.util.io.netty.channel.ChannelHandlerContext;
@@ -44,6 +45,11 @@ public class PlayerChannelHandlerLegacy extends ChannelDuplexHandler {
@Override
public void write(final ChannelHandlerContext ctx, Object packet, final ChannelPromise promise) throws Exception {
if (packet instanceof ByteBuf) {
//Ignore bytebufs!
super.write(ctx, packet, promise);
return;
}
PacketProcessorInternal.PacketData data = PacketEvents.get().getInternalPacketProcessor().write(player, ctx.channel(), packet);
if (data.postAction != null) {
promise.addListener(f -> {
@@ -25,12 +25,11 @@ import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.list.ListWrapper;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.netty.channel.epoll.EpollSocketChannel;
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
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.nio.NioSocketChannel;
import org.bukkit.entity.Player;
import org.bukkit.plugin.PluginDescriptionFile;
@@ -129,12 +128,10 @@ public class EarlyChannelInjectorLegacy implements EarlyInjector {
for (Object networkManager : networkManagers) {
WrappedPacket networkManagerWrapper = new WrappedPacket(new NMSPacket(networkManager), NMSUtils.networkManagerClass);
Channel channel = (Channel) networkManagerWrapper.readObject(0, NMSUtils.nettyChannelClass);
if (channel == null ||
(!(channel.getClass().equals(NioSocketChannel.class))) &&
!(channel.getClass().equals(EpollSocketChannel.class))) {
if (channel == null || ClassUtil.getClassSimpleName(channel.getClass()).equals("FakeChannel")
|| ClassUtil.getClassSimpleName(channel.getClass()).equals("SpoofedChannel")) {
continue;
}
if (channel.pipeline().get(PacketEvents.get().getHandlerName()) != null) {
channel.pipeline().remove(PacketEvents.get().getHandlerName());
}
@@ -230,7 +227,7 @@ public class EarlyChannelInjectorLegacy implements EarlyInjector {
childHandlerField.set(bootstrapAcceptor, ((PEChannelInitializerLegacy) oldInit).getOldChannelInitializer());
}
} catch (Exception e) {
PacketEvents.get().getPlugin().getLogger().severe("PacketEvents failed to eject the injection handler! Please reboot!");
//PacketEvents.get().getPlugin().getLogger().severe("PacketEvents failed to eject the injection handler! Please reboot!");
}
}
injectedFutures.clear();
@@ -246,7 +243,7 @@ public class EarlyChannelInjectorLegacy implements EarlyInjector {
}
} catch (IllegalAccessException e) {
PacketEvents.get().getPlugin().getLogger().severe("PacketEvents failed to eject the injection handler! Please reboot!!");
//PacketEvents.get().getPlugin().getLogger().severe("PacketEvents failed to eject the injection handler! Please reboot!!");
}
}
@@ -286,18 +283,33 @@ public class EarlyChannelInjectorLegacy implements EarlyInjector {
@Override
public void writePacket(Object ch, Object rawNMSPacket) {
Channel channel = (Channel) ch;
//Don't write packets to fake channels
if (channel == null || ClassUtil.getClassSimpleName(channel.getClass()).equals("FakeChannel")
|| ClassUtil.getClassSimpleName(channel.getClass()).equals("SpoofedChannel")) {
return;
}
channel.write(rawNMSPacket);
}
@Override
public void flushPackets(Object ch) {
Channel channel = (Channel) ch;
//Don't flush packets for fake channels
if (channel == null || ClassUtil.getClassSimpleName(channel.getClass()).equals("FakeChannel")
|| ClassUtil.getClassSimpleName(channel.getClass()).equals("SpoofedChannel")) {
return;
}
channel.flush();
}
@Override
public void sendPacket(Object ch, Object rawNMSPacket) {
Channel channel = (Channel) ch;
//Don't send packets to fake channels
if (channel == null || ClassUtil.getClassSimpleName(channel.getClass()).equals("FakeChannel")
|| ClassUtil.getClassSimpleName(channel.getClass()).equals("SpoofedChannel")) {
return;
}
channel.writeAndFlush(rawNMSPacket);
}
@@ -20,11 +20,10 @@ package io.github.retrooper.packetevents.injector.legacy.early;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.injector.legacy.PlayerChannelHandlerLegacy;
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
import io.github.retrooper.packetevents.utils.reflection.Reflection;
import io.netty.channel.epoll.EpollSocketChannel;
import net.minecraft.util.io.netty.channel.Channel;
import net.minecraft.util.io.netty.channel.ChannelInitializer;
import net.minecraft.util.io.netty.channel.socket.nio.NioSocketChannel;
import java.lang.reflect.Method;
@@ -49,15 +48,16 @@ public class PEChannelInitializerLegacy extends ChannelInitializer<Channel> {
protected void initChannel(Channel channel) throws Exception {
initChannelMethod.invoke(oldChannelInitializer, channel);
PlayerChannelHandlerLegacy channelHandler = new PlayerChannelHandlerLegacy();
if (channel.getClass().equals(NioSocketChannel.class)
|| channel.getClass().equals(EpollSocketChannel.class)) {
if (channel.pipeline().get("packet_handler") != null) {
String handlerName = PacketEvents.get().getHandlerName();
if (channel.pipeline().get(handlerName) != null) {
PacketEvents.get().getPlugin().getLogger().warning("[PacketEvents] Attempted to initialize a channel twice!");
} else {
channel.pipeline().addBefore("packet_handler", handlerName, channelHandler);
}
if (channel == null || ClassUtil.getClassSimpleName(channel.getClass()).equals("FakeChannel")
|| ClassUtil.getClassSimpleName(channel.getClass()).equals("SpoofedChannel")) {
return;
}
if (channel.pipeline().get("packet_handler") != null) {
String handlerName = PacketEvents.get().getHandlerName();
if (channel.pipeline().get(handlerName) != null) {
PacketEvents.get().getPlugin().getLogger().warning("[PacketEvents] Attempted to initialize a channel twice!");
} else {
channel.pipeline().addBefore("packet_handler", handlerName, channelHandler);
}
}
}
@@ -21,9 +21,8 @@ package io.github.retrooper.packetevents.injector.legacy.late;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.injector.LateInjector;
import io.github.retrooper.packetevents.injector.legacy.PlayerChannelHandlerLegacy;
import io.netty.channel.epoll.EpollSocketChannel;
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
import net.minecraft.util.io.netty.channel.Channel;
import net.minecraft.util.io.netty.channel.socket.nio.NioSocketChannel;
import org.bukkit.entity.Player;
public class LateChannelInjectorLegacy implements LateInjector {
@@ -42,10 +41,11 @@ public class LateChannelInjectorLegacy implements LateInjector {
PlayerChannelHandlerLegacy playerChannelHandlerLegacy = new PlayerChannelHandlerLegacy();
playerChannelHandlerLegacy.player = player;
Channel channel = (Channel) PacketEvents.get().getPlayerUtils().getChannel(player);
if (channel.getClass().equals(NioSocketChannel.class)
|| channel.getClass().equals(EpollSocketChannel.class)) {
channel.pipeline().addBefore("packet_handler", PacketEvents.get().getHandlerName(), playerChannelHandlerLegacy);
}
if (channel != null) {
channel.eventLoop().execute(() -> {
channel.pipeline().addBefore("packet_handler", PacketEvents.get().getHandlerName(), playerChannelHandlerLegacy);
});
}
}
@Override
@@ -63,24 +63,39 @@ public class LateChannelInjectorLegacy implements LateInjector {
@Override
public boolean hasInjected(Player player) {
Channel channel = (Channel) PacketEvents.get().getPlayerUtils().getChannel(player);
return channel.pipeline().get(PacketEvents.get().getHandlerName()) != null;
return channel != null && channel.pipeline().get(PacketEvents.get().getHandlerName()) != null;
}
@Override
public void writePacket(Object ch, Object rawNMSPacket) {
Channel channel = (Channel) ch;
//Don't write packets to fake channels
if (channel == null || ClassUtil.getClassSimpleName(channel.getClass()).equals("FakeChannel")
|| ClassUtil.getClassSimpleName(channel.getClass()).equals("SpoofedChannel")) {
return;
}
channel.write(rawNMSPacket);
}
@Override
public void flushPackets(Object ch) {
Channel channel = (Channel) ch;
//Don't flush packets for fake channels
if (channel == null || ClassUtil.getClassSimpleName(channel.getClass()).equals("FakeChannel")
|| ClassUtil.getClassSimpleName(channel.getClass()).equals("SpoofedChannel")) {
return;
}
channel.flush();
}
@Override
public void sendPacket(Object rawChannel, Object packet) {
Channel channel = (Channel) rawChannel;
//Don't send packets to fake channels
if (channel == null || ClassUtil.getClassSimpleName(channel.getClass()).equals("FakeChannel")
|| ClassUtil.getClassSimpleName(channel.getClass()).equals("SpoofedChannel")) {
return;
}
channel.pipeline().writeAndFlush(packet);
}
}
@@ -20,11 +20,13 @@ package io.github.retrooper.packetevents.injector.modern;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.processor.PacketProcessorInternal;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import org.bukkit.entity.Player;
@ChannelHandler.Sharable
public class PlayerChannelHandlerModern extends ChannelDuplexHandler {
/**
@@ -44,6 +46,11 @@ public class PlayerChannelHandlerModern extends ChannelDuplexHandler {
@Override
public void write(final ChannelHandlerContext ctx, Object packet, final ChannelPromise promise) throws Exception {
if (packet instanceof ByteBuf) {
//Ignore bytebufs!
super.write(ctx, packet, promise);
return;
}
PacketProcessorInternal.PacketData data = PacketEvents.get().getInternalPacketProcessor().write(player, ctx.channel(), packet);
if (data.postAction != null) {
promise.addListener(f -> {
@@ -25,12 +25,11 @@ 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.ClassUtil;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.epoll.EpollSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.bukkit.entity.Player;
import org.bukkit.plugin.PluginDescriptionFile;
@@ -132,9 +131,8 @@ public class EarlyChannelInjectorModern implements EarlyInjector {
for (Object networkManager : networkManagers) {
WrappedPacket networkManagerWrapper = new WrappedPacket(new NMSPacket(networkManager), NMSUtils.networkManagerClass);
Channel channel = (Channel) networkManagerWrapper.readObject(0, NMSUtils.nettyChannelClass);
if (channel == null ||
(!(channel.getClass().equals(NioSocketChannel.class))) &&
!(channel.getClass().equals(EpollSocketChannel.class))) {
if (channel == null || ClassUtil.getClassSimpleName(channel.getClass()).equals("FakeChannel")
|| ClassUtil.getClassSimpleName(channel.getClass()).equals("SpoofedChannel")) {
continue;
}
@@ -239,7 +237,7 @@ public class EarlyChannelInjectorModern implements EarlyInjector {
childHandlerField.set(bootstrapAcceptor, ((PEChannelInitializerModern) oldInit).getOldChannelInitializer());
}
} catch (Exception e) {
PacketEvents.get().getPlugin().getLogger().severe("PacketEvents failed to eject the injection handler! Please reboot!");
//PacketEvents.get().getPlugin().getLogger().severe("PacketEvents failed to eject the injection handler! Please reboot!");
}
}
injectedFutures.clear();
@@ -255,7 +253,7 @@ public class EarlyChannelInjectorModern implements EarlyInjector {
}
} catch (IllegalAccessException e) {
PacketEvents.get().getPlugin().getLogger().severe("PacketEvents failed to eject the injection handler! Please reboot!!");
//PacketEvents.get().getPlugin().getLogger().severe("PacketEvents failed to eject the injection handler! Please reboot!!");
}
}
@@ -274,9 +272,8 @@ public class EarlyChannelInjectorModern implements EarlyInjector {
public void ejectPlayer(Player player) {
Object channel = PacketEvents.get().getPlayerUtils().getChannel(player);
if (channel != null) {
Channel chnl = (Channel) channel;
try {
chnl.pipeline().remove(PacketEvents.get().getHandlerName());
((Channel)channel).pipeline().remove(PacketEvents.get().getHandlerName());
} catch (Exception ignored) {
}
}
@@ -295,18 +292,33 @@ public class EarlyChannelInjectorModern implements EarlyInjector {
@Override
public void writePacket(Object ch, Object rawNMSPacket) {
Channel channel = (Channel) ch;
//Don't write packets to fake channels
if (channel == null || ClassUtil.getClassSimpleName(channel.getClass()).equals("FakeChannel")
|| ClassUtil.getClassSimpleName(channel.getClass()).equals("SpoofedChannel")) {
return;
}
channel.write(rawNMSPacket);
}
@Override
public void flushPackets(Object ch) {
Channel channel = (Channel) ch;
//Don't flush packets for fake channels
if (channel == null || ClassUtil.getClassSimpleName(channel.getClass()).equals("FakeChannel")
|| ClassUtil.getClassSimpleName(channel.getClass()).equals("SpoofedChannel")) {
return;
}
channel.flush();
}
@Override
public void sendPacket(Object ch, Object rawNMSPacket) {
Channel channel = (Channel) ch;
//Don't send packets to fake channels
if (channel == null || ClassUtil.getClassSimpleName(channel.getClass()).equals("FakeChannel")
|| ClassUtil.getClassSimpleName(channel.getClass()).equals("SpoofedChannel")) {
return;
}
channel.writeAndFlush(rawNMSPacket);
}
@@ -20,11 +20,10 @@ package io.github.retrooper.packetevents.injector.modern.early;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.injector.modern.PlayerChannelHandlerModern;
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
import io.github.retrooper.packetevents.utils.reflection.Reflection;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.epoll.EpollSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import java.lang.reflect.Method;
@@ -38,17 +37,18 @@ public class PEChannelInitializerModern extends ChannelInitializer<Channel> {
}
public static void postInitChannel(Channel channel) {
if (channel.getClass().equals(NioSocketChannel.class)
|| channel.getClass().equals(EpollSocketChannel.class)) {
PlayerChannelHandlerModern channelHandler = new PlayerChannelHandlerModern();
if (channel.pipeline().get("packet_handler") != null) {
String handlerName = PacketEvents.get().getHandlerName();
if (channel.pipeline().get(handlerName) != null) {
//Just ignore this to support latest ProtocolLib snapshots.
//PacketEvents.get().getPlugin().getLogger().warning("[PacketEvents] Attempted to initialize a channel twice!");
} else {
channel.pipeline().addBefore("packet_handler", handlerName, channelHandler);
}
if (channel == null || ClassUtil.getClassSimpleName(channel.getClass()).equals("FakeChannel")
|| ClassUtil.getClassSimpleName(channel.getClass()).equals("SpoofedChannel")) {
return;
}
PlayerChannelHandlerModern channelHandler = new PlayerChannelHandlerModern();
if (channel.pipeline().get("packet_handler") != null) {
String handlerName = PacketEvents.get().getHandlerName();
if (channel.pipeline().get(handlerName) != null) {
//Just ignore this to support latest ProtocolLib snapshots.
//PacketEvents.get().getPlugin().getLogger().warning("[PacketEvents] Attempted to initialize a channel twice!");
} else {
channel.pipeline().addBefore("packet_handler", handlerName, channelHandler);
}
}
}
@@ -21,9 +21,8 @@ package io.github.retrooper.packetevents.injector.modern.late;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.injector.LateInjector;
import io.github.retrooper.packetevents.injector.modern.PlayerChannelHandlerModern;
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
import io.netty.channel.Channel;
import io.netty.channel.epoll.EpollSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.bukkit.entity.Player;
public class LateChannelInjectorModern implements LateInjector {
@@ -42,9 +41,10 @@ public class LateChannelInjectorModern implements LateInjector {
PlayerChannelHandlerModern playerChannelHandlerModern = new PlayerChannelHandlerModern();
playerChannelHandlerModern.player = player;
Channel channel = (Channel) PacketEvents.get().getPlayerUtils().getChannel(player);
if (channel.getClass().equals(NioSocketChannel.class) ||
channel.getClass().equals(EpollSocketChannel.class)) {
channel.pipeline().addBefore("packet_handler", PacketEvents.get().getHandlerName(), playerChannelHandlerModern);
if (channel != null) {
channel.eventLoop().execute(() -> {
channel.pipeline().addBefore("packet_handler", PacketEvents.get().getHandlerName(), playerChannelHandlerModern);
});
}
}
@@ -52,9 +52,8 @@ public class LateChannelInjectorModern implements LateInjector {
public void ejectPlayer(Player player) {
Object channel = PacketEvents.get().getPlayerUtils().getChannel(player);
if (channel != null) {
Channel chnl = (Channel) channel;
try {
chnl.pipeline().remove(PacketEvents.get().getHandlerName());
((Channel) channel).pipeline().remove(PacketEvents.get().getHandlerName());
} catch (Exception ex) {
}
@@ -64,24 +63,39 @@ public class LateChannelInjectorModern implements LateInjector {
@Override
public boolean hasInjected(Player player) {
Channel channel = (Channel) PacketEvents.get().getPlayerUtils().getChannel(player);
return channel.pipeline().get(PacketEvents.get().getHandlerName()) != null;
return channel != null && channel.pipeline().get(PacketEvents.get().getHandlerName()) != null;
}
@Override
public void writePacket(Object ch, Object rawNMSPacket) {
Channel channel = (Channel) ch;
//Don't write packets to fake channels
if (channel == null || ClassUtil.getClassSimpleName(channel.getClass()).equals("FakeChannel")
|| ClassUtil.getClassSimpleName(channel.getClass()).equals("SpoofedChannel")) {
return;
}
channel.write(rawNMSPacket);
}
@Override
public void flushPackets(Object ch) {
Channel channel = (Channel) ch;
//Don't flush packets for fake channels
if (channel == null || ClassUtil.getClassSimpleName(channel.getClass()).equals("FakeChannel")
|| ClassUtil.getClassSimpleName(channel.getClass()).equals("SpoofedChannel")) {
return;
}
channel.flush();
}
@Override
public void sendPacket(Object rawChannel, Object packet) {
Channel channel = (Channel) rawChannel;
//Don't send packets to fake channels
if (channel == null || ClassUtil.getClassSimpleName(channel.getClass()).equals("FakeChannel")
|| ClassUtil.getClassSimpleName(channel.getClass()).equals("SpoofedChannel")) {
return;
}
channel.pipeline().writeAndFlush(packet);
}
}
@@ -23,5 +23,5 @@ package io.github.retrooper.packetevents.packettype;
* @since 1.8
*/
public enum PacketState {
STATUS, HANDSHAKING, LOGIN, PLAY
STATUS, HANDSHAKING, LOGIN, CONFIG, PLAY
}
@@ -326,7 +326,7 @@ public class PacketType {
ADD_VIBRATION_SIGNAL = 30, CLEAR_TITLES = 31, INITIALIZE_BORDER = 32, PLAYER_COMBAT_END = 33,
PLAYER_COMBAT_ENTER = 34, PLAYER_COMBAT_KILL = 35, SET_ACTIONBAR_TEXT = 36, SET_BORDER_CENTER = 37,
SET_BORDER_LERP_SIZE = 38, SET_BORDER_SIZE = 39, SET_BORDER_WARNING_DELAY = 40, SET_BORDER_WARNING_DISTANCE = 41,
SET_SUBTITLE_TEXT = 42, SET_TITLES_ANIMATION = 43, SET_TITLE_TEXT = 44;
SET_SUBTITLE_TEXT = 42, SET_TITLES_ANIMATION = 43, SET_TITLE_TEXT = 44, SYSTEM_CHAT = 45;
private static void load() {
insertPacketID(PacketTypeClasses.Play.Server.SPAWN_ENTITY, SPAWN_ENTITY);
@@ -440,6 +440,7 @@ public class PacketType {
insertPacketID(PacketTypeClasses.Play.Server.SET_SUBTITLE_TEXT, SET_SUBTITLE_TEXT);
insertPacketID(PacketTypeClasses.Play.Server.SET_TITLES_ANIMATION, SET_TITLES_ANIMATION);
insertPacketID(PacketTypeClasses.Play.Server.SET_TITLE_TEXT, SET_TITLE_TEXT);
insertPacketID(PacketTypeClasses.Play.Server.SYSTEM_CHAT, SYSTEM_CHAT);
}
/**
@@ -48,7 +48,7 @@ public class PacketTypeClasses {
PREFIX = "net.minecraft.network.protocol.status.";
}
else {
PREFIX = ServerVersion.getNMSDirectory() + ".";
PREFIX = ServerVersion.getNMSDirectory();
}
Client.START = Reflection.getClassByNameWithoutException(PREFIX + "PacketStatusInStart");
Client.PING = Reflection.getClassByNameWithoutException(PREFIX + "PacketStatusInPing");
@@ -64,7 +64,7 @@ public class PacketTypeClasses {
PREFIX = "net.minecraft.network.protocol.status.";
}
else {
PREFIX = ServerVersion.getNMSDirectory() + ".";
PREFIX = ServerVersion.getNMSDirectory();
}
Server.PONG = Reflection.getClassByNameWithoutException(PREFIX + "PacketStatusOutPong");
Server.SERVER_INFO = Reflection.getClassByNameWithoutException(PREFIX + "PacketStatusOutServerInfo");
@@ -82,7 +82,7 @@ public class PacketTypeClasses {
PREFIX = "net.minecraft.network.protocol.handshake.";
}
else {
PREFIX = ServerVersion.getNMSDirectory() + ".";
PREFIX = ServerVersion.getNMSDirectory();
}
Handshaking.Client.SET_PROTOCOL = Reflection.getClassByNameWithoutException(PREFIX + "PacketHandshakingInSetProtocol");
}
@@ -99,7 +99,7 @@ public class PacketTypeClasses {
PREFIX = "net.minecraft.network.protocol.login.";
}
else {
PREFIX = ServerVersion.getNMSDirectory() + ".";
PREFIX = ServerVersion.getNMSDirectory();
}
//In and Out custom payload login packets have been here since 1.13
if (PacketEvents.get().getServerUtils().getVersion().isNewerThanOrEquals(ServerVersion.v_1_13)) {
@@ -119,7 +119,7 @@ public class PacketTypeClasses {
PREFIX = "net.minecraft.network.protocol.login.";
}
else {
PREFIX = ServerVersion.getNMSDirectory() + ".";
PREFIX = ServerVersion.getNMSDirectory();
}
//In and Out custom payload login packets have been here since 1.13
if (PacketEvents.get().getServerUtils().getVersion().isNewerThanOrEquals(ServerVersion.v_1_13)) {
@@ -137,8 +137,7 @@ public class PacketTypeClasses {
public static class Play {
public static class Client {
private static String COMMON_PREFIX;
private static String PREFIX;
private static String COMMON_PREFIX, PREFIX, PREFIX_COMMON_STATES;
public static Class<?> FLYING, POSITION, POSITION_LOOK, LOOK, GROUND, CLIENT_COMMAND,
TRANSACTION, BLOCK_DIG, ENTITY_ACTION, USE_ENTITY,
WINDOW_CLICK, STEER_VEHICLE, CUSTOM_PAYLOAD, ARM_ANIMATION,
@@ -157,9 +156,12 @@ public class PacketTypeClasses {
public static void load() {
if (PacketEvents.get().getServerUtils().getVersion().isNewerThanOrEquals(ServerVersion.v_1_17)) {
PREFIX = "net.minecraft.network.protocol.game.";
if (PacketEvents.get().getServerUtils().getVersion().isNewerThanOrEquals(ServerVersion.v_1_20_2)) {
PREFIX_COMMON_STATES = "net.minecraft.network.protocol.common.";
}
}
else {
PREFIX = ServerVersion.getNMSDirectory() + ".";
PREFIX = ServerVersion.getNMSDirectory();
}
COMMON_PREFIX = PREFIX + "PacketPlayIn";
FLYING = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "Flying");
@@ -174,6 +176,19 @@ public class PacketTypeClasses {
}
if (PacketEvents.get().getServerUtils().getVersion().isNewerThanOrEquals(ServerVersion.v_1_17)) {
GROUND = SubclassUtil.getSubClass(FLYING, "d");
if (GROUND == null) {
GROUND = SubclassUtil.getSubClass(FLYING, 0);
}
if (POSITION == null) {
POSITION = SubclassUtil.getSubClass(FLYING, 2);
}
if (POSITION_LOOK == null) {
POSITION_LOOK = SubclassUtil.getSubClass(FLYING, 3);
}
if (LOOK == null) {
LOOK = SubclassUtil.getSubClass(FLYING, 1);
}
}
else {
GROUND = FLYING;
@@ -182,17 +197,25 @@ public class PacketTypeClasses {
TRANSACTION = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "Transaction");
//This packet was added in 1.17 protocol
PONG = Reflection.getClassByNameWithoutException(PREFIX + "ServerboundPongPacket");
if (PONG == null) {
PONG = Reflection.getClassByNameWithoutException(PREFIX_COMMON_STATES + "ServerboundPongPacket");
}
SETTINGS = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "Settings");
if (SETTINGS == null) {
SETTINGS = Reflection.getClassByNameWithoutException(PREFIX_COMMON_STATES + "ServerboundClientInformationPacket");
}
try {
SETTINGS = Class.forName(COMMON_PREFIX + "Settings");
ENCHANT_ITEM = Class.forName(COMMON_PREFIX + "EnchantItem");
CLIENT_COMMAND = Class.forName(COMMON_PREFIX + "ClientCommand");
BLOCK_DIG = Class.forName(COMMON_PREFIX + "BlockDig");
ENTITY_ACTION = Class.forName(COMMON_PREFIX + "EntityAction");
USE_ENTITY = Class.forName(COMMON_PREFIX + "UseEntity");
WINDOW_CLICK = Class.forName(COMMON_PREFIX + "WindowClick");
STEER_VEHICLE = Class.forName(COMMON_PREFIX + "SteerVehicle");
CUSTOM_PAYLOAD = Class.forName(COMMON_PREFIX + "CustomPayload");
CUSTOM_PAYLOAD = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "CustomPayload");
if (CUSTOM_PAYLOAD == null) {
CUSTOM_PAYLOAD = Reflection.getClassByNameWithoutException(PREFIX_COMMON_STATES + "ServerboundCustomPayloadPacket");
}
ARM_ANIMATION = Class.forName(COMMON_PREFIX + "ArmAnimation");
ABILITIES = Class.forName(COMMON_PREFIX + "Abilities");
HELD_ITEM_SLOT = Class.forName(COMMON_PREFIX + "HeldItemSlot");
@@ -200,7 +223,10 @@ public class PacketTypeClasses {
TAB_COMPLETE = Class.forName(COMMON_PREFIX + "TabComplete");
CHAT = Class.forName(COMMON_PREFIX + "Chat");
SET_CREATIVE_SLOT = Class.forName(COMMON_PREFIX + "SetCreativeSlot");
KEEP_ALIVE = Class.forName(COMMON_PREFIX + "KeepAlive");
KEEP_ALIVE = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "KeepAlive");
if (KEEP_ALIVE == null) {
KEEP_ALIVE = Reflection.getClassByNameWithoutException(PREFIX_COMMON_STATES + "ServerboundKeepAlivePacket");
}
UPDATE_SIGN = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "UpdateSign");
TELEPORT_ACCEPT = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "TeleportAccept");
@@ -241,7 +267,7 @@ public class PacketTypeClasses {
}
public static class Server {
private static String COMMON_PREFIX, PREFIX;
private static String COMMON_PREFIX, PREFIX, PREFIX_COMMON_STATES;
public static Class<?> SPAWN_ENTITY, SPAWN_ENTITY_EXPERIENCE_ORB, SPAWN_ENTITY_WEATHER, SPAWN_ENTITY_LIVING,
SPAWN_ENTITY_PAINTING, SPAWN_ENTITY_SPAWN, ANIMATION, STATISTIC,
BLOCK_BREAK, BLOCK_BREAK_ANIMATION, TILE_ENTITY_DATA, BLOCK_ACTION,
@@ -267,7 +293,8 @@ public class PacketTypeClasses {
ENTITY_EFFECT, RECIPE_UPDATE, TAGS, MAP_CHUNK_BULK, NAMED_ENTITY_SPAWN, PING, ADD_VIBRATION_SIGNAL,
CLEAR_TITLES, INITIALIZE_BORDER, PLAYER_COMBAT_END, PLAYER_COMBAT_ENTER, PLAYER_COMBAT_KILL,
SET_ACTIONBAR_TEXT, SET_BORDER_CENTER, SET_BORDER_LERP_SIZE, SET_BORDER_SIZE, SET_BORDER_WARNING_DELAY,
SET_BORDER_WARNING_DISTANCE, SET_SUBTITLE_TEXT, SET_TITLES_ANIMATION, SET_TITLE_TEXT;
SET_BORDER_WARNING_DISTANCE, SET_SUBTITLE_TEXT, SET_TITLES_ANIMATION, SET_TITLE_TEXT,
SYSTEM_CHAT;
/**
* Initiate all client-bound packet classes.
@@ -275,9 +302,12 @@ public class PacketTypeClasses {
public static void load() {
if (PacketEvents.get().getServerUtils().getVersion().isNewerThanOrEquals(ServerVersion.v_1_17)) {
PREFIX = "net.minecraft.network.protocol.game.";
if (PacketEvents.get().getServerUtils().getVersion().isNewerThanOrEquals(ServerVersion.v_1_20_2)) {
PREFIX_COMMON_STATES = "net.minecraft.network.protocol.common.";
}
}
else {
PREFIX = ServerVersion.getNMSDirectory() + ".";
PREFIX = ServerVersion.getNMSDirectory();
}
COMMON_PREFIX = PREFIX + "PacketPlayOut";
SPAWN_ENTITY = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "SpawnEntity");
@@ -296,6 +326,9 @@ public class PacketTypeClasses {
BOSS = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "Boss");
SERVER_DIFFICULTY = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "ServerDifficulty");
CHAT = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "Chat");
if (CHAT == null) {
CHAT = Reflection.getClassByNameWithoutException(PREFIX + "ClientboundPlayerChatPacket");
}
MULTI_BLOCK_CHANGE = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "MultiBlockChange");
TAB_COMPLETE = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "TabComplete");
COMMANDS = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "Commands");
@@ -306,14 +339,23 @@ public class PacketTypeClasses {
SET_SLOT = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "SetSlot");
SET_COOLDOWN = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "SetCooldown");
CUSTOM_PAYLOAD = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "CustomPayload");
if (CUSTOM_PAYLOAD == null) {
CUSTOM_PAYLOAD = Reflection.getClassByNameWithoutException(PREFIX_COMMON_STATES + "ClientboundCustomPayloadPacket");
}
CUSTOM_SOUND_EFFECT = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "CustomSoundEffect");
KICK_DISCONNECT = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "KickDisconnect");
if (KICK_DISCONNECT == null) {
KICK_DISCONNECT = Reflection.getClassByNameWithoutException(PREFIX_COMMON_STATES + "ClientboundDisconnectPacket");
}
ENTITY_STATUS = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "EntityStatus");
EXPLOSION = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "Explosion");
UNLOAD_CHUNK = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "UnloadChunk");
GAME_STATE_CHANGE = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "GameStateChange");
OPEN_WINDOW_HORSE = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "OpenWindowHorse");
KEEP_ALIVE = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "KeepAlive");
if (KEEP_ALIVE == null) {
KEEP_ALIVE = Reflection.getClassByNameWithoutException(PREFIX_COMMON_STATES + "ClientboundKeepAlivePacket");
}
MAP_CHUNK = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "MapChunk");
WORLD_EVENT = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "WorldEvent");
WORLD_PARTICLES = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "WorldParticles");
@@ -330,6 +372,16 @@ public class PacketTypeClasses {
REL_ENTITY_MOVE = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "RelEntityMove");
REL_ENTITY_MOVE_LOOK = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "RelEntityMoveLook");
ENTITY_LOOK = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "RelEntityLook");
if (REL_ENTITY_MOVE == null) {
REL_ENTITY_MOVE = SubclassUtil.getSubClass(ENTITY, 1);
}
if (REL_ENTITY_MOVE_LOOK == null) {
REL_ENTITY_MOVE_LOOK = SubclassUtil.getSubClass(ENTITY, 2);
}
if (ENTITY_LOOK == null) {
ENTITY_LOOK = SubclassUtil.getSubClass(ENTITY, 0);
}
}
VEHICLE_MOVE = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "VehicleMove");
OPEN_BOOK = Reflection.getClassByNameWithoutException(COMMON_PREFIX + "OpenBook");
@@ -384,6 +436,9 @@ public class PacketTypeClasses {
//These packets were added in 1.17
PING = Reflection.getClassByNameWithoutException(PREFIX + "ClientboundPingPacket");
if (PING == null) {
PING = Reflection.getClassByNameWithoutException(PREFIX_COMMON_STATES + "ClientboundPingPacket");
}
ADD_VIBRATION_SIGNAL = Reflection.getClassByNameWithoutException(PREFIX + "ClientboundAddVibrationSignalPacket");
CLEAR_TITLES = Reflection.getClassByNameWithoutException(PREFIX + "ClientboundClearTitlesPacket");
INITIALIZE_BORDER = Reflection.getClassByNameWithoutException(PREFIX + "ClientboundInitializeBorderPacket");
@@ -399,6 +454,7 @@ public class PacketTypeClasses {
SET_SUBTITLE_TEXT = Reflection.getClassByNameWithoutException(PREFIX + "ClientboundSetSubtitleTextPacket");
SET_TITLES_ANIMATION = Reflection.getClassByNameWithoutException(PREFIX + "ClientboundSetTitlesAnimationPacket");
SET_TITLE_TEXT = Reflection.getClassByNameWithoutException(PREFIX + "ClientboundSetTitleTextPacket");
SYSTEM_CHAT = Reflection.getClassByNameWithoutException(PREFIX + "ClientboundSystemChatPacket");
// 1.18+ only, doesn't follow the naming convention
if (MAP_CHUNK == null) {
@@ -24,6 +24,8 @@ import io.github.retrooper.packetevents.exceptions.WrapperUnsupportedUsageExcept
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
import io.github.retrooper.packetevents.packetwrappers.api.WrapperPacketReader;
import io.github.retrooper.packetevents.packetwrappers.api.WrapperPacketWriter;
import io.github.retrooper.packetevents.utils.ConditionalValue;
import io.github.retrooper.packetevents.utils.MojangEitherUtil;
import io.github.retrooper.packetevents.utils.enums.EnumUtil;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.player.GameMode;
@@ -43,11 +45,9 @@ import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
import java.util.logging.Level;
public class WrappedPacket implements WrapperPacketReader, WrapperPacketWriter {
@@ -416,9 +416,17 @@ public class WrappedPacket implements WrapperPacketReader, WrapperPacketWriter {
public Vector3i readBlockPosition(int index) {
Object blockPosObj = readObject(index, NMSUtils.blockPosClass);
try {
int x = (Integer) NMSUtils.getBlockPosX.invoke(blockPosObj);
int y = (Integer) NMSUtils.getBlockPosY.invoke(blockPosObj);
int z = (Integer) NMSUtils.getBlockPosZ.invoke(blockPosObj);
int x, y, z;
if (version.isNewerThanOrEquals(ServerVersion.v_1_20_5)) {
x = (int) NMSUtils.getBaseBlockPosX.get(blockPosObj);
y = (int) NMSUtils.getBaseBlockPosY.get(blockPosObj);
z = (int) NMSUtils.getBaseBlockPosZ.get(blockPosObj);
}
else {
x = (int) NMSUtils.getBlockPosX.invoke(blockPosObj);
y = (int) NMSUtils.getBlockPosY.invoke(blockPosObj);
z = (int) NMSUtils.getBlockPosZ.invoke(blockPosObj);
}
return new Vector3i(x, y, z);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
@@ -525,12 +533,7 @@ public class WrappedPacket implements WrapperPacketReader, WrapperPacketWriter {
}
public void writeMinecraftKey(int index, String content) {
Object minecraftKey = null;
try {
minecraftKey = NMSUtils.minecraftKeyConstructor.newInstance(content);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
Object minecraftKey = NMSUtils.generateMinecraftKeyNew(content);
write(NMSUtils.minecraftKeyClass, index, minecraftKey);
}
@@ -542,6 +545,34 @@ public class WrappedPacket implements WrapperPacketReader, WrapperPacketWriter {
write(List.class, index, list);
}
public <T, K> ConditionalValue<T, K> readEither(int index) {
Object either = readObject(index, NMSUtils.mojangEitherClass);
Optional<T> left = MojangEitherUtil.getLeft(either);
if (left.isPresent()) {
return ConditionalValue.makeLeft(left.get());
}
else {
Optional<K> right = MojangEitherUtil.getRight(either);
try {
return ConditionalValue.makeRight(right.orElseThrow((Supplier<Throwable>) () -> new IllegalStateException("Conditional value has no values. Atleast one side must have a value!")));
} catch (Throwable e) {
e.printStackTrace();
}
}
return null;
}
public <T, K> void writeEither(int index, ConditionalValue<T, K> conditionalValue) {
Object either;
if (conditionalValue.left().isPresent()) {
either = MojangEitherUtil.makeLeft(conditionalValue.left().get());
}
else {
either = MojangEitherUtil.makeRight(conditionalValue.right().get());
}
write(NMSUtils.mojangEitherClass, index, either);
}
private Field getField(Class<?> type, int index) {
Map<Class<?>, Field[]> cached = FIELD_CACHE.computeIfAbsent(packetClass, k -> new ConcurrentHashMap<>());
Field[] fields = cached.computeIfAbsent(type, typeClass -> getFields(typeClass, packetClass.getDeclaredFields()));
@@ -23,30 +23,30 @@ import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
public class WrappedPacketHandshakingInSetProtocol extends WrappedPacket {
private static boolean v_1_17;
private static boolean between_V_1_17_And_1_20_1;
public WrappedPacketHandshakingInSetProtocol(NMSPacket packet) {
super(packet);
}
@Override
protected void load() {
v_1_17 = version.isNewerThanOrEquals(ServerVersion.v_1_17);
between_V_1_17_And_1_20_1 = version.isNewerThanOrEquals(ServerVersion.v_1_17) && version.isOlderThan(ServerVersion.v_1_20_2);
}
public int getProtocolVersion() {
return readInt(v_1_17 ? 1 : 0);
return readInt(between_V_1_17_And_1_20_1 ? 1 : 0);
}
public void setProtocolVersion(int protocolVersion) {
writeInt(v_1_17 ? 1 : 0, protocolVersion);
writeInt(between_V_1_17_And_1_20_1 ? 1 : 0, protocolVersion);
}
public int getPort() {
return readInt(v_1_17 ? 2 : 1);
return readInt(between_V_1_17_And_1_20_1 ? 2 : 1);
}
public void setPort(int port) {
writeInt(v_1_17 ? 2 : 1, port);
writeInt(between_V_1_17_And_1_20_1 ? 2 : 1, port);
}
public String getHostName() {
@@ -21,12 +21,38 @@ package io.github.retrooper.packetevents.packetwrappers.login.in.encryptionbegin
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.ConditionalValue;
import io.github.retrooper.packetevents.utils.MojangEitherUtil;
import io.github.retrooper.packetevents.utils.SaltSignature;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
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 java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class WrappedPacketLoginInEncryptionBegin extends WrappedPacket {
private static Class<?> VANILLA_SALT_SIGNATURE_CLASS;
private static Constructor<?> VANILLA_SALT_SIGNATURE_CONSTRUCTOR;
public WrappedPacketLoginInEncryptionBegin(NMSPacket packet) {
super(packet);
}
@Override
protected void load() {
Class<?> minecraftEncryptionClass = Reflection.getClassByNameWithoutException("net.minecraft.util.MinecraftEncryption");
if (minecraftEncryptionClass != null) {
VANILLA_SALT_SIGNATURE_CLASS = SubclassUtil.getSubClass(minecraftEncryptionClass, "b");
try {
VANILLA_SALT_SIGNATURE_CONSTRUCTOR = VANILLA_SALT_SIGNATURE_CLASS.getConstructor(long.class, byte[].class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
public byte[] getPublicKey() {
return readByteArray(0);
}
@@ -35,12 +61,46 @@ public class WrappedPacketLoginInEncryptionBegin extends WrappedPacket {
writeByteArray(0, key);
}
public byte[] getVerifyToken() {
return readByteArray(1);
public ConditionalValue<byte[], SaltSignature> getVerifyTokenOrSaltSignature() {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19)) {
ConditionalValue<byte[], Object> rawEither = readEither(0);
if (rawEither.left().isPresent()) {
return ConditionalValue.makeLeft(rawEither.left().get());
}
else {
Object rawRight = rawEither.right().get();
WrappedPacket rawRightWrapper = new WrappedPacket(new NMSPacket(rawRight));
SaltSignature ss = new SaltSignature(rawRightWrapper.readLong(0), rawRightWrapper.readByteArray(0));
return ConditionalValue.makeRight(ss);
}
}
else {
return ConditionalValue.makeLeft(readByteArray(1));
}
}
public void setVerifyToken(byte[] token) {
writeByteArray(1, token);
public void setVerifyTokenOrSaltSignature(ConditionalValue<byte[], SaltSignature> value) {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19)) {
Object either;
if (value.left().isPresent()) {
either = MojangEitherUtil.makeLeft(value.left().get());
}
else {
SaltSignature ss = value.right().get();
Object rawSS = null;
try {
rawSS = VANILLA_SALT_SIGNATURE_CONSTRUCTOR.newInstance(ss.getSalt(), ss.getSignature());
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
either = MojangEitherUtil.makeRight(rawSS);
}
write(NMSUtils.mojangEitherClass, 0, either);
}
else {
writeByteArray(1, value.left().get());
}
}
@Override
@@ -24,21 +24,71 @@ import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.gameprofile.GameProfileUtil;
import io.github.retrooper.packetevents.utils.gameprofile.WrappedGameProfile;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
import java.util.UUID;
// TODO: This wrapper needs Signature data @retrooper
public class WrappedPacketLoginInStart extends WrappedPacket {
public WrappedPacketLoginInStart(NMSPacket packet) {
super(packet);
}
//TODO Allow accessing game profile property
public WrappedGameProfile getGameProfile() {
return GameProfileUtil.getWrappedGameProfile(readObject(0, NMSUtils.gameProfileClass));
public Optional<WrappedGameProfile> getGameProfile() {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19)) {
return Optional.empty();
}
return Optional.of(GameProfileUtil.getWrappedGameProfile(readObject(0, NMSUtils.gameProfileClass)));
}
//TODO Add support for game profile property
public void setGameProfile(WrappedGameProfile wrappedGameProfile) {
Object gameProfile = GameProfileUtil.getGameProfile(wrappedGameProfile.getId(), wrappedGameProfile.getName());
write(NMSUtils.gameProfileClass, 0, gameProfile);
if (version.isNewerThanOrEquals(ServerVersion.v_1_19)) {
writeString(0, wrappedGameProfile.getName());
}
else {
Object gameProfile = GameProfileUtil.getGameProfile(wrappedGameProfile.getId(), wrappedGameProfile.getName());
write(NMSUtils.gameProfileClass, 0, gameProfile);
}
}
public String getUsername() {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19)) {
return readString(0);
}
else {
return GameProfileUtil.getWrappedGameProfile(readObject(0, NMSUtils.gameProfileClass)).getName();
}
}
public void setUsername(String username) throws IllegalAccessException {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19)) {
writeString(0, username);
}
else {
throw new IllegalAccessException("Please use the setGameProfile method in the WrappedPacketLoginInStart wrapper to change the username!");
}
}
public @Nullable UUID getPlayerUUID() {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19_1)) {
return readObject(0, UUID.class);
}
else {
return GameProfileUtil.getWrappedGameProfile(readObject(0, NMSUtils.gameProfileClass)).getId();
}
}
public void setPlayerUUID(UUID playerUUID) throws IllegalAccessException {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19_1)) {
writeObject(0, playerUUID);
}
else {
throw new IllegalAccessException("Please use the setGameProfile method in the WrappedPacketLoginInStart wrapper to change the uuid!");
}
}
@Override
@@ -28,28 +28,14 @@ import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import java.lang.reflect.Constructor;
public class WrappedPacketLoginOutSuccess extends WrappedPacket implements SendableWrapper {
private static Constructor<?> packetConstructor;
public class WrappedPacketLoginOutSuccess extends WrappedPacket {
private WrappedGameProfile wrappedGameProfile;
public WrappedPacketLoginOutSuccess(final NMSPacket packet) {
super(packet);
}
public WrappedPacketLoginOutSuccess(final WrappedGameProfile wrappedGameProfile) {
this.wrappedGameProfile = wrappedGameProfile;
}
@Override
protected void load() {
try {
packetConstructor = PacketTypeClasses.Login.Server.SUCCESS.getConstructors()[1];
} catch (final Exception e) {
e.printStackTrace();
}
}
//TODO Support property reading in wrapped game profile
//TODO Support property reading in wrapped game profile(NECESSARY IN 1.19!, PLEASE UPDATE TO 2.0 PACKETEVENTS)
public WrappedGameProfile getGameProfile() {
if (packet != null) {
return GameProfileUtil.getWrappedGameProfile(readObject(0, NMSUtils.gameProfileClass));
@@ -58,7 +44,7 @@ public class WrappedPacketLoginOutSuccess extends WrappedPacket implements Senda
}
}
//TODO Support writing property in wrapped game profile
//TODO Support writing property in wrapped game profile(NECESSARY IN 1.19!, PLEASE UPDATE TO 2.0 PACKETEVENTS)
public void setGameProfile(final WrappedGameProfile wrappedGameProfile) {
if (packet != null) {
final Object gameProfile = GameProfileUtil.getGameProfile(wrappedGameProfile.getId(), wrappedGameProfile.getName());
@@ -68,13 +54,6 @@ public class WrappedPacketLoginOutSuccess extends WrappedPacket implements Senda
}
}
@Override
public Object asNMSPacket() throws Exception {
WrappedGameProfile gp = getGameProfile();
//TODO Support writing property in wrapped game profile
return packetConstructor.newInstance(GameProfileUtil.getGameProfile(gp.getId(), gp.getName()));
}
@Override
public boolean isSupported() {
return PacketTypeClasses.Login.Server.SUCCESS != null;
@@ -47,6 +47,9 @@ public final class WrappedPacketInBlockDig extends WrappedPacket {
} catch (ClassNotFoundException e) {
//It is probably a subclass
digTypeClass = SubclassUtil.getEnumSubClass(blockDigClass, "EnumPlayerDigType");
if (digTypeClass == null) {
digTypeClass = SubclassUtil.getEnumSubClass(blockDigClass, 0);
}
}
}
}
@@ -20,12 +20,38 @@ package io.github.retrooper.packetevents.packetwrappers.play.in.chat;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.SaltSignature;
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 java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.time.Instant;
import java.util.Optional;
public final class WrappedPacketInChat extends WrappedPacket {
private static Class<?> VANILLA_SALT_SIGNATURE_CLASS;
private static Constructor<?> VANILLA_SALT_SIGNATURE_CONSTRUCTOR;
public WrappedPacketInChat(NMSPacket packet) {
super(packet);
}
@Override
protected void load() {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19)) {
Class<?> minecraftEncryptionClass = Reflection.getClassByNameWithoutException("net.minecraft.util.MinecraftEncryption");
if (minecraftEncryptionClass != null) {
VANILLA_SALT_SIGNATURE_CLASS = SubclassUtil.getSubClass(minecraftEncryptionClass, "b");
try {
VANILLA_SALT_SIGNATURE_CONSTRUCTOR = VANILLA_SALT_SIGNATURE_CLASS.getConstructor(long.class, byte[].class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
}
public String getMessage() {
return readString(0);
}
@@ -33,4 +59,53 @@ public final class WrappedPacketInChat extends WrappedPacket {
public void setMessage(String message) {
writeString(0, message);
}
public Optional<Instant> getInstant() {
return version.isNewerThanOrEquals(ServerVersion.v_1_19) ? Optional.of(readObject(0, Instant.class)) : Optional.empty();
}
public void setInstant(Instant instant) {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19)) {
writeObject(0, instant);
}
}
public Optional<SaltSignature> getSaltSignature() {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19)) {
Object rawSS = readObject(0, VANILLA_SALT_SIGNATURE_CLASS);
WrappedPacket rawSSWrapper = new WrappedPacket(new NMSPacket(rawSS));
SaltSignature ss = new SaltSignature(rawSSWrapper.readLong(0), rawSSWrapper.readByteArray(0));
return Optional.of(ss);
}
else {
return Optional.empty();
}
}
public void setSaltSignature(SaltSignature saltSignature) {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19)) {
Object rawSS = null;
try {
rawSS = VANILLA_SALT_SIGNATURE_CONSTRUCTOR.newInstance(saltSignature.getSalt(), saltSignature.getSignature());
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
write(VANILLA_SALT_SIGNATURE_CLASS, 0, rawSS);
}
}
public boolean isSignedPreview() {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19)) {
return readBoolean(0);
}
else {
return false;
}
}
public void setSignedPreview(boolean signedPreview) {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19)) {
writeBoolean(0, signedPreview);
}
}
}
@@ -41,6 +41,9 @@ public final class WrappedPacketInClientCommand extends WrappedPacket {
if (enumClientCommandClass == null) {
//Probably a subclass
enumClientCommandClass = SubclassUtil.getEnumSubClass(PacketTypeClasses.Play.Client.CLIENT_COMMAND, "EnumClientCommand");
if (enumClientCommandClass == null) {
enumClientCommandClass = SubclassUtil.getEnumSubClass(PacketTypeClasses.Play.Client.CLIENT_COMMAND, 0);
}
}
}
@@ -22,13 +22,21 @@ import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.netty.bytebuf.ByteBufUtil;
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 org.bukkit.entity.Player;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public final class WrappedPacketInCustomPayload extends WrappedPacket {
private static boolean strPresent, byteArrayPresent;
private static boolean strPresent, byteArrayPresent, customPacketPayloadPresent;
private static Class<?> CUSTOM_PACKET_PAYLOAD, BRAND_PAYLOAD, DISCARDED_PAYLOAD;
private static Method CUSTOM_PACKET_PAYLOAD_MINECRAFT_KEY, CUSTOM_PACKET_PAYLOAD_PACKETDATASERIALIZER;
private static byte isVersion_1_17 = -1;
private static boolean isVersion_1_20_5;
private static boolean isVersion_1_20_6;
public WrappedPacketInCustomPayload(NMSPacket packet) {
super(packet);
@@ -38,10 +46,61 @@ public final class WrappedPacketInCustomPayload extends WrappedPacket {
protected void load() {
strPresent = Reflection.getField(PacketTypeClasses.Play.Client.CUSTOM_PAYLOAD, String.class, 0) != null;
byteArrayPresent = Reflection.getField(PacketTypeClasses.Play.Client.CUSTOM_PAYLOAD, byte[].class, 0) != null;
CUSTOM_PACKET_PAYLOAD = Reflection.getClassByNameWithoutException("net.minecraft.network.protocol.common.custom.CustomPacketPayload");
customPacketPayloadPresent = Reflection.getField(PacketTypeClasses.Play.Client.CUSTOM_PAYLOAD, CUSTOM_PACKET_PAYLOAD, 0) != null;
if (customPacketPayloadPresent) {
CUSTOM_PACKET_PAYLOAD_MINECRAFT_KEY = Reflection.getMethod(CUSTOM_PACKET_PAYLOAD, NMSUtils.minecraftKeyClass, 0);
CUSTOM_PACKET_PAYLOAD_PACKETDATASERIALIZER = Reflection.getMethod(CUSTOM_PACKET_PAYLOAD, 0, NMSUtils.packetDataSerializerClass);
}
isVersion_1_20_5 = version.isNewerThanOrEquals(ServerVersion.v_1_20_5);
isVersion_1_20_6 = version.isNewerThanOrEquals(ServerVersion.v_1_20_6);
if (isVersion_1_20_5) {
BRAND_PAYLOAD = NMSUtils.getNMClassWithoutException("network.protocol.common.custom.BrandPayload");
DISCARDED_PAYLOAD = NMSUtils.getNMClassWithoutException("network.protocol.common.custom.DiscardedPayload");
}
}
private Object getModernPayloadObject() {
return readObject(0, CUSTOM_PACKET_PAYLOAD);
}
public String getChannelName() {
if (strPresent) {
if (customPacketPayloadPresent) {
Object payload = getModernPayloadObject();
if (isVersion_1_20_5) {
if (BRAND_PAYLOAD.isInstance(payload)) {
WrappedPacket reflectBrandPayload = new WrappedPacket(new NMSPacket(payload));
return reflectBrandPayload.readString(0);
}
else if (DISCARDED_PAYLOAD.isInstance(payload)) {
WrappedPacket reflectBrandPayload = new WrappedPacket(new NMSPacket(payload));
if (isVersion_1_20_6) {
return reflectBrandPayload.readMinecraftKey(0);
}
else {
return reflectBrandPayload.readString(0);
}
}
else {
return null;
}
}
else {
try {
if (isVersion_1_17 == -1) {
isVersion_1_17 = (byte) (version.isNewerThanOrEquals(ServerVersion.v_1_17) ? 1 : 0);
}
int namespaceIndex = isVersion_1_17 == 1 ? 2 : 0;
int keyIndex = isVersion_1_17 == 1 ? 3 : 1;
Object minecraftKey = CUSTOM_PACKET_PAYLOAD_MINECRAFT_KEY.invoke(payload);
WrappedPacket minecraftKeyWrapper = new WrappedPacket(new NMSPacket(minecraftKey));
return minecraftKeyWrapper.readString(namespaceIndex) + ":" + minecraftKeyWrapper.readString(keyIndex);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
return null;
} else if (strPresent) {
return readString(0);
} else {
return readMinecraftKey(1);
@@ -49,7 +108,10 @@ public final class WrappedPacketInCustomPayload extends WrappedPacket {
}
public void setChannelName(String channelName) {
if (strPresent) {
if (customPacketPayloadPresent) {
throw new UnsupportedOperationException("PacketEvents v1.8 is a dying version, setting the channel name is not supported!");
}
else if (strPresent) {
writeString(0, channelName);
} else {
writeMinecraftKey(1, channelName);
@@ -57,7 +119,32 @@ public final class WrappedPacketInCustomPayload extends WrappedPacket {
}
public byte[] getData() {
if (byteArrayPresent) {
if (customPacketPayloadPresent) {
Object payload = getModernPayloadObject();
if (isVersion_1_20_6) {
if (DISCARDED_PAYLOAD.isInstance(payload)) {
WrappedPacket reflectDiscardedPayload = new WrappedPacket(new NMSPacket(payload));
Object buffer = reflectDiscardedPayload.readObject(0, NMSUtils.byteBufClass);
return PacketEvents.get().getByteBufUtil().getBytes(buffer);
}
else {
return null;
}
}
else {
Object buffer = PacketEvents.get().getByteBufUtil().buffer();
Object packetDataSerializer = NMSUtils.generatePacketDataSerializer(buffer);
try {
CUSTOM_PACKET_PAYLOAD_PACKETDATASERIALIZER.invoke(payload, packetDataSerializer);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
byte[] data = PacketEvents.get().getByteBufUtil().getBytes(buffer);
PacketEvents.get().getByteBufUtil().release(buffer);
return data;
}
}
else if (byteArrayPresent) {
return readByteArray(0);
} else {
return PacketEvents.get().getByteBufUtil().getBytes(getBuffer());
@@ -43,6 +43,9 @@ public final class WrappedPacketInEntityAction extends WrappedPacketEntityAbstra
if (enumPlayerActionClass == null) {
enumPlayerActionClass = SubclassUtil.getEnumSubClass(PacketTypeClasses.Play.Client.ENTITY_ACTION, "EnumPlayerAction");
}
if (version.isNewerThanOrEquals(ServerVersion.v_1_20_6)) {
enumPlayerActionClass = SubclassUtil.getEnumSubClass(PacketTypeClasses.Play.Client.ENTITY_ACTION, 0);
}
}
@@ -23,6 +23,7 @@ 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.server.ServerVersion;
import io.github.retrooper.packetevents.utils.vector.Vector3i;
public class WrappedPacketInUpdateSign extends WrappedPacket {
@@ -78,4 +79,19 @@ public class WrappedPacketInUpdateSign extends WrappedPacket {
writeAnyObject(1, iChatComponents);
}
}
public boolean isFrontText() {
if (version.isNewerThanOrEquals(ServerVersion.v_1_20)) {
return readBoolean(0);
}
else {
return true;
}
}
public void setFrontText(boolean frontText) {
if (version.isNewerThanOrEquals(ServerVersion.v_1_20)) {
writeBoolean(0,frontText);
}
}
}
@@ -38,7 +38,7 @@ public final class WrappedPacketInUseEntity extends WrappedPacketEntityAbstracti
private static Class<? extends Enum<?>> enumEntityUseActionClass;
private static Class<?> obfuscatedDataInterface, obfuscatedHandContainerClass, obfuscatedTargetAndHandContainerClass;
private static Method getObfuscatedEntityUseActionMethod;
private static boolean v_1_7_10, v_1_9, v_1_17;
private static boolean v_1_7_10, v_1_9, v_1_17, v_1_20_5;
private EntityUseAction action;
private Object obfuscatedDataObj;
@@ -51,15 +51,27 @@ public final class WrappedPacketInUseEntity extends WrappedPacketEntityAbstracti
v_1_7_10 = version.isOlderThan(ServerVersion.v_1_8);
v_1_9 = version.isNewerThanOrEquals(ServerVersion.v_1_9);
v_1_17 = version.isNewerThanOrEquals(ServerVersion.v_1_17);
v_1_20_5 = version.isNewerThanOrEquals(ServerVersion.v_1_20_5);
try {
enumEntityUseActionClass = NMSUtils.getNMSEnumClass("EnumEntityUseAction");
} catch (ClassNotFoundException e) {
//That is fine, it is probably a subclass
if (v_1_17) {
enumEntityUseActionClass = SubclassUtil.getEnumSubClass(PacketTypeClasses.Play.Client.USE_ENTITY, "b");
if (v_1_20_5) {
if (enumEntityUseActionClass == null) {
enumEntityUseActionClass = SubclassUtil.getEnumSubClass(PacketTypeClasses.Play.Client.USE_ENTITY, 3);
}
}
obfuscatedDataInterface = SubclassUtil.getSubClass(PacketTypeClasses.Play.Client.USE_ENTITY, "EnumEntityUseAction");
if (v_1_20_5) {
obfuscatedDataInterface = SubclassUtil.getEnumSubClass(PacketTypeClasses.Play.Client.USE_ENTITY, 0);
}
obfuscatedHandContainerClass = SubclassUtil.getSubClass(PacketTypeClasses.Play.Client.USE_ENTITY, "d");
obfuscatedTargetAndHandContainerClass = SubclassUtil.getSubClass(PacketTypeClasses.Play.Client.USE_ENTITY, "e");
if (obfuscatedTargetAndHandContainerClass == null) {
obfuscatedTargetAndHandContainerClass = SubclassUtil.getEnumSubClass(PacketTypeClasses.Play.Client.USE_ENTITY, 2);
}
getObfuscatedEntityUseActionMethod = Reflection.getMethod(obfuscatedDataInterface, enumEntityUseActionClass, 0);
} else {
enumEntityUseActionClass = SubclassUtil.getEnumSubClass(PacketTypeClasses.Play.Client.USE_ENTITY, "EnumEntityUseAction");
@@ -71,7 +71,15 @@ public class WrappedPacketOutBlockChange extends WrappedPacket implements Sendab
@Override
protected void load() {
getNMSBlockMethodCache = Reflection.getMethod(NMSUtils.iBlockDataClass, "getBlock", 0);
if (getNMSBlockMethodCache == null) {
Class<?> blockDataClass = NMSUtils.iBlockDataClass.getSuperclass();
getNMSBlockMethodCache = Reflection.getMethod(blockDataClass, NMSUtils.blockClass, 0);
}
getNMSWorldTypeMethodCache = Reflection.getMethod(NMSUtils.nmsWorldClass, "getType", 0);
if (getNMSWorldTypeMethodCache == null) {
getNMSWorldTypeMethodCache = Reflection.getMethod(NMSUtils.nmsWorldClass,
"getBlockStateIfLoaded", 0);
}
v_1_7_10 = version.isOlderThan(ServerVersion.v_1_8);
v_1_17 = version.isNewerThanOrEquals(ServerVersion.v_1_17);
if (v_1_17) {
@@ -25,16 +25,21 @@ import io.github.retrooper.packetevents.packetwrappers.api.SendableWrapper;
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.reflection.SubclassUtil;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.chat.ComponentSerializer;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.UUID;
import java.util.*;
public final class WrappedPacketOutChat extends WrappedPacket implements SendableWrapper {
private static Constructor<?> chatClassConstructor;
private static Class<? extends Enum<?>> chatMessageTypeEnum;
private static Class<?> PLAYER_CHAT_MESSAGE_CLASS, SIGNED_MESSAGE_BODY_CLASS,
CHAT_MESSAGE_CONTENT_CLASS, CHAT_MESSAGE_TYPE_CLASS, NETWORK_BOUND_CHAT_TYPE_CLASS;
//0 = IChatBaseComponent, Byte
//1 = IChatBaseComponent, Int
//2 = IChatBaseComponent, ChatMessageType
@@ -69,50 +74,66 @@ public final class WrappedPacketOutChat extends WrappedPacket implements Sendabl
@Override
protected void load() {
Class<?> packetClass = PacketTypeClasses.Play.Server.CHAT;
chatMessageTypeEnum = NMSUtils.getNMSEnumClassWithoutException("ChatMessageType");
if (chatMessageTypeEnum == null) {
chatMessageTypeEnum = NMSUtils.getNMEnumClassWithoutException("network.chat.ChatMessageType");
}
if (chatMessageTypeEnum != null) {
try {
chatClassConstructor = packetClass.getConstructor(NMSUtils.iChatBaseComponentClass, chatMessageTypeEnum);
constructorMode = 2;
} catch (NoSuchMethodException e) {
//Just a much newer version(1.16.x and above right now)
try {
chatClassConstructor = packetClass.getConstructor(NMSUtils.iChatBaseComponentClass, chatMessageTypeEnum, UUID.class);
constructorMode = 3;
} catch (NoSuchMethodException e2) {
//Failed to resolve the constructor
e2.printStackTrace();
}
if (version.isNewerThanOrEquals(ServerVersion.v_1_19)) {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19_1)) {
PLAYER_CHAT_MESSAGE_CLASS = NMSUtils.getNMClassWithoutException("network.chat.PlayerChatMessage");
SIGNED_MESSAGE_BODY_CLASS = NMSUtils.getNMClassWithoutException("network.chat.SignedMessageBody");
CHAT_MESSAGE_CONTENT_CLASS = NMSUtils.getNMClassWithoutException("network.chat.ChatMessageContent");
CHAT_MESSAGE_TYPE_CLASS = NMSUtils.getNMClassWithoutException("network.chat.ChatMessageType");
NETWORK_BOUND_CHAT_TYPE_CLASS = SubclassUtil.getSubClass(CHAT_MESSAGE_TYPE_CLASS, 1);
}
} else {
try {
chatClassConstructor = packetClass.getConstructor(NMSUtils.iChatBaseComponentClass, byte.class);
constructorMode = 0;
} catch (NoSuchMethodException e) {
//That is fine, they are most likely on an older version.
//Cause we read getChatPosition using constructor mode
constructorMode = 4;
}
else {
chatMessageTypeEnum = NMSUtils.getNMSEnumClassWithoutException("ChatMessageType");
if (chatMessageTypeEnum == null) {
chatMessageTypeEnum = NMSUtils.getNMEnumClassWithoutException("network.chat.ChatMessageType");
}
if (chatMessageTypeEnum != null) {
try {
chatClassConstructor = packetClass.getConstructor(NMSUtils.iChatBaseComponentClass, int.class);
constructorMode = 1;
} catch (NoSuchMethodException e2) {
chatClassConstructor = packetClass.getConstructor(NMSUtils.iChatBaseComponentClass, chatMessageTypeEnum);
constructorMode = 2;
} catch (NoSuchMethodException e) {
//Just a much newer version(1.16.x and above right now)
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(NMSUtils.iChatBaseComponentClass);
constructorMode = -1;
} catch (NoSuchMethodException e3) {
e3.printStackTrace();
chatClassConstructor = packetClass.getConstructor(NMSUtils.iChatBaseComponentClass, chatMessageTypeEnum, UUID.class);
constructorMode = 3;
} catch (NoSuchMethodException e2) {
//Failed to resolve the constructor
e2.printStackTrace();
}
}
} else {
try {
chatClassConstructor = packetClass.getConstructor(NMSUtils.iChatBaseComponentClass, byte.class);
constructorMode = 0;
} catch (NoSuchMethodException e) {
//That is fine, they are most likely on an older version.
try {
chatClassConstructor = packetClass.getConstructor(NMSUtils.iChatBaseComponentClass, int.class);
constructorMode = 1;
} catch (NoSuchMethodException e2) {
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(NMSUtils.iChatBaseComponentClass);
constructorMode = -1;
} catch (NoSuchMethodException e3) {
e3.printStackTrace();
}
}
}
}
}
}
@Override
public Object asNMSPacket() throws Exception {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19)) {
throw new IllegalStateException("You are trying to send the WrappedPacketOutChat packet on 1.19 or above. Please update to packetevents 2.0, this is not supported.");
}
byte chatPos = (byte) getChatPosition().ordinal();
Enum<?> chatMessageTypeInstance = null;
if (chatMessageTypeEnum != null) {
@@ -141,6 +162,15 @@ public final class WrappedPacketOutChat extends WrappedPacket implements Sendabl
*/
public String getMessage() {
if (packet != null) {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19_1)) {
Object playerChatMessage = readObject(0, PLAYER_CHAT_MESSAGE_CLASS);
WrappedPacket playerChatMessageWrapper = new WrappedPacket(new NMSPacket(playerChatMessage));
Object signedMessageBody = playerChatMessageWrapper.readObject(0, SIGNED_MESSAGE_BODY_CLASS);
WrappedPacket wrappedSignedMessageBody = new WrappedPacket(new NMSPacket(signedMessageBody));
Object chatMessageContent = wrappedSignedMessageBody.readObject(0, CHAT_MESSAGE_CONTENT_CLASS);
WrappedPacket wrappedChatMessage = new WrappedPacket(new NMSPacket(chatMessageContent));
return wrappedChatMessage.readIChatBaseComponent(0);
}
return readIChatBaseComponent(0);
} else {
return message;
@@ -149,12 +179,55 @@ public final class WrappedPacketOutChat extends WrappedPacket implements Sendabl
public void setMessage(String message) {
if (packet != null) {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19_1)) {
Object playerChatMessage = readObject(0, PLAYER_CHAT_MESSAGE_CLASS);
WrappedPacket playerChatMessageWrapper = new WrappedPacket(new NMSPacket(playerChatMessage));
Object signedMessageBody = playerChatMessageWrapper.readObject(0, SIGNED_MESSAGE_BODY_CLASS);
WrappedPacket wrappedSignedMessageBody = new WrappedPacket(new NMSPacket(signedMessageBody));
Object chatMessageContent = wrappedSignedMessageBody.readObject(0, CHAT_MESSAGE_CONTENT_CLASS);
WrappedPacket wrappedChatMessage = new WrappedPacket(new NMSPacket(chatMessageContent));
wrappedChatMessage.writeIChatBaseComponent(0, message);
return;
}
writeIChatBaseComponent(0, message);
} else {
this.message = message;
}
}
public Optional<String> getUnsignedMessage() {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19_1)) {
Object playerChatMessage = readObject(0, PLAYER_CHAT_MESSAGE_CLASS);
WrappedPacket playerChatMessageWrapper = new WrappedPacket(new NMSPacket(playerChatMessage));
Optional<?> opt = playerChatMessageWrapper.readObject(0, Optional.class);
if (opt.isPresent()) {
Object iChatBaseComponent = opt.get();
return Optional.ofNullable(NMSUtils.readIChatBaseComponent(iChatBaseComponent));
}
}
else if (version.isNewerThanOrEquals(ServerVersion.v_1_19)) {
Optional<?> opt = readObject(0, Optional.class);
if (opt.isPresent()) {
Object iChatBaseComponent = opt.get();
return Optional.ofNullable(NMSUtils.readIChatBaseComponent(iChatBaseComponent));
}
}
return Optional.empty();
}
public void setUnsignedMessage(String unsignedMessage) {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19_1)) {
Object playerChatMessage = readObject(0, PLAYER_CHAT_MESSAGE_CLASS);
WrappedPacket playerChatMessageWrapper = new WrappedPacket(new NMSPacket(playerChatMessage));
Object iChatBaseComponent = NMSUtils.generateIChatBaseComponent(unsignedMessage);
playerChatMessageWrapper.write(Optional.class, 0, Optional.ofNullable(iChatBaseComponent));
}
else if (version.isNewerThanOrEquals(ServerVersion.v_1_19)) {
Object iChatBaseComponent = NMSUtils.generateIChatBaseComponent(unsignedMessage);
write(Optional.class, 0, Optional.ofNullable(iChatBaseComponent));
}
}
/**
* Get the chat position.
* <p>
@@ -168,7 +241,7 @@ public final class WrappedPacketOutChat extends WrappedPacket implements Sendabl
byte chatPositionValue;
switch (constructorMode) {
case -1:
chatPositionValue = (byte) ChatPosition.CHAT.ordinal();
chatPositionValue = (byte) ChatPosition.CHAT.getId(version);
break;
case 0:
chatPositionValue = readByte(0);
@@ -180,11 +253,16 @@ public final class WrappedPacketOutChat extends WrappedPacket implements Sendabl
case 3:
Enum<?> chatTypeEnumInstance = readEnumConstant(0, chatMessageTypeEnum);
return ChatPosition.values()[chatTypeEnumInstance.ordinal()];
case 4:
Object chatMsgType = readObject(0, NETWORK_BOUND_CHAT_TYPE_CLASS);
WrappedPacket chatMsgTypeWrapper = new WrappedPacket(new NMSPacket(chatMsgType));
chatPositionValue = (byte) chatMsgTypeWrapper.readInt(0);
break;
default:
chatPositionValue = 0;
break;
}
return ChatPosition.values()[chatPositionValue];
return ChatPosition.getById(version, chatPositionValue);
} else {
return chatPosition;
}
@@ -194,25 +272,87 @@ public final class WrappedPacketOutChat extends WrappedPacket implements Sendabl
if (packet != null) {
switch (constructorMode) {
case 0:
writeByte(0, (byte) chatPosition.ordinal());
writeByte(0, (byte) chatPosition.getId(version));
break;
case 1:
writeInt(0, chatPosition.ordinal());
writeInt(0, chatPosition.getId(version));
break;
case 2:
case 3:
Enum<?> chatTypeEnumInstance = EnumUtil.valueByIndex(chatMessageTypeEnum, chatPosition.ordinal());
Enum<?> chatTypeEnumInstance = EnumUtil.valueByIndex(chatMessageTypeEnum,
chatPosition.getId(version));
writeEnumConstant(0, chatTypeEnumInstance);
break;
case 4:
Object chatMsgType = readObject(0, NETWORK_BOUND_CHAT_TYPE_CLASS);
WrappedPacket chatMsgTypeWrapper = new WrappedPacket(new NMSPacket(chatMsgType));
chatMsgTypeWrapper.writeInt(0, chatPosition.getId(version));
break;
}
} else {
this.chatPosition = chatPosition;
}
}
// TODO: Add support to every single Wrapper usage
public enum ChatPosition {
CHAT,
SYSTEM_MESSAGE,
GAME_INFO;
CHAT(0),
@Deprecated
SYSTEM(-1),
@Deprecated
GAME_INFO(-1),
SAY_COMMAND(1),
@Deprecated
MSG_COMMAND(-1),
MSG_COMMAND_INCOMING(2),
MSG_COMMAND_OUTGOING(3),
@Deprecated
TEAM_MSG_COMMAND(-1),
TEAM_MSG_COMMAND_INCOMING(4),
TEAM_MSG_COMMAND_OUTGOING(5),
EMOTE_COMMAND(6),
@Deprecated
TELLRAW_COMMAND(-1);
private final byte modernId;
ChatPosition(int modernId) {
this.modernId = (byte) modernId;
}
private static final ChatPosition[] VALUES;
private static final Map<Byte, ChatPosition> MODERN_CHAT_TYPE_MAP;
static {
VALUES = values();
MODERN_CHAT_TYPE_MAP = new HashMap<>();
Arrays.stream(VALUES)
.filter(chatType -> chatType.modernId != -1)
.forEach(chatType -> MODERN_CHAT_TYPE_MAP.put(chatType.modernId, chatType));
}
public int getId(ServerVersion version) {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19_1)) {
return modernId;
}
return ordinal();
}
@Nullable
public static ChatPosition getById(ServerVersion version, int id) {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19_1)) {
return MODERN_CHAT_TYPE_MAP.get((byte) id);
} else {
return VALUES[id];
}
}
}
}
@@ -95,7 +95,9 @@ public class WrappedPacketOutEntity extends WrappedPacketEntityAbstraction imple
pitchByteIndex = 4;
} else if (dxField.equals(Reflection.getField(packetClass, int.class, 1))) {
mode = 1;
} else if (dxField.equals(Reflection.getField(packetClass, short.class, 0))) {
} else if (dxField.equals(Reflection.getField(packetClass, short.class, 0))
//1.19 support
|| dxField.equals(Reflection.getField(packetClass, short.class, 1))) {
mode = 2;
}
if (mode == 0) {
@@ -24,17 +24,23 @@ import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.api.SendableWrapper;
import io.github.retrooper.packetevents.packetwrappers.api.helper.WrappedPacketEntityAbstraction;
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 org.bukkit.Effect;
import org.bukkit.entity.Entity;
import org.bukkit.potion.PotionEffectType;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Optional;
public class WrappedPacketOutEntityEffect extends WrappedPacketEntityAbstraction implements SendableWrapper {
private static boolean v_1_7_10, v_1_17, v_1_18_2;
private static boolean v_1_7_10, v_1_17, v_1_18_2, v_1_19, v_1_20_5;
private static Constructor<?> packetConstructor;
private static Class<?> holderClass;
private static Method accessHolderValueMethod;
private static boolean hasHolder = false;
private int effectID;
private int amplifier;
private int duration;
@@ -105,12 +111,25 @@ public class WrappedPacketOutEntityEffect extends WrappedPacketEntityAbstraction
v_1_7_10 = version.isOlderThan(ServerVersion.v_1_8);
v_1_17 = version.isNewerThanOrEquals(ServerVersion.v_1_17);
v_1_18_2 = version.isNewerThanOrEquals(ServerVersion.v_1_18_2);
v_1_19 = version.isNewerThanOrEquals(ServerVersion.v_1_19);
v_1_20_5 = version.isNewerThanOrEquals(ServerVersion.v_1_20_5);
try {
if (v_1_17) {
packetConstructor = PacketTypeClasses.Play.Server.ENTITY_EFFECT.getConstructor(NMSUtils.packetDataSerializerClass);
/*packetConstructor = PacketTypeClasses.Play.Server.ENTITY_EFFECT.getDeclaredConstructor(NMSUtils.packetDataSerializerClass);
packetConstructor.setAccessible(true);
if (packetConstructor == null) {
Class<?> registryFriendlyByteBuf = NMSUtils.getNMClassWithoutException("network.RegistryFriendlyByteBuf");
packetConstructor = PacketTypeClasses.Play.Server.ENTITY_EFFECT.getDeclaredConstructor(registryFriendlyByteBuf);
}*/
} else {
packetConstructor = PacketTypeClasses.Play.Server.ENTITY_EFFECT.getConstructor();
}
holderClass = NMSUtils.getNMClassWithoutException("core.Holder");
if (holderClass != null) {
hasHolder = Reflection.getField(PacketTypeClasses.Play.Server.ENTITY_EFFECT, holderClass, 0) != null;
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
@@ -118,10 +137,26 @@ public class WrappedPacketOutEntityEffect extends WrappedPacketEntityAbstraction
public int getEffectId() {
if (packet != null) {
if (v_1_18_2) {
if (v_1_19) {
Object mobEffectList = null;
if (hasHolder) {
Object holder = readObject(0, holderClass);
if (accessHolderValueMethod == null) {
accessHolderValueMethod = Reflection.getMethod(holderClass, 0);
}
try {
mobEffectList = accessHolderValueMethod.invoke(holder);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
else {
mobEffectList = readObject(0, NMSUtils.mobEffectListClass);
}
return NMSUtils.getEffectId(mobEffectList);
} else if (v_1_18_2) {
return readInt(4);
}
else {
} else {
return readByte(0);
}
} else {
@@ -131,10 +166,12 @@ public class WrappedPacketOutEntityEffect extends WrappedPacketEntityAbstraction
public void setEffectId(int effectID) {
if (packet != null) {
if (v_1_18_2) {
if (v_1_19) {
Object mobEffectList = NMSUtils.getMobEffectListById(effectID);
write(NMSUtils.mobEffectListClass, 0, mobEffectList);
} else if (v_1_18_2) {
writeInt(4, effectID);
}
else {
} else {
writeByte(0, (byte) effectID);
}
} else {
@@ -144,6 +181,9 @@ public class WrappedPacketOutEntityEffect extends WrappedPacketEntityAbstraction
public int getAmplifier() {
if (packet != null) {
if (v_1_20_5) {
return readInt(5);
}
return readByte(v_1_18_2 ? 0 : 1);
} else {
return amplifier;
@@ -152,6 +192,9 @@ public class WrappedPacketOutEntityEffect extends WrappedPacketEntityAbstraction
public void setAmplifier(int amplifier) {
if (packet != null) {
if (v_1_20_5) {
writeInt(5, amplifier);
}
writeByte(v_1_18_2 ? 0 : 1, (byte) amplifier);
} else {
this.amplifier = amplifier;
@@ -160,10 +203,16 @@ public class WrappedPacketOutEntityEffect extends WrappedPacketEntityAbstraction
public int getDuration() {
if (packet != null) {
//1.7 and only 1.7
//1.7 and only 1.7(below 1.8)
if (v_1_7_10) {
return readShort(1);
}
else if (v_1_20_5) {
return readInt(6);
}
else if (v_1_19) {
return readInt(4);
}
//1.18.2+
else if (v_1_18_2) {
return readInt(5);
@@ -188,10 +237,14 @@ public class WrappedPacketOutEntityEffect extends WrappedPacketEntityAbstraction
}
writeShort(0, (short) duration);
}
else if (v_1_18_2) {
writeInt(5, duration);
else if (v_1_20_5) {
writeInt(6, duration);
}
else {
else if (v_1_19) {
writeInt(4, duration);
} else if (v_1_18_2) {
writeInt(5, duration);
} else {
writeInt(v_1_17 ? 4 : 1, duration);
}
} else {
@@ -204,6 +257,9 @@ public class WrappedPacketOutEntityEffect extends WrappedPacketEntityAbstraction
return Optional.empty();
}
if (packet != null && !byteMaskInitialized) {
if (v_1_20_5) {
return Optional.of(readByte(0));
}
return Optional.of(byteMask = readByte(v_1_18_2 ? 1 : 2));
} else {
return Optional.of(byteMask);
@@ -214,6 +270,9 @@ public class WrappedPacketOutEntityEffect extends WrappedPacketEntityAbstraction
if (!v_1_7_10) {
this.byteMask = byteMask;
if (packet != null) {
if (v_1_20_5) {
writeByte(0, byteMask);
}
writeByte(v_1_18_2 ? 1 : 2, byteMask);
}
}
@@ -37,7 +37,7 @@ public class WrappedPacketOutEntityMetadata extends WrappedPacketEntityAbstracti
public List<WrappedWatchableObject> getWatchableObjects() {
List<Object> nmsWatchableObjectList = readList(0);
//Its annotated as nullable on 1.17 NMS, so lets just handle it being null
//It's annotated as nullable on 1.17 NMS, so lets just handle it being null
if (nmsWatchableObjectList == null) {
return new ArrayList<>();
}
@@ -38,7 +38,15 @@ public class WrappedWatchableObject extends WrappedPacket {
@Override
protected void load() {
if (version.isNewerThan(ServerVersion.v_1_8_8)) {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19_3)) {
valueIndex = 2;
try {
googleOptionalClass = Class.forName("com.google.common.base.Optional");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
else if (version.isNewerThan(ServerVersion.v_1_8_8)) {
valueIndex = 1;
try {
googleOptionalClass = Class.forName("com.google.common.base.Optional");
@@ -49,17 +57,19 @@ public class WrappedWatchableObject extends WrappedPacket {
}
public int getIndex() {
if (version.isNewerThan(ServerVersion.v_1_8_8)) {
if (version.isNewerThan(ServerVersion.v_1_8_8) && version.isOlderThan(ServerVersion.v_1_19_3)) {
Object dataWatcherObject = readAnyObject(0);
WrappedPacket wrappedDataWatcher = new WrappedPacket(new NMSPacket(dataWatcherObject));
return wrappedDataWatcher.readInt(0);
} else {
//1.19.3 changed back to this
return readInt(0);
}
}
public void setIndex(int index) {
if (version.isNewerThan(ServerVersion.v_1_8_8)) {
if (version.isNewerThan(ServerVersion.v_1_8_8) && version.isOlderThan(ServerVersion.v_1_19_3)) {
Object dataWatcherObject = readAnyObject(0);
WrappedPacket wrappedDataWatcher = new WrappedPacket(new NMSPacket(dataWatcherObject));
wrappedDataWatcher.writeInt(0, index);
@@ -69,11 +79,13 @@ public class WrappedWatchableObject extends WrappedPacket {
}
public boolean isDirty() {
return readBoolean(0);
return !version.isOlderThan(ServerVersion.v_1_19_3) || readBoolean(0);
}
public void setDirty(boolean dirty) {
writeBoolean(0, dirty);
if (version.isOlderThan(ServerVersion.v_1_19_3)) {
writeBoolean(0, dirty);
}
}
public Object getRawValue() {
@@ -81,7 +81,7 @@ public class WrappedPacketOutExplosion extends WrappedPacket implements Sendable
chunkPosConstructor = chunkPosClass.getConstructor(int.class, int.class, int.class);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
//1.20.4 or newer
}
}
@@ -80,4 +80,27 @@ public class WrappedPacketOutLogin extends WrappedPacketEntityAbstraction {
return -1;
}
}
public int getPortalCooldown() {
if (packet != null) {
if (version.isNewerThanOrEquals(ServerVersion.v_1_20)) {
return readInt(4);
}
}
else {
//TODO unfinished
}
return 0;
}
public void setPortalCooldown(int portalCooldown) {
if (packet != null) {
if (version.isNewerThanOrEquals(ServerVersion.v_1_20)) {
writeInt(4, portalCooldown);
}
}
else {
//TODO unfinished
}
}
}
@@ -114,6 +114,7 @@ public class WrappedPacketOutPlayerInfo extends WrappedPacket implements Sendabl
}
}
//TODO Technically we would need to support profile signiture data for complete 1.19.1 support.
public PlayerInfo[] getPlayerInfo() {
if (packet != null) {
PlayerInfo[] playerInfoArray = new PlayerInfo[1];
@@ -126,6 +127,7 @@ public class WrappedPacketOutPlayerInfo extends WrappedPacket implements Sendabl
playerInfoArray[0] = new PlayerInfo(username, gameProfile, gameMode, ping);
} else {
List<Object> nmsPlayerInfoDataList = readList(0);
playerInfoArray = new PlayerInfo[nmsPlayerInfoDataList.size()];
for (int i = 0; i < nmsPlayerInfoDataList.size(); i++) {
Object nmsPlayerInfoData = nmsPlayerInfoDataList.get(i);
WrappedPacket nmsPlayerInfoDataWrapper = new WrappedPacket(new NMSPacket(nmsPlayerInfoData));
@@ -200,6 +202,14 @@ public class WrappedPacketOutPlayerInfo extends WrappedPacket implements Sendabl
return packetInstance;
}
@Override
public boolean isSupported() {
//1.19.3 removed this packet and replaced it with PlayerInfoRemove & PlayerInfoUpdate
//TODO Since this is a minimal update, we won't add those. v1.8 will eventually be discontinued
//so please consider updating to 2.0
return version.isOlderThanOrEquals(ServerVersion.v_1_19_2);
}
public enum PlayerInfoAction {
ADD_PLAYER,
UPDATE_GAME_MODE,
@@ -23,14 +23,20 @@ import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.api.SendableWrapper;
import io.github.retrooper.packetevents.packetwrappers.api.helper.WrappedPacketEntityAbstraction;
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 org.bukkit.entity.Entity;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class WrappedPacketOutRemoveEntityEffect extends WrappedPacketEntityAbstraction implements SendableWrapper {
private static boolean v_1_8_x, v_1_17;
private static Constructor<?> packetConstructor;
private static Class<?> holderClass;
private static Method accessHolderValueMethod;
private static boolean hasHolder = false;
private int effectID;
public WrappedPacketOutRemoveEntityEffect(NMSPacket packet) {
@@ -54,11 +60,17 @@ public class WrappedPacketOutRemoveEntityEffect extends WrappedPacketEntityAbstr
v_1_17 = version.isNewerThanOrEquals(ServerVersion.v_1_17);
try {
if (v_1_17) {
packetConstructor = PacketTypeClasses.Play.Server.REMOVE_ENTITY_EFFECT.getConstructor(int.class, NMSUtils.mobEffectListClass);
//packetConstructor = PacketTypeClasses.Play.Server.REMOVE_ENTITY_EFFECT.getConstructor(int.class, NMSUtils.mobEffectListClass);
}
else {
packetConstructor = PacketTypeClasses.Play.Server.REMOVE_ENTITY_EFFECT.getConstructor();
}
holderClass = NMSUtils.getNMClassWithoutException("core.Holder");
if (holderClass != null) {
hasHolder = Reflection.getField(PacketTypeClasses.Play.Server.ENTITY_EFFECT, holderClass, 0) != null;
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
@@ -72,8 +84,22 @@ public class WrappedPacketOutRemoveEntityEffect extends WrappedPacketEntityAbstr
}
//1.9+
else {
Object nmsMobEffectList = readObject(0, NMSUtils.mobEffectListClass);
return NMSUtils.getEffectId(nmsMobEffectList);
Object mobEffectList = null;
if (hasHolder) {
Object holder = readObject(0, holderClass);
if (accessHolderValueMethod == null) {
accessHolderValueMethod = Reflection.getMethod(holderClass, 0);
}
try {
mobEffectList = accessHolderValueMethod.invoke(holder);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
else {
mobEffectList = readObject(0, NMSUtils.mobEffectListClass);
}
return NMSUtils.getEffectId(mobEffectList);
}
}
else {
@@ -33,6 +33,7 @@ class WrappedPacketOutRespawn extends WrappedPacket {
private Difficulty difficulty;
private GameMode gameMode;
private WorldType levelType;
private int portalCooldown;
public WrappedPacketOutRespawn(NMSPacket packet) {
super(packet);
@@ -76,6 +77,24 @@ class WrappedPacketOutRespawn extends WrappedPacket {
}
}
public int getPortalCooldown() {
if (packet != null) {
return readInt(0);
}
else {
return portalCooldown;
}
}
public void setPortalCooldown(int portalCooldown) {
if (packet != null) {
writeInt(0, portalCooldown);
}
else {
this.portalCooldown = portalCooldown;
}
}
/*public WorldType getLevelType() {
if (packet != null) {
//TODO finish
@@ -155,7 +155,7 @@ public class WrappedPacketOutSetSlot extends WrappedPacket implements SendableWr
@Override
public Object asNMSPacket() throws Exception {
if (v_1_17_1) {
return packetConstructor.newInstance(getWindowId(), getStateId(), getSlot(), NMSUtils.toNMSItemStack(getItemStack()));
return packetConstructor.newInstance(getWindowId(), getStateId().get(), getSlot(), NMSUtils.toNMSItemStack(getItemStack()));
}
else {
return packetConstructor.newInstance(getWindowId(), getSlot(), NMSUtils.toNMSItemStack(getItemStack()));
@@ -0,0 +1,92 @@
package io.github.retrooper.packetevents.packetwrappers.play.out.systemchat;
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.api.SendableWrapper;
import io.github.retrooper.packetevents.packetwrappers.play.out.chat.WrappedPacketOutChat;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import java.lang.reflect.Constructor;
public class WrappedPacketOutSystemChat extends WrappedPacket implements SendableWrapper {
private static Constructor<?> packetConstructor;
private String message;
private WrappedPacketOutChat.ChatPosition position;
public WrappedPacketOutSystemChat(final NMSPacket packet) {
super(packet);
}
public WrappedPacketOutSystemChat(String messageJSON, WrappedPacketOutChat.ChatPosition position) {
this.message = messageJSON;
this.position = position;
}
@Override
protected void load() {
try {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19_1)) {
packetConstructor = PacketTypeClasses.Play.Server.SYSTEM_CHAT.getConstructor(String.class, boolean.class);
}
else {
packetConstructor = PacketTypeClasses.Play.Server.SYSTEM_CHAT.getConstructor(String.class, int.class);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
public String getMessageJSON() {
if (packet != null) {
return readString(0);
} else {
return message;
}
}
public void setMessageJSON(String message) {
if (packet != null) {
writeString(0, message);
} else {
this.message = message;
}
}
public WrappedPacketOutChat.ChatPosition getPosition() {
if (packet != null) {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19_1)) {
return readBoolean(1) ? WrappedPacketOutChat.ChatPosition.GAME_INFO : WrappedPacketOutChat.ChatPosition.SYSTEM;
}
return WrappedPacketOutChat.ChatPosition.getById(version, readInt(0));
}
else {
return position;
}
}
public void setPosition(WrappedPacketOutChat.ChatPosition position) {
if (packet != null) {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19_1)) {
writeBoolean(1, position == WrappedPacketOutChat.ChatPosition.GAME_INFO);
return;
}
writeInt(0, position.ordinal());
}
else {
this.position = position;
}
}
@Override
public Object asNMSPacket() throws Exception {
if (version.isNewerThanOrEquals(ServerVersion.v_1_19_1)) {
return packetConstructor.newInstance(getMessageJSON(), getPosition() == WrappedPacketOutChat.ChatPosition.GAME_INFO);
}
else {
return packetConstructor.newInstance(getMessageJSON(), getPosition().ordinal());
}
}
}
@@ -35,7 +35,6 @@ import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.event.world.WorldLoadEvent;
import org.spigotmc.AsyncCatcher;
import java.net.InetSocketAddress;
import java.util.UUID;
@@ -24,8 +24,7 @@ import io.github.retrooper.packetevents.packettype.PacketState;
import io.github.retrooper.packetevents.packettype.PacketType;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.handshaking.setprotocol.WrappedPacketHandshakingInSetProtocol;
import io.github.retrooper.packetevents.packetwrappers.login.in.start.WrappedPacketLoginInStart;
import io.github.retrooper.packetevents.utils.gameprofile.WrappedGameProfile;
import io.github.retrooper.packetevents.packetwrappers.login.out.success.WrappedPacketLoginOutSuccess;
import io.github.retrooper.packetevents.utils.player.ClientVersion;
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
import org.bukkit.entity.Player;
@@ -90,12 +89,7 @@ public class PacketProcessorInternal {
}
break;
case LOGIN:
PacketLoginReceiveEvent loginEvent = new PacketLoginReceiveEvent(channel, new NMSPacket(packet));//Cache the channel
if (loginEvent.getPacketId() == PacketType.Login.Client.START) {
WrappedPacketLoginInStart startWrapper = new WrappedPacketLoginInStart(loginEvent.getNMSPacket());
WrappedGameProfile gameProfile = startWrapper.getGameProfile();
PacketEvents.get().getPlayerUtils().channels.put(gameProfile.getName(), channel);
}
PacketLoginReceiveEvent loginEvent = new PacketLoginReceiveEvent(channel, new NMSPacket(packet));
PacketEvents.get().getEventManager().callEvent(loginEvent);
packet = loginEvent.getNMSPacket().getRawNMSPacket();
interceptLoginReceive(loginEvent);
@@ -103,6 +97,14 @@ public class PacketProcessorInternal {
packet = null;
}
break;
case CONFIG:
PacketConfigReceiveEvent configEvent = new PacketConfigReceiveEvent(channel, new NMSPacket(packet));
PacketEvents.get().getEventManager().callEvent(configEvent);
packet = configEvent.getNMSPacket().getRawNMSPacket();
if (configEvent.isCancelled()) {
packet = null;
}
break;
case PLAY:
PacketPlayReceiveEvent event = new PacketPlayReceiveEvent(player, channel, new NMSPacket(packet));
PacketEvents.get().getEventManager().callEvent(event);
@@ -148,6 +150,11 @@ public class PacketProcessorInternal {
break;
case LOGIN:
PacketLoginSendEvent loginEvent = new PacketLoginSendEvent(channel, new NMSPacket(packet));
if (loginEvent.getPacketId() == PacketType.Login.Server.SUCCESS) {
WrappedPacketLoginOutSuccess success = new WrappedPacketLoginOutSuccess(loginEvent.getNMSPacket());
String username = success.getGameProfile().getName();
PacketEvents.get().getPlayerUtils().channels.put(username, channel); //Cache channel
}
PacketEvents.get().getEventManager().callEvent(loginEvent);
if (loginEvent.isPostTaskAvailable()) {
data.postAction = loginEvent.getPostTask();
@@ -158,6 +165,17 @@ public class PacketProcessorInternal {
packet = null;
}
break;
case CONFIG:
PacketConfigSendEvent configEvent = new PacketConfigSendEvent(channel, new NMSPacket(packet));
PacketEvents.get().getEventManager().callEvent(configEvent);
if (configEvent.isPostTaskAvailable()) {
data.postAction = configEvent.getPostTask();
}
packet = configEvent.getNMSPacket().getRawNMSPacket();
if (configEvent.isCancelled()) {
packet = null;
}
break;
case PLAY:
PacketPlaySendEvent playEvent = new PacketPlaySendEvent(player, channel, new NMSPacket(packet));
PacketEvents.get().getEventManager().callEvent(playEvent);
@@ -324,7 +342,11 @@ public class PacketProcessorInternal {
return PacketState.LOGIN;
} else if (packetName.startsWith("PacketS")) {
return PacketState.STATUS;
} else {
}
else if (packet.getClass().getName().contains("protocol.common")) {
return PacketState.CONFIG;
}
else {
return null;
}
}
@@ -1,45 +0,0 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2021 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.github.retrooper.packetevents.updatechecker;
import net.minecraft.util.com.google.gson.JsonObject;
import net.minecraft.util.com.google.gson.JsonParser;
import java.io.IOException;
public class LowLevelUpdateCheckerLegacy implements LowLevelUpdateChecker {
@Override
public String getLatestRelease() {
String jsonResponse;
try {
jsonResponse = getLatestReleaseJson();
} catch (IOException e) {
e.printStackTrace();
throw new IllegalStateException("Failed to parse packetevents version!");
}
JsonParser parser = new JsonParser();
JsonObject jsonObject = parser.parse(jsonResponse).getAsJsonObject();
String versionName = null;
if (jsonObject != null) {
versionName = jsonObject.get("name").getAsString();
}
return versionName;
}
}
@@ -1,45 +0,0 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2021 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.github.retrooper.packetevents.updatechecker;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.io.IOException;
public class LowLevelUpdateCheckerModern implements LowLevelUpdateChecker {
@Override
public String getLatestRelease() {
String jsonResponse;
try {
jsonResponse = getLatestReleaseJson();
} catch (IOException e) {
e.printStackTrace();
throw new IllegalStateException("Failed to parse packetevents version!");
}
JsonParser parser = new JsonParser();
JsonObject jsonObject = parser.parse(jsonResponse).getAsJsonObject();
String versionName = null;
if (jsonObject != null) {
versionName = jsonObject.get("name").getAsString();
}
return versionName;
}
}
@@ -19,7 +19,6 @@
package io.github.retrooper.packetevents.updatechecker;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import io.github.retrooper.packetevents.utils.version.PEVersion;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
@@ -31,14 +30,10 @@ import org.bukkit.ChatColor;
* @since 1.6.9
*/
public class UpdateChecker {
private final LowLevelUpdateChecker lowLevelUpdateChecker;
private final UpdaterCheck lowLevelUpdateChecker;
public UpdateChecker() {
if (PacketEvents.get().getServerUtils().getVersion().isOlderThan(ServerVersion.v_1_8)) {
lowLevelUpdateChecker = new LowLevelUpdateCheckerLegacy();
} else {
lowLevelUpdateChecker = new LowLevelUpdateCheckerModern();
}
lowLevelUpdateChecker = new UpdaterCheck();
}
public String checkLatestReleasedVersion() {
@@ -50,23 +45,26 @@ public class UpdateChecker {
*/
public UpdateCheckerStatus checkForUpdate() {
PEVersion localVersion = PacketEvents.get().getVersion();
PEVersion newVersion;
try {
newVersion = new PEVersion(checkLatestReleasedVersion());
} catch (Exception ex) {
newVersion = null;
String version = checkLatestReleasedVersion();
if (version == null) {
return UpdateCheckerStatus.FAILED;
}
if (newVersion != null && localVersion.isOlderThan(newVersion)) {
inform("There is an update available for the PacketEvents API! Your build: (" + localVersion.toString() + ") | Latest released build: (" + newVersion.toString() + ")");
PEVersion newVersion = new PEVersion(checkLatestReleasedVersion());
if (localVersion.isOlderThan(newVersion)) {
inform("There is an update available for the PacketEvents API! Your build: (" + localVersion + ") | Latest released build: (" + newVersion + ")");
return UpdateCheckerStatus.OUTDATED;
} else if (newVersion != null && localVersion.isNewerThan(newVersion)) {
inform("You are on a dev or pre released build of PacketEvents. Your build: (" + localVersion.toString() + ") | Latest released build: (" + newVersion.toString() + ")");
} else if (localVersion.isNewerThan(newVersion)) {
inform("You are on a dev or pre released build of PacketEvents. Your build: (" + localVersion + ") | Latest released build: (" + newVersion + ")");
return UpdateCheckerStatus.PRE_RELEASE;
} else if (localVersion.equals(newVersion)) {
inform("You are on the latest released version of PacketEvents. (" + newVersion.toString() + ")");
inform("You are on the latest released version of PacketEvents. (" + newVersion + ")");
return UpdateCheckerStatus.UP_TO_DATE;
} else {
report("Something went wrong while checking for an update. Your build: (" + localVersion.toString() + ") | Latest released build: (" + newVersion.toString() + ")");
report("Something went wrong while checking for an update. Your build: (" + localVersion + ") | Latest released build: (" + newVersion + ")");
return UpdateCheckerStatus.FAILED;
}
}
@@ -24,10 +24,23 @@ import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
public interface LowLevelUpdateChecker {
String getLatestRelease();
public class UpdaterCheck {
public String getLatestRelease() {
try {
String jsonResponse = getLatestReleaseJson();
default String getLatestReleaseJson() throws IOException {
String targetPart = "\"name\":";
int nameIndex = jsonResponse.indexOf(targetPart);
int stringStart = nameIndex + targetPart.length();
int stringEnd = jsonResponse.indexOf(",", stringStart);
return jsonResponse.substring(stringStart + 1, stringEnd - 1);
} catch (Exception e) {
return null;
}
}
private String getLatestReleaseJson() throws IOException {
URLConnection connection = new URL("https://api.github.com/repos/retrooper/packetevents/releases/latest").openConnection();
connection.addRequestProperty("User-Agent", "Mozilla/4.0");
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
@@ -0,0 +1,32 @@
package io.github.retrooper.packetevents.utils;
import java.util.Optional;
public class ConditionalValue<T, K> {
private final Optional<T> left;
private final Optional<K> right;
private ConditionalValue(Optional<T> left, Optional<K> right) {
this.left = left;
this.right = right;
}
public Optional<T> left() {
return left;
}
public Optional<K> right() {
return right;
}
@Override
public String toString() {
return left.map(t -> "ConditionalValue {left: " + t.toString() + "}")
.orElseGet(() -> "ConditionalValue {right: " + right.get().toString() + "}");
}
public static <L, R> ConditionalValue<L, R> makeLeft(L left) {
return new ConditionalValue<>(Optional.of(left), Optional.empty());
}
public static <L, R> ConditionalValue<L, R> makeRight(R right) {
return new ConditionalValue<>(Optional.empty(), Optional.of(right));
}
}
@@ -0,0 +1,23 @@
package io.github.retrooper.packetevents.utils;
import com.mojang.datafixers.util.Either;
import java.util.Optional;
public class MojangEitherUtil {
public static <L, R> Either<L, R> makeLeft(L left) {
return Either.left(left);
}
public static <L, R> Either<L, R> makeRight(R right) {
return Either.right(right);
}
public static <L> Optional<L> getLeft(Object either) {
return ((Either)either).left();
}
public static <R> Optional<R> getRight(Object either) {
return ((Either)either).right();
}
}
@@ -0,0 +1,37 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2021 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.github.retrooper.packetevents.utils;
public class SaltSignature {
private final long salt;
private final byte[] signature;
public SaltSignature(long salt, byte[] signature) {
this.salt = salt;
this.signature = signature;
}
public long getSalt() {
return salt;
}
public byte[] getSignature() {
return signature;
}
}
@@ -101,6 +101,7 @@ public class AttributeModifierWrapper extends WrappedPacket {
}
}
//TODO Might cause issues since now a resourcelocation
public String getName() {
if (supplierPresent) {
//About 1.13 and above
@@ -24,6 +24,7 @@ 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 io.github.retrooper.packetevents.utils.server.ServerVersion;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
@@ -40,6 +41,11 @@ public class AttributeSnapshotWrapper extends WrappedPacket {
private static Class<?> attributeSnapshotClass, attributeBaseClass;
private static Field iRegistryAttributeBaseField;
private static Method getiRegistryByMinecraftKeyMethod;
private static Method readStringMethod;
private static Class<?> holderClass;
private static Method accessHolderValueMethod;
private static boolean hasHolder = false;
private static boolean stringKeyPresent;
public AttributeSnapshotWrapper(NMSPacket packet) {
@@ -58,6 +64,11 @@ public class AttributeSnapshotWrapper extends WrappedPacket {
attributeSnapshotClass = SubclassUtil.getSubClass(PacketTypeClasses.Play.Server.UPDATE_ATTRIBUTES, "AttributeSnapshot");
}
}
holderClass = NMSUtils.getNMClassWithoutException("core.Holder");
if (holderClass != null) {
hasHolder = Reflection.getField(attributeSnapshotClass, holderClass, 0) != null;
}
if (attributeSnapshotConstructor == null) {
try {
attributeSnapshotConstructor = attributeSnapshotClass.getConstructor(PacketTypeClasses.Play.Server.UPDATE_ATTRIBUTES, String.class, double.class, Collection.class);
@@ -135,6 +146,11 @@ public class AttributeSnapshotWrapper extends WrappedPacket {
}
}
holderClass = NMSUtils.getNMClassWithoutException("core.Holder");
if (holderClass != null) {
hasHolder = Reflection.getField(attributeSnapshotClass, holderClass, 0) != null;
}
if (attributeSnapshotConstructor == null) {
try {
attributeSnapshotConstructor = attributeSnapshotClass.getConstructor(attributeBaseClass, double.class, Collection.class);
@@ -160,9 +176,33 @@ public class AttributeSnapshotWrapper extends WrappedPacket {
if (stringKeyPresent) {
return readString(0);
} else {
Object attributeBase = readObject(0, attributeBaseClass);
WrappedPacket attributeBaseWrapper = new WrappedPacket(new NMSPacket(attributeBase), attributeBaseClass);
return attributeBaseWrapper.readString(0);
Object attributeBase = null;
if (hasHolder) {
Object holder = readObject(0, holderClass);
if (accessHolderValueMethod == null) {
accessHolderValueMethod = Reflection.getMethod(holderClass, 0);
}
try {
attributeBase = accessHolderValueMethod.invoke(holder);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
} else {
attributeBase = readObject(0, attributeBaseClass);
}
if (version.isNewerThanOrEquals(ServerVersion.v_1_21)) {
if (readStringMethod== null) {
readStringMethod = Reflection.getMethod(attributeBaseClass, String.class, 0);
}
try {
return (String) readStringMethod.invoke(attributeBase);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
} else {
WrappedPacket attributeBaseWrapper = new WrappedPacket(new NMSPacket(attributeBase), attributeBaseClass);
return attributeBaseWrapper.readString(0);
}
}
}
@@ -20,6 +20,8 @@ package io.github.retrooper.packetevents.utils.netty.bytebuf;
public interface ByteBufUtil {
Object buffer();
Object newByteBuf(byte[] data);
void retain(Object byteBuf);
@@ -24,6 +24,11 @@ import net.minecraft.util.io.netty.util.internal.EmptyArrays;
public final class ByteBufUtil_7 implements ByteBufUtil {
@Override
public Object buffer() {
return Unpooled.buffer();
}
@Override
public Object newByteBuf(byte[] data) {
return Unpooled.wrappedBuffer(data);
@@ -24,6 +24,11 @@ import io.netty.util.internal.EmptyArrays;
public final class ByteBufUtil_8 implements ByteBufUtil {
@Override
public Object buffer() {
return Unpooled.buffer();
}
@Override
public Object newByteBuf(byte[] data) {
return Unpooled.wrappedBuffer(data);
@@ -21,6 +21,7 @@ package io.github.retrooper.packetevents.utils.nms;
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.reflection.ClassUtil;
import io.github.retrooper.packetevents.utils.reflection.Reflection;
import io.github.retrooper.packetevents.utils.reflection.SubclassUtil;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
@@ -33,35 +34,33 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.*;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
public final class NMSUtils {
public static final String NMS_DIR = ServerVersion.getNMSDirectory() + ".";
public static final String OBC_DIR = ServerVersion.getOBCDirectory() + ".";
private static final ThreadLocal<Random> randomThreadLocal = ThreadLocal.withInitial(Random::new);
public static boolean legacyNettyImportMode;
public static ServerVersion version;
public static Constructor<?> blockPosConstructor, minecraftKeyConstructor, vec3DConstructor, dataWatcherConstructor, packetDataSerializerConstructor, itemStackConstructor;
public static Class<?> mobEffectListClass, nmsEntityClass, minecraftServerClass, craftWorldClass, playerInteractManagerClass, entityPlayerClass, playerConnectionClass, craftServerClass,
public static Executable minecraftKeyConstructorOrMethod;
public static Constructor<?> blockPosConstructor, vec3DConstructor, dataWatcherConstructor, packetDataSerializerConstructor, itemStackConstructor;
public static Class<?> mobEffectListClass, nmsEntityClass, minecraftServerClass, craftWorldClass, playerInteractManagerClass, entityPlayerClass, playerConnectionClass, SERVER_COMMON_PACKETLISTENER_IMPL_CLASS, craftServerClass,
craftPlayerClass, serverConnectionClass, craftEntityClass, nmsItemStackClass, networkManagerClass, nettyChannelClass, gameProfileClass, iChatBaseComponentClass,
blockPosClass, sectionPositionClass, vec3DClass, channelFutureClass, blockClass, iBlockDataClass, nmsWorldClass, craftItemStackClass,
soundEffectClass, minecraftKeyClass, chatSerializerClass, craftMagicNumbersClass, worldSettingsClass, worldServerClass, dataWatcherClass,
dedicatedServerClass, entityHumanClass, packetDataSerializerClass, byteBufClass, dimensionManagerClass, nmsItemClass, iMaterialClass, movingObjectPositionBlockClass, boundingBoxClass,
tileEntityCommandClass;
tileEntityCommandClass, mojangEitherClass, registryMaterials, builtInRegistriesClass;
public static Class<? extends Enum<?>> enumDirectionClass, enumHandClass, enumGameModeClass, enumDifficultyClass, tileEntityCommandTypeClass;
public static Method getBlockPosX, getBlockPosY, getBlockPosZ;
public static Method getBlockPosX, getBlockPosY, getBlockPosZ, mojangEitherLeft, mojangEitherRight, getRegistryId, getRegistryById;
private static String nettyPrefix;
private static Method getCraftPlayerHandle, getCraftEntityHandle, getCraftWorldHandle, asBukkitCopy,
asNMSCopy, getMessageMethod, chatFromStringMethod, getMaterialFromNMSBlock, getNMSBlockFromMaterial,
getMobEffectListId, getMobEffectListById, getItemId, getItemById, getBukkitEntity;
private static Field entityPlayerPingField, entityBoundingBoxField;
private static Field entityPlayerPingField, entityBoundingBoxField, mobEffectsRegistryField;
public static Field getBaseBlockPosX, getBaseBlockPosY, getBaseBlockPosZ;
private static Object minecraftServer;
private static Object minecraftServerConnection;
@@ -133,6 +132,8 @@ public final class NMSUtils {
playerConnectionClass = getNMSClassWithoutException("PlayerConnection");
if (playerConnectionClass == null) {
playerConnectionClass = getNMClassWithoutException("server.network.PlayerConnection");
//Only for 1.20.2
SERVER_COMMON_PACKETLISTENER_IMPL_CLASS = getNMClassWithoutException("server.network.ServerCommonPacketListenerImpl");
}
serverConnectionClass = getNMSClassWithoutException("ServerConnection");
if (serverConnectionClass == null) {
@@ -182,6 +183,9 @@ public final class NMSUtils {
dataWatcherClass = getNMSClassWithoutException("DataWatcher");
if (dataWatcherClass == null) {
dataWatcherClass = getNMClassWithoutException("network.syncher.DataWatcher");
if (dataWatcherClass == null) {
dataWatcherClass = getNMClassWithoutException("network.syncher.SynchedEntityData");
}
}
nmsItemClass = getNMSClassWithoutException("Item");
if (nmsItemClass == null) {
@@ -222,6 +226,9 @@ public final class NMSUtils {
iChatBaseComponentClass = NMSUtils.getNMSClassWithoutException("IChatBaseComponent");
if (iChatBaseComponentClass == null) {
iChatBaseComponentClass = getNMClassWithoutException("network.chat.IChatBaseComponent");
if (iChatBaseComponentClass == null) {
iChatBaseComponentClass = getNMClassWithoutException("network.chat.Component");
}
}
tileEntityCommandClass = NMSUtils.getNMSClassWithoutException("TileEntityCommand");
@@ -231,6 +238,37 @@ public final class NMSUtils {
tileEntityCommandTypeClass = SubclassUtil.getEnumSubClass(tileEntityCommandClass, 0);
//Isn't present on every version
mojangEitherClass = Reflection.getClassByNameWithoutException("com.mojang.datafixers.util.Either");
registryMaterials = Reflection.getClassByNameWithoutException("net.minecraft.core.RegistryMaterials");
builtInRegistriesClass = Reflection.getClassByNameWithoutException("net.minecraft.core.registries.BuiltInRegistries");
if (builtInRegistriesClass != null) {
mobEffectsRegistryField = Reflection.getField(builtInRegistriesClass, "e");
for (Field f : Reflection.getFields(builtInRegistriesClass)) {
Type type = f.getGenericType();
if (type instanceof ParameterizedType) {
ParameterizedType pType = (ParameterizedType) type;
if (pType.getActualTypeArguments()[0].equals(mobEffectListClass)) {
mobEffectsRegistryField = f;
break;
}
}
}
}
Class<?> baseBlockPosClass = NMSUtils.getNMSClassWithoutException("BaseBlockPosition");
if (baseBlockPosClass == null) {
baseBlockPosClass = getNMClassWithoutException("core.BaseBlockPosition");
}
if (baseBlockPosClass != null) {
getBaseBlockPosX = Reflection.getField(baseBlockPosClass, int.class, 0);
getBaseBlockPosY = Reflection.getField(baseBlockPosClass, int.class, 1);
getBaseBlockPosZ = Reflection.getField(baseBlockPosClass, int.class, 2);
}
vec3DClass = NMSUtils.getNMSClassWithoutException("Vec3D");
if (vec3DClass == null) {
vec3DClass = getNMClassWithoutException("world.phys.Vec3D");
@@ -266,7 +304,11 @@ public final class NMSUtils {
}
if (dataWatcherClass != null) {
dataWatcherConstructor = dataWatcherClass.getConstructor(nmsEntityClass);
try {
dataWatcherConstructor = dataWatcherClass.getConstructor(nmsEntityClass);
} catch (Exception ex) {
dataWatcherConstructor = dataWatcherClass.getDeclaredConstructors()[0];
}
}
if (nmsItemStackClass != null && iMaterialClass != null) {
@@ -309,6 +351,9 @@ public final class NMSUtils {
} catch (ClassNotFoundException e) {
//That is fine, it is probably a subclass
chatSerializerClass = SubclassUtil.getSubClass(iChatBaseComponentClass, "ChatSerializer");
if (chatSerializerClass == null) {
chatSerializerClass = SubclassUtil.getSubClass(iChatBaseComponentClass, "Serializer");
}
}
craftMagicNumbersClass = NMSUtils.getOBCClass("util.CraftMagicNumbers");
@@ -318,7 +363,12 @@ public final class NMSUtils {
getNMSBlockFromMaterial = Reflection.getMethod(craftMagicNumbersClass, "getBlock", NMSUtils.blockClass, Material.class);
if (minecraftKeyClass != null) {
minecraftKeyConstructor = minecraftKeyClass.getConstructor(String.class);
try {
minecraftKeyConstructorOrMethod = minecraftKeyClass.getConstructor(String.class);
} catch (Exception ex) {
minecraftKeyConstructorOrMethod = Reflection.getMethod(minecraftKeyClass, 0, String.class, char.class);
}
}
} catch (Exception e) {
e.printStackTrace();
@@ -345,6 +395,9 @@ public final class NMSUtils {
// Mappings changed with 1.18
if (getBlockPosX == null) {
getBlockPosX = Reflection.getMethod(NMSUtils.blockPosClass, "u", int.class);
if (getBlockPosX == null) {
}
}
if (getBlockPosY == null) {
getBlockPosY = Reflection.getMethod(NMSUtils.blockPosClass, "v", int.class);
@@ -353,6 +406,17 @@ public final class NMSUtils {
getBlockPosZ = Reflection.getMethod(NMSUtils.blockPosClass, "w", int.class);
}
}
if (mojangEitherClass != null) {
mojangEitherLeft = Reflection.getMethod(mojangEitherClass, "left", Optional.class);
mojangEitherRight = Reflection.getMethod(mojangEitherClass, "right", Optional.class);
}
if (registryMaterials != null) {
getRegistryId = Reflection.getMethod(registryMaterials, int.class, 0, 1);
getRegistryById = Reflection.getMethod(registryMaterials, Optional.class, true, 0, int.class);
}
worldSettingsClass = NMSUtils.getNMSClassWithoutException("WorldSettings");
if (worldServerClass == null) {
worldServerClass = getNMClassWithoutException("world.level.WorldSettings");
@@ -379,8 +443,13 @@ public final class NMSUtils {
public static Object getMinecraftServerInstance(Server server) {
if (minecraftServer == null) {
try {
minecraftServer = Reflection.getField(craftServerClass, minecraftServerClass, 0)
.get(server);
Field f = Reflection.getField(craftServerClass, minecraftServerClass, 0);
if (f == null) {
//1.20.5 way
minecraftServer = Reflection.getField(minecraftServerClass, minecraftServerClass, 0).get(null);
} else {
minecraftServer = f.get(server);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
@@ -407,7 +476,7 @@ public final class NMSUtils {
}
public static Class<?> getNMSClass(String name) throws ClassNotFoundException {
return Class.forName(NMS_DIR + name);
return Class.forName(ServerVersion.getNMSDirectory() + name);
}
public static Class<?> getNMClass(String name) throws ClassNotFoundException {
@@ -431,7 +500,7 @@ public final class NMSUtils {
}
public static Class<? extends Enum<?>> getNMSEnumClass(String name) throws ClassNotFoundException {
return (Class<? extends Enum<?>>) Class.forName(NMS_DIR + name);
return (Class<? extends Enum<?>>) Class.forName(ServerVersion.getNMSDirectory() + name);
}
public static Class<? extends Enum<?>> getNMSEnumClassWithoutException(String name) {
@@ -452,7 +521,7 @@ public final class NMSUtils {
}
public static Class<?> getOBCClass(String name) throws ClassNotFoundException {
return Class.forName(OBC_DIR + name);
return Class.forName(ServerVersion.getOBCDirectory() + name);
}
public static Class<?> getNettyClass(String name) throws ClassNotFoundException {
@@ -510,10 +579,18 @@ public final class NMSUtils {
public static Object getPlayerConnection(final Player player) {
Object entityPlayer = getEntityPlayer(player);
if (entityPlayer == null) {
Class<?> entityPlayerClass = entityPlayer != null ? entityPlayer.getClass() : null;
String className = entityPlayer != null ? ClassUtil.getClassSimpleName(entityPlayerClass) : "";
if (entityPlayer == null
|| className.contains("Fake")) {
return null;
}
WrappedPacket wrappedEntityPlayer = new WrappedPacket(new NMSPacket(entityPlayer));
//If we need to get the superclass, we get it
if (!className.equals("EntityPlayer")
&& ClassUtil.getClassSimpleName(entityPlayerClass.getSuperclass()).equals("EntityPlayer")) {
entityPlayerClass = entityPlayerClass.getSuperclass();
}
WrappedPacket wrappedEntityPlayer = new WrappedPacket(new NMSPacket(entityPlayer), entityPlayerClass);
return wrappedEntityPlayer.readObject(0, NMSUtils.playerConnectionClass);
}
@@ -528,7 +605,8 @@ public final class NMSUtils {
if (playerConnection == null) {
return null;
}
WrappedPacket wrapper = new WrappedPacket(new NMSPacket(playerConnection), playerConnectionClass);
Class<?> playerConClass = SERVER_COMMON_PACKETLISTENER_IMPL_CLASS != null ? SERVER_COMMON_PACKETLISTENER_IMPL_CLASS : playerConnectionClass;
WrappedPacket wrapper = new WrappedPacket(new NMSPacket(playerConnection), playerConClass);
try {
return wrapper.readObject(0, networkManagerClass);
} catch (Exception ex) {
@@ -537,11 +615,17 @@ public final class NMSUtils {
return wrapper.readObject(0, networkManagerClass);
} catch (Exception ex2) {
//Support for some custom plugins.
playerConnection = wrapper.read(0, playerConnectionClass);
wrapper = new WrappedPacket(new NMSPacket(playerConnection), playerConnectionClass);
return wrapper.readObject(0, networkManagerClass);
try {
playerConnection = wrapper.read(0, playerConnectionClass);
wrapper = new WrappedPacket(new NMSPacket(playerConnection), playerConnectionClass);
return wrapper.readObject(0, networkManagerClass);
} catch (Exception ex3) {
//Print the original exception!
ex.printStackTrace();
}
}
}
return null;
}
public static Object getChannel(final Player player) {
@@ -700,7 +784,12 @@ public final class NMSUtils {
public static Object generateMinecraftKeyNew(String text) {
try {
return minecraftKeyConstructor.newInstance(text);
if (minecraftKeyConstructorOrMethod instanceof Constructor<?>) {
return ((Constructor<?>)minecraftKeyConstructorOrMethod).newInstance(text);
}
else {
return ((Method)minecraftKeyConstructorOrMethod).invoke(text, ':');
}
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
@@ -744,7 +833,11 @@ public final class NMSUtils {
public static Object generateDataWatcher(Object nmsEntity) {
try {
return dataWatcherConstructor.newInstance(nmsEntity);
if (dataWatcherConstructor.getParameterCount() == 2) {
return dataWatcherConstructor.newInstance(nmsEntity, null);
} else {
return dataWatcherConstructor.newInstance(nmsEntity);
}
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
@@ -780,6 +873,11 @@ public final class NMSUtils {
public static int getEffectId(Object nmsMobEffectList) {
try {
//1.20.2+
if (getMobEffectListId == null) {
Object registry = mobEffectsRegistryField.get(null);
return (int) getRegistryId.invoke(registry, nmsMobEffectList);
}
return (int) getMobEffectListId.invoke(null, nmsMobEffectList);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
@@ -789,6 +887,10 @@ public final class NMSUtils {
public static Object getMobEffectListById(int effectID) {
try {
if (getMobEffectListById == null) {
Object registry = mobEffectsRegistryField.get(null);
return getRegistryById.invoke(registry, effectID);
}
return getMobEffectListById.invoke(null, effectID);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
@@ -822,4 +924,22 @@ public final class NMSUtils {
}
return null;
}
public static Optional<Object> getEitherLeft(Object either) {
try {
return (Optional<Object>) mojangEitherLeft.invoke(either);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
public static Optional<Object> getEitherRight(Object either) {
try {
return (Optional<Object>) mojangEitherRight.invoke(either);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}
@@ -94,8 +94,19 @@ public enum ClientVersion {
v_1_18_2(758),
v_1_19(759), v_1_19_1(760), v_1_19_3(761), v_1_19_4(762),
/**
* 1.20.3 and 1.20.4 have the same protocol version.
* 1.20.5 and 1.20.6 have the same protocol version.
*/
v_1_20(763), v_1_20_2(764), v_1_20_3(765), v_1_20_5(766),
v_1_21(767),
//TODO Update(checkpoint for things to look out for when updating)
LOWER_THAN_SUPPORTED_VERSIONS(v_1_7_10.protocolVersion - 1),
HIGHER_THAN_SUPPORTED_VERSIONS(v_1_18_2.protocolVersion + 1),
//TODO Update(checkpoint for things to look out for when updating)
HIGHER_THAN_SUPPORTED_VERSIONS(v_1_21.protocolVersion + 1),
/**
* Pre releases just aren't supported, we would end up with so many enum constants.
* This constant assures you they are on a pre-release.
@@ -113,9 +124,10 @@ public enum ClientVersion {
private static final int HIGHEST_SUPPORTED_PROTOCOL_VERSION = HIGHER_THAN_SUPPORTED_VERSIONS.protocolVersion - 1;
private static final Map<Integer, ClientVersion> CLIENT_VERSION_CACHE = new IdentityHashMap<>();
//TODO Update(checkpoint for things to look out for when updating)
private static final int[] CLIENT_VERSIONS = new int[]{5, 47, 107, 108, 109, 110, 210, 315, 316, 335, 338,
340, 393, 401, 404, 477, 480, 485, 490, 498, 573,
575, 578, 735, 736, 751, 753, 754, 755, 756, 757, 758};
575, 578, 735, 736, 751, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767};
private int protocolVersion;
ClientVersion(int protocolVersion) {
@@ -33,6 +33,7 @@ import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.net.InetSocketAddress;
import java.util.Map;
@@ -275,6 +276,7 @@ public final class PlayerUtils {
return GameProfileUtil.getGameProfileSkin(gameProfile);
}
@Nullable
public Object getChannel(Player player) {
String name = player.getName();
Object channel = channels.get(name);
@@ -139,6 +139,23 @@ public final class Reflection {
return null;
}
public static Method getMethod(Class<?> cls, Class<?> returning, boolean checkIfIsNotReturnType, int index, Class<?>... params) {
int currentIndex = 0;
for (Method m : cls.getDeclaredMethods()) {
boolean isReturnType = returning == null || m.getReturnType().equals(returning);
if (Arrays.equals(m.getParameterTypes(), params)
&& (checkIfIsNotReturnType ? !isReturnType : isReturnType)
&& index == currentIndex++) {
m.setAccessible(true);
return m;
}
}
if (cls.getSuperclass() != null) {
return getMethod(cls.getSuperclass(), null, index, params);
}
return null;
}
public static Method getMethod(final Class<?> cls, final String name, Class<?> returning, Class<?>... params) {
for (final Method m : cls.getDeclaredMethods()) {
if (m.getName().equals(name)
@@ -188,6 +205,24 @@ public final class Reflection {
return null;
}
public static Method getMethod(final Class<?> cls, final Class<?> returning, final int index, int amountOfArguments) {
if (cls == null) {
return null;
}
int currentIndex = 0;
for (final Method m : cls.getDeclaredMethods()) {
if ((returning == null || m.getReturnType().equals(returning)) && m.getParameterTypes().length == amountOfArguments
&& index == currentIndex++) {
m.setAccessible(true);
return m;
}
}
if (cls.getSuperclass() != null) {
return getMethod(cls.getSuperclass(), returning, index);
}
return null;
}
public static Method getMethodCheckContainsString(Class<?> cls, String nameContainsThisStr, Class<?> returning) {
if (cls == null) {
return null;
@@ -31,7 +31,6 @@ import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.spigotmc.SpigotConfig;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -95,10 +94,6 @@ public final class ServerUtils {
return npcManager;
}
public boolean isBungeeCordEnabled() {
return SpigotConfig.bungee;
}
public BoundingBox getEntityBoundingBox(Entity entity) {
Object nmsEntity = NMSUtils.getNMSEntity(entity);
Object aabb = NMSUtils.getNMSAxisAlignedBoundingBox(nmsEntity);
@@ -44,10 +44,27 @@ public enum ServerVersion {
v_1_16(735), v_1_16_1(736), v_1_16_2(751), v_1_16_3(753), v_1_16_4(754), v_1_16_5(754),
v_1_17(755), v_1_17_1(756),
v_1_18(757), v_1_18_1(757), v_1_18_2(758),
v_1_19(759), v_1_19_1(760), v_1_19_2(760), v_1_19_3(761), v_1_19_4(762),
//Same protocol version for 1.20 and 1.20.1. Same protocol version for 1.20.3 and 1.20.4.
//Same protocol version for 1.20.5 and 1.20.6.
v_1_20(763), v_1_20_1(763), v_1_20_2(764), v_1_20_3(765), v_1_20_4(765), v_1_20_5(766), v_1_20_6(766),
v_1_21(767),
//TODO Update (checkpoint)
ERROR(-1);
private static final String NMS_VERSION_SUFFIX = Bukkit.getServer().getClass().getPackage().getName()
.replace(".", ",").split(",")[3];
private static final String NMS_VERSION_SUFFIX, OBC_DIRECTORY;
static {
String cbPackage = Bukkit.getServer().getClass().getPackage().getName();
String temp;
try {
temp = cbPackage.replace(".", ",").split(",")[3];
} catch (Exception ex) {
temp = "";
}
NMS_VERSION_SUFFIX = temp + ".";
OBC_DIRECTORY = cbPackage + ".";
}
private static final ServerVersion[] VALUES = values();
public static ServerVersion[] reversedValues = new ServerVersion[VALUES.length];
private static ServerVersion cachedVersion;
@@ -124,11 +141,11 @@ public enum ServerVersion {
}
public static String getOBCDirectory() {
return "org.bukkit.craftbukkit." + (getNMSSuffix());
return OBC_DIRECTORY;
}
public static ServerVersion getLatest() {
return reversedValues[0];
return reversedValues[1];
}
public static ServerVersion getOldest() {
+1 -1
View File
@@ -1,5 +1,5 @@
name: packetevents
version: 1.8.2
version: 1.8.4
main: io.github.retrooper.packetevents.PacketEventsPlugin
author: retrooper
softdepend: