From f5c341bf2e3a268299c88c9fe9726111194e498d Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 15 Sep 2016 22:38:37 +0200 Subject: [PATCH] Fix potion race condition on Forge 1.8.9 diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/AbstractPacketHandler.java b/protocol/src/main/java/net/md_5/bungee/protocol/AbstractPacketHandler.java index 8d91211b..e2221010 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/AbstractPacketHandler.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/AbstractPacketHandler.java @@ -278,4 +278,14 @@ public abstract class AbstractPacketHandler public void handle(ServerLinks serverLinks) throws Exception { } + + // Waterfall start + public void handle(net.md_5.bungee.protocol.packet.EntityEffect entityEffect) throws Exception + { + } + + public void handle(net.md_5.bungee.protocol.packet.EntityRemoveEffect removeEffect) throws Exception + { + } + // Waterfall end } diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/EntityEffect.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/EntityEffect.java new file mode 100644 index 00000000..d11a9ea9 --- /dev/null +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/EntityEffect.java @@ -0,0 +1,45 @@ +package net.md_5.bungee.protocol.packet; + +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import net.md_5.bungee.protocol.AbstractPacketHandler; +import net.md_5.bungee.protocol.DefinedPacket; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class EntityEffect extends DefinedPacket { + + private int entityId; + private int effectId; + private int amplifier; + private int duration; + private boolean hideParticles; + + @Override + public void read(ByteBuf buf) { + this.entityId = readVarInt(buf); + this.effectId = buf.readUnsignedByte(); + this.amplifier = buf.readUnsignedByte(); + this.duration = readVarInt(buf); + this.hideParticles = buf.readBoolean(); + } + + @Override + public void write(ByteBuf buf) { + writeVarInt(this.entityId, buf); + buf.writeByte(this.effectId); + buf.writeByte(this.amplifier); + writeVarInt(this.duration, buf); + buf.writeBoolean(this.hideParticles); + } + + @Override + public void handle(AbstractPacketHandler handler) throws Exception { + handler.handle(this); + } +} diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/EntityRemoveEffect.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/EntityRemoveEffect.java new file mode 100644 index 00000000..7ed2dc3a --- /dev/null +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/EntityRemoveEffect.java @@ -0,0 +1,36 @@ +package net.md_5.bungee.protocol.packet; + +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import net.md_5.bungee.protocol.AbstractPacketHandler; +import net.md_5.bungee.protocol.DefinedPacket; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class EntityRemoveEffect extends DefinedPacket { + + private int entityId; + private int effectId; + + @Override + public void read(ByteBuf buf) { + this.entityId = readVarInt(buf); + this.effectId = buf.readUnsignedByte(); + } + + @Override + public void write(ByteBuf buf) { + writeVarInt(this.entityId, buf); + buf.writeByte(effectId); + } + + @Override + public void handle(AbstractPacketHandler handler) throws Exception { + handler.handle(this); + } +} diff --git a/proxy/src/main/java/net/md_5/bungee/UserConnection.java b/proxy/src/main/java/net/md_5/bungee/UserConnection.java index d8f7bc95..d15f2bcc 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -1,7 +1,9 @@ package net.md_5.bungee; import com.google.common.base.Preconditions; +import com.google.common.collect.HashMultimap; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Multimap; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -129,6 +131,10 @@ public final class UserConnection implements ProxiedPlayer private final Scoreboard serverSentScoreboard = new Scoreboard(); @Getter private final Collection sentBossBars = new HashSet<>(); + // Waterfall start + @Getter + private final Multimap potions = HashMultimap.create(); + // Waterfall end @Getter @Setter private String lastCommandTabbed; diff --git a/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java b/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java index d4036c5d..ad9fc042 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java @@ -753,6 +753,32 @@ public class DownstreamBridge extends PacketHandler } } + // Waterfall start + @Override + public void handle(net.md_5.bungee.protocol.packet.EntityEffect entityEffect) throws Exception + { + // Don't send any potions when switching between servers (which involves a handshake), which can trigger a race + // condition on the client. + if (this.con.getForgeClientHandler().isForgeUser() && !this.con.getForgeClientHandler().isHandshakeComplete()) { + throw CancelSendSignal.INSTANCE; + } + con.getPotions().put(rewriteEntityId(entityEffect.getEntityId()), entityEffect.getEffectId()); + } + + @Override + public void handle(net.md_5.bungee.protocol.packet.EntityRemoveEffect removeEffect) throws Exception + { + con.getPotions().remove(rewriteEntityId(removeEffect.getEntityId()), removeEffect.getEffectId()); + } + + private int rewriteEntityId(int entityId) { + if (entityId == con.getServerEntityId()) { + return con.getClientEntityId(); + } + return entityId; + } + // Waterfall end + @Override public void handle(Respawn respawn) { diff --git a/proxy/src/main/java/net/md_5/bungee/forge/ForgeClientHandler.java b/proxy/src/main/java/net/md_5/bungee/forge/ForgeClientHandler.java index d15044f4..bea2bbff 100644 --- a/proxy/src/main/java/net/md_5/bungee/forge/ForgeClientHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/forge/ForgeClientHandler.java @@ -9,6 +9,8 @@ import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.Setter; import net.md_5.bungee.UserConnection; +import net.md_5.bungee.protocol.ProtocolConstants; +import net.md_5.bungee.protocol.packet.EntityRemoveEffect; import net.md_5.bungee.protocol.packet.PluginMessage; /** @@ -94,9 +96,23 @@ public class ForgeClientHandler public void resetHandshake() { state = ForgeClientHandshakeState.HELLO; + + // This issue only exists in Forge 1.8.9 + if (this.con.getPendingConnection().getVersion() == ProtocolConstants.MINECRAFT_1_8) { + this.resetAllThePotions(con); + } + con.unsafe().sendPacket( ForgeConstants.FML_RESET_HANDSHAKE ); } + private void resetAllThePotions(UserConnection con) { + // Just to be sure + for (Map.Entry entry: con.getPotions().entries()) { + con.unsafe().sendPacket(new EntityRemoveEffect(entry.getKey(), entry.getValue())); + } + con.getPotions().clear(); + } + /** * Sends the server mod list to the client, or stores it for sending later. * -- 2.45.1