From ca1ba4f42278915473a14f10277ff1ef08ab67cb Mon Sep 17 00:00:00 2001 From: KennyTV <28825609+KennyTV@users.noreply.github.com> Date: Sun, 19 May 2019 23:28:05 +0200 Subject: [PATCH 1/3] Fix suffocation damage for 1.14+ players in hitbox patch --- .../multiversion/PlayerSneakListener.java | 47 ++++++++++++++----- .../bukkit/platform/BukkitViaLoader.java | 2 +- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/multiversion/PlayerSneakListener.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/multiversion/PlayerSneakListener.java index 993cd8f14..30dacd545 100644 --- a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/multiversion/PlayerSneakListener.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/multiversion/PlayerSneakListener.java @@ -1,7 +1,9 @@ package us.myles.ViaVersion.bukkit.listeners.multiversion; +import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerToggleSneakEvent; import us.myles.ViaVersion.ViaVersionPlugin; @@ -9,13 +11,11 @@ import us.myles.ViaVersion.api.data.UserConnection; import us.myles.ViaVersion.api.protocol.ProtocolRegistry; import us.myles.ViaVersion.api.protocol.ProtocolVersion; import us.myles.ViaVersion.bukkit.listeners.ViaBukkitListener; -import us.myles.ViaVersion.bukkit.platform.BukkitViaLoader; import us.myles.ViaVersion.protocols.base.ProtocolInfo; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; +import java.util.*; public class PlayerSneakListener extends ViaBukkitListener { private static final float STANDING_HEIGHT = 1.8F; @@ -24,13 +24,14 @@ public class PlayerSneakListener extends ViaBukkitListener { private static final float DEFAULT_WIDTH = 0.6F; private Map sneaking; // true = 1.14+, else false + private Set sneakingUuids; private Method getHandle; private Method setSize; private boolean is1_9Fix; private boolean is1_14Fix; private boolean useCache; - public PlayerSneakListener(ViaVersionPlugin plugin, BukkitViaLoader viaLoader, boolean is1_9Fix, boolean is1_14Fix) { + public PlayerSneakListener(ViaVersionPlugin plugin, boolean is1_9Fix, boolean is1_14Fix) { super(plugin, null); this.is1_9Fix = is1_9Fix; this.is1_14Fix = is1_14Fix; @@ -41,16 +42,11 @@ public class PlayerSneakListener extends ViaBukkitListener { } catch (ClassNotFoundException | NoSuchMethodException e) { e.printStackTrace(); } + // From 1.9 upwards the server hitbox is set in every entity tick, so we have to reset it everytime if (ProtocolRegistry.SERVER_PROTOCOL >= ProtocolVersion.v1_9.getId()) { sneaking = new HashMap<>(); useCache = true; - viaLoader.storeListener(new ViaBukkitListener(plugin, null) { - @EventHandler - public void playerQuit(PlayerQuitEvent event) { - sneaking.remove(event.getPlayer()); - } - }).register(); plugin.getServer().getScheduler().runTaskTimer(plugin, new Runnable() { @Override public void run() { @@ -60,6 +56,11 @@ public class PlayerSneakListener extends ViaBukkitListener { } }, 1, 1); } + + // Suffocation removal only required for 1.14+ clients. + if (is1_14Fix) { + sneakingUuids = new HashSet<>(); + } } @EventHandler(ignoreCancelled = true) @@ -73,6 +74,11 @@ public class PlayerSneakListener extends ViaBukkitListener { int protocolVersion = info.getProtocolVersion(); if (is1_14Fix && protocolVersion >= ProtocolVersion.v1_14.getId()) { setHeight(player, event.isSneaking() ? HEIGHT_1_14 : STANDING_HEIGHT); + if (event.isSneaking()) + sneakingUuids.add(player.getUniqueId()); + else + sneakingUuids.remove(player.getUniqueId()); + if (!useCache) return; if (event.isSneaking()) sneaking.put(player, true); @@ -88,6 +94,25 @@ public class PlayerSneakListener extends ViaBukkitListener { } } + @EventHandler(ignoreCancelled = true) + public void playerDamage(EntityDamageEvent event) { + if (!is1_14Fix) return; + if (event.getCause() != EntityDamageEvent.DamageCause.SUFFOCATION) return; + if (event.getEntityType() != EntityType.PLAYER) return; + + Player player = (Player) event.getEntity(); + if (!sneakingUuids.contains(player.getUniqueId())) return; + event.setCancelled(true); + } + + @EventHandler + public void playerQuit(PlayerQuitEvent event) { + if (sneaking != null) + sneaking.remove(event.getPlayer()); + if (sneakingUuids != null) + sneakingUuids.remove(event.getPlayer().getUniqueId()); + } + private void setHeight(Player player, float height) { try { setSize.invoke(getHandle.invoke(player), DEFAULT_WIDTH, height); @@ -95,4 +120,4 @@ public class PlayerSneakListener extends ViaBukkitListener { e.printStackTrace(); } } -} +} \ No newline at end of file diff --git a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaLoader.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaLoader.java index ca5fc776f..b2e3e82e8 100644 --- a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaLoader.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaLoader.java @@ -82,7 +82,7 @@ public class BukkitViaLoader implements ViaPlatformLoader { if (ProtocolRegistry.SERVER_PROTOCOL < ProtocolVersion.v1_14.getId()) { boolean use1_9Fix = plugin.getConf().is1_9HitboxFix() && ProtocolRegistry.SERVER_PROTOCOL < ProtocolVersion.v1_9.getId(); if (use1_9Fix || plugin.getConf().is1_14HitboxFix()) { - storeListener(new PlayerSneakListener(plugin, this, use1_9Fix, plugin.getConf().is1_14HitboxFix())).register(); + storeListener(new PlayerSneakListener(plugin, use1_9Fix, plugin.getConf().is1_14HitboxFix())).register(); } } From 5cc421cff9fa6c52984b77606f5a9762eea62b94 Mon Sep 17 00:00:00 2001 From: KennyTV <28825609+KennyTV@users.noreply.github.com> Date: Mon, 20 May 2019 10:30:42 +0200 Subject: [PATCH 2/3] Don't cancel normal suffocation --- .../listeners/multiversion/PlayerSneakListener.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/multiversion/PlayerSneakListener.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/multiversion/PlayerSneakListener.java index 30dacd545..e756a116b 100644 --- a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/multiversion/PlayerSneakListener.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/multiversion/PlayerSneakListener.java @@ -102,7 +102,14 @@ public class PlayerSneakListener extends ViaBukkitListener { Player player = (Player) event.getEntity(); if (!sneakingUuids.contains(player.getUniqueId())) return; - event.setCancelled(true); + + // Don't cancel when they should actually be suffocating; Essentially cancel when the head is in the top block only ever so slightly + // ~0.041 should suffice, but gotta stay be safe + double y = player.getEyeLocation().getY() + 0.045; + y -= (int) y; + if (y < 0.09) { + event.setCancelled(true); + } } @EventHandler From 10d8ce86b371cb9f34ef56ae4d16ec84ade012a8 Mon Sep 17 00:00:00 2001 From: KennyTV <28825609+KennyTV@users.noreply.github.com> Date: Tue, 21 May 2019 19:02:03 +0200 Subject: [PATCH 3/3] Use weakhashmap --- .../bukkit/listeners/multiversion/PlayerSneakListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/multiversion/PlayerSneakListener.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/multiversion/PlayerSneakListener.java index e756a116b..a44dc1e74 100644 --- a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/multiversion/PlayerSneakListener.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/multiversion/PlayerSneakListener.java @@ -45,7 +45,7 @@ public class PlayerSneakListener extends ViaBukkitListener { // From 1.9 upwards the server hitbox is set in every entity tick, so we have to reset it everytime if (ProtocolRegistry.SERVER_PROTOCOL >= ProtocolVersion.v1_9.getId()) { - sneaking = new HashMap<>(); + sneaking = new WeakHashMap<>(); useCache = true; plugin.getServer().getScheduler().runTaskTimer(plugin, new Runnable() { @Override