From eb6b63b63fd07d9dee8105dea71344785776cbc6 Mon Sep 17 00:00:00 2001 From: isokissa3 Date: Fri, 30 Nov 2018 22:14:37 +0200 Subject: [PATCH] Block sending remove mob effect packet to clients when updating give-effects potion effect timers Due to how CraftBukkit internally works is that when you add dublicate potion effect type it will be ignored unless you force it. But that causes some issues as the potion effect is removed (for really short period of time) but the packet is still sent to client. After this the new potion effect timer is sent on add mob effect packet. This will cause the nausea effect to reset everytime on clients 1.9 and above. This also fixes latency issues where the different packets dont arrive excatly at the same time and causes blinking on night vision effect. This is fixed by using ProtocolLib to cancel the sending of remove mob effect packet when we are updating those effects. On servers with 1.13 that are missing ProtocolLib alternative method will be used --- Common/pom.xml | 9 +++ .../WorldGuardExtraFlagsPlugin.java | 26 ++++++++ .../EntityPotionEffectEventListener.java | 61 +++++++++++++++++++ .../protocollib/ProtocolLibHelper.java | 25 ++++++++ .../RemoveEffectPacketListener.java | 47 ++++++++++++++ .../utils/SupportedFeatures.java | 10 +++ .../wg/handlers/GiveEffectsFlagHandler.java | 42 ++++++++----- Spigot/src/main/resources/plugin.yml | 4 +- 8 files changed, 208 insertions(+), 16 deletions(-) create mode 100644 Common/src/main/java/net/goldtreeservers/worldguardextraflags/listeners/EntityPotionEffectEventListener.java create mode 100644 Common/src/main/java/net/goldtreeservers/worldguardextraflags/protocollib/ProtocolLibHelper.java create mode 100644 Common/src/main/java/net/goldtreeservers/worldguardextraflags/protocollib/RemoveEffectPacketListener.java diff --git a/Common/pom.xml b/Common/pom.xml index 1c6a82b..f397ed9 100644 --- a/Common/pom.xml +++ b/Common/pom.xml @@ -26,6 +26,10 @@ empcraft http://ci.athion.net/job/FastAsyncWorldEdit/ws/mvn/ + + dmulloy2-repo + http://repo.dmulloy2.net/nexus/repository/public/ + @@ -79,5 +83,10 @@ 2.13-SNAPSHOT provided + + com.comphenix.protocol + ProtocolLib-API + 4.4.0 + \ No newline at end of file diff --git a/Common/src/main/java/net/goldtreeservers/worldguardextraflags/WorldGuardExtraFlagsPlugin.java b/Common/src/main/java/net/goldtreeservers/worldguardextraflags/WorldGuardExtraFlagsPlugin.java index 521cee0..2970ae8 100644 --- a/Common/src/main/java/net/goldtreeservers/worldguardextraflags/WorldGuardExtraFlagsPlugin.java +++ b/Common/src/main/java/net/goldtreeservers/worldguardextraflags/WorldGuardExtraFlagsPlugin.java @@ -16,9 +16,12 @@ import net.goldtreeservers.worldguardextraflags.flags.Flags; import net.goldtreeservers.worldguardextraflags.listeners.BlockListener; import net.goldtreeservers.worldguardextraflags.listeners.EntityListener; import net.goldtreeservers.worldguardextraflags.listeners.EntityListenerOnePointNine; +import net.goldtreeservers.worldguardextraflags.listeners.EntityPotionEffectEventListener; import net.goldtreeservers.worldguardextraflags.listeners.PlayerListener; import net.goldtreeservers.worldguardextraflags.listeners.WorldEditListener; import net.goldtreeservers.worldguardextraflags.listeners.WorldListener; +import net.goldtreeservers.worldguardextraflags.protocollib.ProtocolLibHelper; +import net.goldtreeservers.worldguardextraflags.utils.SupportedFeatures; import net.goldtreeservers.worldguardextraflags.wg.WorldGuardUtils; import net.goldtreeservers.worldguardextraflags.wg.handlers.BlockedEffectsFlagHandler; import net.goldtreeservers.worldguardextraflags.wg.handlers.CommandOnEntryFlagHandler; @@ -49,6 +52,7 @@ public class WorldGuardExtraFlagsPlugin extends JavaPlugin @Getter private EssentialsHelper essentialsHelper; @Getter private FAWEHelper faweHelper; + @Getter private ProtocolLibHelper protocolLibHelper; public WorldGuardExtraFlagsPlugin() { @@ -137,6 +141,19 @@ public class WorldGuardExtraFlagsPlugin extends JavaPlugin { } + + try + { + Plugin protocolLibPlugin = this.getServer().getPluginManager().getPlugin("ProtocolLib"); + if (protocolLibPlugin != null) + { + this.protocolLibHelper = new ProtocolLibHelper(this, protocolLibPlugin); + } + } + catch(Throwable ignore) + { + + } } @Override @@ -206,6 +223,15 @@ public class WorldGuardExtraFlagsPlugin extends JavaPlugin this.essentialsHelper.onEnable(); } + if (this.protocolLibHelper != null) + { + this.protocolLibHelper.onEnable(); + } + else if (SupportedFeatures.isPotionEffectEventSupported()) + { + this.getServer().getPluginManager().registerEvents(new EntityPotionEffectEventListener(this), this); + } + for(World world : this.getServer().getWorlds()) { this.getWorldGuardCommunicator().doUnloadChunkFlagCheck(world); diff --git a/Common/src/main/java/net/goldtreeservers/worldguardextraflags/listeners/EntityPotionEffectEventListener.java b/Common/src/main/java/net/goldtreeservers/worldguardextraflags/listeners/EntityPotionEffectEventListener.java new file mode 100644 index 0000000..ad1a205 --- /dev/null +++ b/Common/src/main/java/net/goldtreeservers/worldguardextraflags/listeners/EntityPotionEffectEventListener.java @@ -0,0 +1,61 @@ +package net.goldtreeservers.worldguardextraflags.listeners; + +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityPotionEffectEvent; + +import com.sk89q.worldguard.session.Session; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import net.goldtreeservers.worldguardextraflags.WorldGuardExtraFlagsPlugin; +import net.goldtreeservers.worldguardextraflags.wg.handlers.GiveEffectsFlagHandler; + +@RequiredArgsConstructor +public class EntityPotionEffectEventListener implements Listener +{ + @Getter private final WorldGuardExtraFlagsPlugin plugin; + + @EventHandler(ignoreCancelled = true) + public void onEntityPotionEffectEvent(EntityPotionEffectEvent event) + { + if (event.getAction() != EntityPotionEffectEvent.Action.REMOVED) + { + return; + } + + if (event.getCause() != EntityPotionEffectEvent.Cause.PLUGIN) + { + return; + } + + Entity entity = event.getEntity(); + if (!(entity instanceof Player)) + { + return; + } + + Player player = (Player)entity; + if (!player.isValid()) //Work around, getIfPresent is broken inside WG due to using LocalPlayer as key instead of CacheKey + { + return; + } + + try + { + Session session = WorldGuardExtraFlagsPlugin.getPlugin().getWorldGuardCommunicator().getSessionManager().get(player); + + GiveEffectsFlagHandler giveEffectsHandler = session.getHandler(GiveEffectsFlagHandler.class); + if (giveEffectsHandler.isSupressRemovePotionPacket()) + { + event.setCancelled(true); + } + } + catch(IllegalStateException wgBug) + { + + } + } +} diff --git a/Common/src/main/java/net/goldtreeservers/worldguardextraflags/protocollib/ProtocolLibHelper.java b/Common/src/main/java/net/goldtreeservers/worldguardextraflags/protocollib/ProtocolLibHelper.java new file mode 100644 index 0000000..38a0b58 --- /dev/null +++ b/Common/src/main/java/net/goldtreeservers/worldguardextraflags/protocollib/ProtocolLibHelper.java @@ -0,0 +1,25 @@ +package net.goldtreeservers.worldguardextraflags.protocollib; + +import org.bukkit.plugin.Plugin; + +import com.comphenix.protocol.ProtocolLibrary; + +import lombok.Getter; +import net.goldtreeservers.worldguardextraflags.WorldGuardExtraFlagsPlugin; + +public class ProtocolLibHelper +{ + @Getter private final WorldGuardExtraFlagsPlugin plugin; + @Getter private final Plugin protocolLibPlugin; + + public ProtocolLibHelper(WorldGuardExtraFlagsPlugin plugin, Plugin protocolLibPlugin) + { + this.plugin = plugin; + this.protocolLibPlugin = protocolLibPlugin; + } + + public void onEnable() + { + ProtocolLibrary.getProtocolManager().addPacketListener(new RemoveEffectPacketListener()); + } +} diff --git a/Common/src/main/java/net/goldtreeservers/worldguardextraflags/protocollib/RemoveEffectPacketListener.java b/Common/src/main/java/net/goldtreeservers/worldguardextraflags/protocollib/RemoveEffectPacketListener.java new file mode 100644 index 0000000..5be99c0 --- /dev/null +++ b/Common/src/main/java/net/goldtreeservers/worldguardextraflags/protocollib/RemoveEffectPacketListener.java @@ -0,0 +1,47 @@ +package net.goldtreeservers.worldguardextraflags.protocollib; + +import org.bukkit.entity.Player; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.events.PacketAdapter; +import com.comphenix.protocol.events.PacketEvent; +import com.sk89q.worldguard.session.Session; + +import net.goldtreeservers.worldguardextraflags.WorldGuardExtraFlagsPlugin; +import net.goldtreeservers.worldguardextraflags.wg.handlers.GiveEffectsFlagHandler; + +public class RemoveEffectPacketListener extends PacketAdapter +{ + public RemoveEffectPacketListener() + { + super(WorldGuardExtraFlagsPlugin.getPlugin(), PacketType.Play.Server.REMOVE_ENTITY_EFFECT); + } + + @Override + public void onPacketSending(PacketEvent event) + { + if (!event.isCancelled()) + { + Player player = event.getPlayer(); + if (!player.isValid()) //Work around, getIfPresent is broken inside WG due to using LocalPlayer as key instead of CacheKey + { + return; + } + + try + { + Session session = WorldGuardExtraFlagsPlugin.getPlugin().getWorldGuardCommunicator().getSessionManager().get(player); + + GiveEffectsFlagHandler giveEffectsHandler = session.getHandler(GiveEffectsFlagHandler.class); + if (giveEffectsHandler.isSupressRemovePotionPacket()) + { + event.setCancelled(true); + } + } + catch(IllegalStateException wgBug) + { + + } + } + } +} diff --git a/Common/src/main/java/net/goldtreeservers/worldguardextraflags/utils/SupportedFeatures.java b/Common/src/main/java/net/goldtreeservers/worldguardextraflags/utils/SupportedFeatures.java index 5557333..e5fe541 100644 --- a/Common/src/main/java/net/goldtreeservers/worldguardextraflags/utils/SupportedFeatures.java +++ b/Common/src/main/java/net/goldtreeservers/worldguardextraflags/utils/SupportedFeatures.java @@ -4,6 +4,7 @@ import java.awt.Color; import org.bukkit.Material; import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityPotionEffectEvent; import lombok.Getter; @@ -14,6 +15,7 @@ public class SupportedFeatures { @Getter private static boolean frostwalkerSupported; @Getter private static boolean stopSoundSupported; + @Getter private static boolean potionEffectEventSupported; static { @@ -32,5 +34,13 @@ public class SupportedFeatures catch (Throwable ignored) { } + + try + { + SupportedFeatures.potionEffectEventSupported = EntityPotionEffectEvent.class != null; + } + catch (Throwable ignored) + { + } } } diff --git a/Common/src/main/java/net/goldtreeservers/worldguardextraflags/wg/handlers/GiveEffectsFlagHandler.java b/Common/src/main/java/net/goldtreeservers/worldguardextraflags/wg/handlers/GiveEffectsFlagHandler.java index 488f5ca..4e90070 100644 --- a/Common/src/main/java/net/goldtreeservers/worldguardextraflags/wg/handlers/GiveEffectsFlagHandler.java +++ b/Common/src/main/java/net/goldtreeservers/worldguardextraflags/wg/handlers/GiveEffectsFlagHandler.java @@ -20,6 +20,7 @@ import com.sk89q.worldguard.session.MoveType; import com.sk89q.worldguard.session.Session; import com.sk89q.worldguard.session.handler.Handler; +import lombok.Getter; import net.goldtreeservers.worldguardextraflags.WorldGuardExtraFlagsPlugin; import net.goldtreeservers.worldguardextraflags.flags.Flags; import net.goldtreeservers.worldguardextraflags.flags.data.PotionEffectDetails; @@ -41,6 +42,8 @@ public class GiveEffectsFlagHandler extends HandlerWrapper private Map removedEffects; private Set givenEffects; + @Getter private boolean supressRemovePotionPacket; + protected GiveEffectsFlagHandler(Session session) { super(session); @@ -72,28 +75,39 @@ public class GiveEffectsFlagHandler extends HandlerWrapper private void check(Player player, ApplicableRegionSet set) { Set potionEffects = WorldGuardUtils.queryValue(player, player.getWorld(), set.getRegions(), Flags.GIVE_EFFECTS); + + if (potionEffects != null && potionEffects.size() > 0) { - for (PotionEffect effect : potionEffects) + this.supressRemovePotionPacket = true; + + try { - PotionEffect effect_ = null; - for(PotionEffect activeEffect : player.getActivePotionEffects()) + for (PotionEffect effect : potionEffects) { - if (activeEffect.getType().equals(effect.getType())) + PotionEffect effect_ = null; + for(PotionEffect activeEffect : player.getActivePotionEffects()) { - effect_ = activeEffect; - break; + if (activeEffect.getType().equals(effect.getType())) + { + effect_ = activeEffect; + break; + } + } + + if (this.givenEffects.add(effect.getType()) && effect_ != null) + { + this.removedEffects.put(effect_.getType(), new PotionEffectDetails(System.nanoTime() + (long)(effect_.getDuration() / 20D * TimeUnit.SECONDS.toNanos(1L)), effect_.getAmplifier(), effect_.isAmbient(), effect_.hasParticles())); + + player.removePotionEffect(effect_.getType()); } - } - - if (this.givenEffects.add(effect.getType()) && effect_ != null) - { - this.removedEffects.put(effect_.getType(), new PotionEffectDetails(System.nanoTime() + (long)(effect_.getDuration() / 20D * TimeUnit.SECONDS.toNanos(1L)), effect_.getAmplifier(), effect_.isAmbient(), effect_.hasParticles())); - player.removePotionEffect(effect_.getType()); + player.addPotionEffect(effect, true); } - - player.addPotionEffect(effect, true); + } + finally + { + this.supressRemovePotionPacket = false; } } diff --git a/Spigot/src/main/resources/plugin.yml b/Spigot/src/main/resources/plugin.yml index ac05f59..4b9393d 100644 --- a/Spigot/src/main/resources/plugin.yml +++ b/Spigot/src/main/resources/plugin.yml @@ -1,9 +1,9 @@ name: WorldGuardExtraFlags -version: 4.1.1 +version: 4.1.2-DEV description: Adds more flags to WorldGuard to help manage your server easily! author: isokissa3 website: https://goldtreevers.net depend: [ WorldGuard ] -softdepend: [ MythicMobs, FastAsyncWorldEdit, Essentials ] +softdepend: [ MythicMobs, FastAsyncWorldEdit, Essentials, ProtocolLib ] main: net.goldtreeservers.worldguardextraflags.WorldGuardExtraFlagsPlugin \ No newline at end of file