diff --git a/build.gradle b/build.gradle index b4b11ed..fea3463 100644 --- a/build.gradle +++ b/build.gradle @@ -18,12 +18,11 @@ tasks { allprojects { group = "com.github.kaspiandev.antipopup" - version = "7.2" + version = "7.3" repositories { mavenCentral() mavenLocal() - maven { url "https://repo.codemc.io/repository/maven-snapshots/" } maven { name = "spigotmc-repo" url = "https://hub.spigotmc.org/nexus/content/repositories/snapshots/" diff --git a/main/build.gradle b/main/build.gradle index 4149477..226afc2 100644 --- a/main/build.gradle +++ b/main/build.gradle @@ -1,5 +1,3 @@ -import java.util.concurrent.TimeUnit - plugins { id "java" id "com.github.johnrengelman.shadow" version "7.1.2" @@ -10,6 +8,10 @@ repositories { name = "devmart-other" url = "https://nexuslite.gcnt.net/repos/other/" } + maven { + name = "codemc" + url = "https://repo.codemc.io/repository/maven-releases/" + } } dependencies { @@ -19,6 +21,7 @@ dependencies { implementation project(path: ":v1.19.4", configuration: "reobf") implementation project(path: ":v1.20", configuration: "reobf") implementation project(path: ":v1.20.2", configuration: "reobf") + implementation project(path: ":v1.20.3", configuration: "reobf") compileOnly "org.spigotmc:spigot-api:1.19.4-R0.1-SNAPSHOT" compileOnly "dev.dejvokep:boosted-yaml-spigot:1.3" @@ -26,7 +29,7 @@ dependencies { compileOnly "org.apache.logging.log4j:log4j-core:2.19.0" implementation "org.bstats:bstats-bukkit:3.0.0" - implementation "com.github.retrooper.packetevents:spigot:2.1.0-20231127.180146-12" + implementation "com.github.retrooper.packetevents:spigot:2.2.0" implementation "com.tcoded:FoliaLib:0.2.3" } @@ -47,10 +50,6 @@ tasks { } } -configurations.configureEach { - resolutionStrategy.cacheChangingModulesFor(0, TimeUnit.SECONDS) -} - def targetJavaVersion = 17 java { diff --git a/main/src/main/java/com/github/kaspiandev/antipopup/AntiPopup.java b/main/src/main/java/com/github/kaspiandev/antipopup/AntiPopup.java index 7bc421d..c72d286 100644 --- a/main/src/main/java/com/github/kaspiandev/antipopup/AntiPopup.java +++ b/main/src/main/java/com/github/kaspiandev/antipopup/AntiPopup.java @@ -10,7 +10,7 @@ import com.github.kaspiandev.antipopup.nms.v1_19_4.PlayerInjector_v1_19_4; import com.github.kaspiandev.antipopup.nms.v1_20.PlayerInjector_v1_20; import com.github.kaspiandev.antipopup.nms.v1_20_2.PlayerInjector_v1_20_2; -import com.github.kaspiandev.antipopup.util.VersionUtil; +import com.github.kaspiandev.antipopup.nms.v1_20_3.PlayerInjector_v1_20_3; import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.manager.server.ServerManager; import com.github.retrooper.packetevents.manager.server.ServerVersion; @@ -113,12 +113,8 @@ public void onEnable() { if (yamlDoc.getBoolean("block-chat-reports")) { PlayerListener playerListener = switch (serverManager.getVersion()) { - case V_1_20_2 -> { - if (!ServerVersion.V_1_20_2.getReleaseName().equals(VersionUtil.getMinecraftVersion())) { - throw new IllegalStateException("Minecraft version and server version are different!"); - } - yield new PlayerListener(new PlayerInjector_v1_20_2()); - } + case V_1_20_3, V_1_20_4 -> new PlayerListener(new PlayerInjector_v1_20_3()); + case V_1_20_2 -> new PlayerListener(new PlayerInjector_v1_20_2()); case V_1_20, V_1_20_1 -> new PlayerListener(new PlayerInjector_v1_20()); case V_1_19_4 -> new PlayerListener(new PlayerInjector_v1_19_4()); case V_1_19_3 -> new PlayerListener(new PlayerInjector_v1_19_3()); diff --git a/settings.gradle b/settings.gradle index ad3f2f1..7bf8536 100644 --- a/settings.gradle +++ b/settings.gradle @@ -6,4 +6,4 @@ pluginManagement { } rootProject.name = "AntiPopup" -include "main", "shared", "v1.19.2", "v1.19.3", "v1.19.4", "v1.20", "v1.20.2" +include "main", "shared", "v1.19.2", "v1.19.3", "v1.19.4", "v1.20", "v1.20.2", "v1.20.3" diff --git a/v1.20.3/build.gradle b/v1.20.3/build.gradle new file mode 100644 index 0000000..b4e0aae --- /dev/null +++ b/v1.20.3/build.gradle @@ -0,0 +1,10 @@ +plugins { + id "java" + id "io.papermc.paperweight.userdev" version "${userdevVer}" +} + +dependencies { + compileOnly project(path: ":shared") + + paperweightDevelopmentBundle "io.papermc.paper:dev-bundle:1.20.3-R0.1-SNAPSHOT" +} diff --git a/v1.20.3/src/main/java/com/github/kaspiandev/antipopup/nms/v1_20_3/PlayerInjector_v1_20_3.java b/v1.20.3/src/main/java/com/github/kaspiandev/antipopup/nms/v1_20_3/PlayerInjector_v1_20_3.java new file mode 100644 index 0000000..19fc0e0 --- /dev/null +++ b/v1.20.3/src/main/java/com/github/kaspiandev/antipopup/nms/v1_20_3/PlayerInjector_v1_20_3.java @@ -0,0 +1,90 @@ +package com.github.kaspiandev.antipopup.nms.v1_20_3; + +import com.github.kaspiandev.antipopup.nms.AbstractInjector; +import io.netty.channel.*; +import net.minecraft.network.Connection; +import net.minecraft.network.chat.ChatType; +import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.game.ClientboundPlayerChatPacket; +import net.minecraft.network.protocol.game.ClientboundSystemChatPacket; +import net.minecraft.server.network.ServerCommonPacketListenerImpl; +import net.minecraft.server.network.ServerGamePacketListenerImpl; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R3.CraftServer; +import org.bukkit.craftbukkit.v1_20_R3.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import java.lang.reflect.Field; +import java.lang.reflect.InaccessibleObjectException; +import java.util.Optional; + +@SuppressWarnings("unused") +public class PlayerInjector_v1_20_3 implements AbstractInjector { + + private static final String HANDLER_NAME = "antipopup_handler"; + private static Field connectionField; + + static { + try { + for (Field field : ServerCommonPacketListenerImpl.class.getDeclaredFields()) { + if (field.getType().equals(Connection.class)) { + field.setAccessible(true); + connectionField = field; + break; + } + } + } catch (SecurityException | InaccessibleObjectException e) { + throw new RuntimeException(e); + } + } + + public void inject(Player player) { + ChannelDuplexHandler duplexHandler = new ChannelDuplexHandler() { + @Override + public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception { + if (packet instanceof ClientboundPlayerChatPacket chatPacket) { + Component content = chatPacket.unsignedContent(); + if (content == null) { + content = Component.literal(chatPacket.body().content()); + } + Optional chatType = chatPacket.chatType().resolve( + ((CraftServer) Bukkit.getServer()).getServer().registryAccess()); + + ((CraftPlayer) player).getHandle().connection.send( + new ClientboundSystemChatPacket(chatType.orElseThrow().decorate(content), false)); + return; + } + super.write(ctx, packet, promise); + } + }; + + ServerGamePacketListenerImpl listener = ((CraftPlayer) player).getHandle().connection; + Channel channel = getConnection(listener).channel; + ChannelPipeline pipeline = channel.pipeline(); + + if (pipeline.get(HANDLER_NAME) != null) { + pipeline.remove(HANDLER_NAME); + } + + channel.eventLoop().submit(() -> { + channel.pipeline().addBefore("packet_handler", HANDLER_NAME, duplexHandler); + }); + } + + public void uninject(Player player) { + ServerGamePacketListenerImpl listener = ((CraftPlayer) player).getHandle().connection; + Channel channel = getConnection(listener).channel; + channel.eventLoop().submit(() -> { + channel.pipeline().remove(HANDLER_NAME); + }); + } + + private Connection getConnection(ServerGamePacketListenerImpl listener) { + try { + return (Connection) connectionField.get(listener); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + +}