diff --git a/bukkit/build.gradle b/bukkit/build.gradle index 37242d65..7681586c 100644 --- a/bukkit/build.gradle +++ b/bukkit/build.gradle @@ -13,6 +13,7 @@ dependencies { implementation 'de.tr7zw:item-nbt-api:2.12.4' compileOnly 'org.spigotmc:spigot-api:1.17.1-R0.1-SNAPSHOT' + compileOnly 'com.github.retrooper.packetevents:spigot:2.2.1' compileOnly 'com.comphenix.protocol:ProtocolLib:5.1.0' compileOnly 'org.projectlombok:lombok:1.18.32' compileOnly 'commons-io:commons-io:2.16.1' diff --git a/bukkit/src/main/java/net/william278/husksync/BukkitHuskSync.java b/bukkit/src/main/java/net/william278/husksync/BukkitHuskSync.java index c1755b63..a92d3881 100644 --- a/bukkit/src/main/java/net/william278/husksync/BukkitHuskSync.java +++ b/bukkit/src/main/java/net/william278/husksync/BukkitHuskSync.java @@ -46,7 +46,6 @@ import net.william278.husksync.database.PostgresDatabase; import net.william278.husksync.event.BukkitEventDispatcher; import net.william278.husksync.hook.PlanHook; import net.william278.husksync.listener.BukkitEventListener; -import net.william278.husksync.listener.EventListener; import net.william278.husksync.migrator.LegacyMigrator; import net.william278.husksync.migrator.Migrator; import net.william278.husksync.migrator.MpdbMigrator; @@ -98,7 +97,7 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync, BukkitTask.S private MorePaperLib paperLib; private Database database; private RedisManager redisManager; - private EventListener eventListener; + private BukkitEventListener eventListener; private DataAdapter dataAdapter; private DataSyncer dataSyncer; private LegacyConverter legacyConverter; @@ -113,11 +112,10 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync, BukkitTask.S private Server serverName; @Override - public void onEnable() { + public void onLoad() { // Initial plugin setup this.disabling = false; this.gson = createGson(); - this.audiences = BukkitAudiences.create(this); this.paperLib = new MorePaperLib(this); // Load settings and locales @@ -127,6 +125,13 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync, BukkitTask.S loadServer(); }); + this.eventListener = createEventListener(); + eventListener.onLoad(); + } + + @Override + public void onEnable() { + this.audiences = BukkitAudiences.create(this); // Prepare data adapter initialize("data adapter", (plugin) -> { if (settings.getSynchronization().isCompressData()) { @@ -185,7 +190,7 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync, BukkitTask.S }); // Register events - initialize("events", (plugin) -> this.eventListener = createEventListener()); + initialize("events", (plugin) -> eventListener.onEnable()); // Register commands initialize("commands", (plugin) -> BukkitCommand.Type.registerCommands(this)); diff --git a/bukkit/src/main/java/net/william278/husksync/listener/BukkitEventListener.java b/bukkit/src/main/java/net/william278/husksync/listener/BukkitEventListener.java index 21c282bf..7bdea7d7 100644 --- a/bukkit/src/main/java/net/william278/husksync/listener/BukkitEventListener.java +++ b/bukkit/src/main/java/net/william278/husksync/listener/BukkitEventListener.java @@ -20,7 +20,6 @@ package net.william278.husksync.listener; import net.william278.husksync.BukkitHuskSync; -import net.william278.husksync.HuskSync; import net.william278.husksync.data.BukkitData; import net.william278.husksync.user.BukkitUser; import net.william278.husksync.user.OnlineUser; @@ -40,21 +39,38 @@ import java.util.stream.Collectors; public class BukkitEventListener extends EventListener implements BukkitJoinEventListener, BukkitQuitEventListener, BukkitDeathEventListener, Listener { - protected final LockedHandler lockedHandler; + protected LockedHandler lockedHandler; public BukkitEventListener(@NotNull BukkitHuskSync plugin) { super(plugin); - plugin.getServer().getPluginManager().registerEvents(this, plugin); - this.lockedHandler = createLockedHandler(plugin); + } + + public void onLoad() { + this.lockedHandler = createLockedHandler((BukkitHuskSync) plugin); + } + + public void onEnable() { + getPlugin().getServer().getPluginManager().registerEvents(this, getPlugin()); + lockedHandler.onEnable(); + } + + public void handlePluginDisable() { + super.handlePluginDisable(); + lockedHandler.onDisable(); } @NotNull private LockedHandler createLockedHandler(@NotNull BukkitHuskSync plugin) { - if (getPlugin().isDependencyLoaded("ProtocolLib") && getPlugin().getSettings().isCancelPackets()) { - return new BukkitLockedPacketListener(plugin); - } else { + if (!getPlugin().getSettings().isCancelPackets()) { return new BukkitLockedEventListener(plugin); } + if (getPlugin().isDependencyLoaded("PacketEvents")) { + return new BukkitPacketEventsLockedPacketListener(plugin); + } else if (getPlugin().isDependencyLoaded("ProtocolLib")) { + return new BukkitProtocolLibLockedPacketListener(plugin); + } + + return new BukkitLockedEventListener(plugin); } @Override @@ -134,8 +150,8 @@ public class BukkitEventListener extends EventListener implements BukkitJoinEven @NotNull @Override - public HuskSync getPlugin() { - return plugin; + public BukkitHuskSync getPlugin() { + return (BukkitHuskSync) plugin; } } diff --git a/bukkit/src/main/java/net/william278/husksync/listener/BukkitLockedEventListener.java b/bukkit/src/main/java/net/william278/husksync/listener/BukkitLockedEventListener.java index ae8f79d2..f20ea4a1 100644 --- a/bukkit/src/main/java/net/william278/husksync/listener/BukkitLockedEventListener.java +++ b/bukkit/src/main/java/net/william278/husksync/listener/BukkitLockedEventListener.java @@ -50,6 +50,10 @@ public class BukkitLockedEventListener implements LockedHandler, Listener { protected BukkitLockedEventListener(@NotNull BukkitHuskSync plugin) { this.plugin = plugin; + } + + @Override + public void onEnable() { plugin.getServer().getPluginManager().registerEvents(this, plugin); } diff --git a/bukkit/src/main/java/net/william278/husksync/listener/BukkitPacketEventsLockedPacketListener.java b/bukkit/src/main/java/net/william278/husksync/listener/BukkitPacketEventsLockedPacketListener.java new file mode 100644 index 00000000..a707d63f --- /dev/null +++ b/bukkit/src/main/java/net/william278/husksync/listener/BukkitPacketEventsLockedPacketListener.java @@ -0,0 +1,103 @@ +/* + * This file is part of HuskSync, licensed under the Apache License 2.0. + * + * Copyright (c) William278 + * Copyright (c) contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.william278.husksync.listener; + +import com.github.retrooper.packetevents.PacketEvents; +import com.github.retrooper.packetevents.event.PacketListenerAbstract; +import com.github.retrooper.packetevents.event.PacketListenerPriority; +import com.github.retrooper.packetevents.event.PacketReceiveEvent; +import com.github.retrooper.packetevents.protocol.packettype.PacketType; +import com.google.common.collect.Sets; +import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder; +import net.william278.husksync.BukkitHuskSync; +import org.jetbrains.annotations.NotNull; + +import java.util.Set; +import java.util.logging.Level; + +public class BukkitPacketEventsLockedPacketListener extends BukkitLockedEventListener implements LockedHandler { + + protected BukkitPacketEventsLockedPacketListener(@NotNull BukkitHuskSync plugin) { + super(plugin); + } + + @Override + public void onLoad() { + super.onLoad(); + PacketEvents.setAPI(SpigotPacketEventsBuilder.build(getPlugin())); + PacketEvents.getAPI().getSettings().reEncodeByDefault(false) + .checkForUpdates(false) + .bStats(true); + PacketEvents.getAPI().load(); + } + + @Override + public void onEnable() { + super.onEnable(); + PacketEvents.getAPI().getEventManager().registerListener(new PlayerPacketAdapter(this)); + PacketEvents.getAPI().init(); + plugin.log(Level.INFO, "Using PacketEvents to cancel packets for locked players"); + } + + private static class PlayerPacketAdapter extends PacketListenerAbstract { + + private static final Set ALLOWED_PACKETS = Set.of( + PacketType.Play.Client.KEEP_ALIVE, PacketType.Play.Client.PONG, PacketType.Play.Client.PLUGIN_MESSAGE, // Connection packets + PacketType.Play.Client.CHAT_MESSAGE, PacketType.Play.Client.CHAT_COMMAND, PacketType.Play.Client.CHAT_SESSION_UPDATE, // Chat / command packets + PacketType.Play.Client.PLAYER_POSITION, PacketType.Play.Client.PLAYER_POSITION_AND_ROTATION, PacketType.Play.Client.PLAYER_ROTATION, // Movement packets + PacketType.Play.Client.HELD_ITEM_CHANGE, PacketType.Play.Client.ANIMATION, PacketType.Play.Client.TELEPORT_CONFIRM, // Animation packets + PacketType.Play.Client.CLIENT_SETTINGS // Video setting packets + ); + + private static final Set CANCEL_PACKETS = getPacketsToListenFor(); + + + private final BukkitPacketEventsLockedPacketListener listener; + + public PlayerPacketAdapter(@NotNull BukkitPacketEventsLockedPacketListener listener) { + super(PacketListenerPriority.HIGH); + this.listener = listener; + } + + @Override + public void onPacketReceive(PacketReceiveEvent event) { + if(!(event.getPacketType() instanceof PacketType.Play.Client client)) { + return; + } + if (!CANCEL_PACKETS.contains(client)) { + return; + } + if (listener.cancelPlayerEvent(event.getUser().getUUID())) { + event.setCancelled(true); + } + } + + // Returns the set of ALL Server packets, excluding the set of allowed packets + @NotNull + private static Set getPacketsToListenFor() { + return Sets.difference( + Sets.newHashSet(PacketType.Play.Client.values()), + ALLOWED_PACKETS + ); + } + + } + +} diff --git a/bukkit/src/main/java/net/william278/husksync/listener/BukkitLockedPacketListener.java b/bukkit/src/main/java/net/william278/husksync/listener/BukkitProtocolLibLockedPacketListener.java similarity index 88% rename from bukkit/src/main/java/net/william278/husksync/listener/BukkitLockedPacketListener.java rename to bukkit/src/main/java/net/william278/husksync/listener/BukkitProtocolLibLockedPacketListener.java index ff9965c8..eac661b0 100644 --- a/bukkit/src/main/java/net/william278/husksync/listener/BukkitLockedPacketListener.java +++ b/bukkit/src/main/java/net/william278/husksync/listener/BukkitProtocolLibLockedPacketListener.java @@ -34,10 +34,15 @@ import java.util.stream.Collectors; import static com.comphenix.protocol.PacketType.Play.Client; -public class BukkitLockedPacketListener extends BukkitLockedEventListener implements LockedHandler { +public class BukkitProtocolLibLockedPacketListener extends BukkitLockedEventListener implements LockedHandler { - protected BukkitLockedPacketListener(@NotNull BukkitHuskSync plugin) { + protected BukkitProtocolLibLockedPacketListener(@NotNull BukkitHuskSync plugin) { super(plugin); + } + + @Override + public void onEnable() { + super.onEnable(); ProtocolLibrary.getProtocolManager().addPacketListener(new PlayerPacketAdapter(this)); plugin.log(Level.INFO, "Using ProtocolLib to cancel packets for locked players"); } @@ -53,9 +58,9 @@ public class BukkitLockedPacketListener extends BukkitLockedEventListener implem Client.SETTINGS // Video setting packets ); - private final BukkitLockedPacketListener listener; + private final BukkitProtocolLibLockedPacketListener listener; - public PlayerPacketAdapter(@NotNull BukkitLockedPacketListener listener) { + public PlayerPacketAdapter(@NotNull BukkitProtocolLibLockedPacketListener listener) { super(listener.getPlugin(), ListenerPriority.HIGHEST, getPacketsToListenFor()); this.listener = listener; } diff --git a/bukkit/src/main/resources/plugin.yml b/bukkit/src/main/resources/plugin.yml index 44d45516..71aa4c2d 100644 --- a/bukkit/src/main/resources/plugin.yml +++ b/bukkit/src/main/resources/plugin.yml @@ -7,6 +7,7 @@ description: '${description}' website: 'https://william278.net' folia-supported: true softdepend: + - 'packetevents' - 'ProtocolLib' - 'MysqlPlayerDataBridge' - 'Plan' diff --git a/common/src/main/java/net/william278/husksync/listener/EventListener.java b/common/src/main/java/net/william278/husksync/listener/EventListener.java index af352227..c1cfbcf1 100644 --- a/common/src/main/java/net/william278/husksync/listener/EventListener.java +++ b/common/src/main/java/net/william278/husksync/listener/EventListener.java @@ -107,7 +107,7 @@ public abstract class EventListener { /** * Handle the plugin disabling */ - public final void handlePluginDisable() { + public void handlePluginDisable() { // Save for all online players plugin.getOnlineUsers().stream() .filter(user -> !plugin.isLocked(user.getUuid()) && !user.isNpc()) diff --git a/common/src/main/java/net/william278/husksync/listener/LockedHandler.java b/common/src/main/java/net/william278/husksync/listener/LockedHandler.java index 088be49a..2286a050 100644 --- a/common/src/main/java/net/william278/husksync/listener/LockedHandler.java +++ b/common/src/main/java/net/william278/husksync/listener/LockedHandler.java @@ -54,4 +54,16 @@ public interface LockedHandler { @ApiStatus.Internal HuskSync getPlugin(); + default void onLoad() { + + } + + default void onEnable() { + + } + + default void onDisable() { + + } + } diff --git a/paper/src/main/resources/paper-plugin.yml b/paper/src/main/resources/paper-plugin.yml index bcc6cd96..2b8407bd 100644 --- a/paper/src/main/resources/paper-plugin.yml +++ b/paper/src/main/resources/paper-plugin.yml @@ -9,6 +9,10 @@ api-version: '1.19' folia-supported: true dependencies: server: + packetevents: + required: false + load: BEFORE + join-classpath: true ProtocolLib: required: false load: BEFORE