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
This commit is contained in:
isokissa3 2018-11-30 22:14:37 +02:00
parent 56e6dc83a0
commit eb6b63b63f
8 changed files with 208 additions and 16 deletions

View file

@ -26,6 +26,10 @@
<id>empcraft</id>
<url>http://ci.athion.net/job/FastAsyncWorldEdit/ws/mvn/</url>
</repository>
<repository>
<id>dmulloy2-repo</id>
<url>http://repo.dmulloy2.net/nexus/repository/public/</url>
</repository>
</repositories>
@ -79,5 +83,10 @@
<version>2.13-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib-API</artifactId>
<version>4.4.0</version>
</dependency>
</dependencies>
</project>

View file

@ -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);

View file

@ -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)
{
}
}
}

View file

@ -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());
}
}

View file

@ -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)
{
}
}
}
}

View file

@ -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)
{
}
}
}

View file

@ -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<PotionEffectType, PotionEffectDetails> removedEffects;
private Set<PotionEffectType> 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<PotionEffect> 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;
}
}

View file

@ -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