diff --git a/src/main/java/net/minestom/server/ServerFlag.java b/src/main/java/net/minestom/server/ServerFlag.java index f951facb4f3..4f5bd6cf47a 100644 --- a/src/main/java/net/minestom/server/ServerFlag.java +++ b/src/main/java/net/minestom/server/ServerFlag.java @@ -27,6 +27,7 @@ public final class ServerFlag { public static final int POOLED_BUFFER_SIZE = intProperty("minestom.pooled-buffer-size", 262_143); public static final int SEND_LIGHT_AFTER_BLOCK_PLACEMENT_DELAY = intProperty("minestom.send-light-after-block-placement-delay", 100); public static final long LOGIN_PLUGIN_MESSAGE_TIMEOUT = longProperty("minestom.login-plugin-message-timeout", 5_000); + public static final int EXPLOSION_SEND_DISTANCE = intProperty("minestom.explosion-send-distance", 100); public static final int SERVER_LINK_AMOUNT = intProperty("minestom.server-link-amount", 100); // Network rate limiting diff --git a/src/main/java/net/minestom/server/instance/Explosion.java b/src/main/java/net/minestom/server/instance/Explosion.java index c96f8c45a0b..1a5467cce1f 100644 --- a/src/main/java/net/minestom/server/instance/Explosion.java +++ b/src/main/java/net/minestom/server/instance/Explosion.java @@ -1,6 +1,9 @@ package net.minestom.server.instance; +import net.minestom.server.ServerFlag; import net.minestom.server.coordinate.Point; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.entity.Player; import net.minestom.server.instance.block.Block; import net.minestom.server.network.packet.server.play.ExplosionPacket; import net.minestom.server.utils.PacketUtils; @@ -69,11 +72,14 @@ public void apply(@NotNull Instance instance) { records[i * 3 + 2] = z; } - // TODO send only to close players ExplosionPacket packet = new ExplosionPacket(centerX, centerY, centerZ, strength, records, 0, 0, 0); postExplosion(instance, blocks, packet); - PacketUtils.sendGroupedPacket(instance.getPlayers(), packet); + List players = instance.getNearbyEntities(new Pos(centerX, centerY, centerZ), ServerFlag.EXPLOSION_SEND_DISTANCE) + .stream() + .filter(Player.class::isInstance) + .map(Player.class::cast).toList(); + PacketUtils.sendGroupedPacket(players, packet); postSend(instance, blocks); } diff --git a/src/test/java/net/minestom/server/instance/ExplosionIntegrationTest.java b/src/test/java/net/minestom/server/instance/ExplosionIntegrationTest.java new file mode 100644 index 00000000000..7e76f0b9abd --- /dev/null +++ b/src/test/java/net/minestom/server/instance/ExplosionIntegrationTest.java @@ -0,0 +1,62 @@ +package net.minestom.server.instance; + +import net.kyori.adventure.nbt.CompoundBinaryTag; +import net.minestom.server.coordinate.Point; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.network.packet.server.play.ExplosionPacket; +import net.minestom.testing.Env; +import net.minestom.testing.extension.MicrotusExtension; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import java.util.List; + + +@ExtendWith(MicrotusExtension.class) +class ExplosionIntegrationTest { + + // Checks that only nearby players actually receive the packet from the server + @Test + void sendToNearbyPlayers(Env env) { + var instance = env.createFlatInstance(); + instance.setExplosionSupplier(new TestExplosionSupplierImpl()); + + var connection1 = env.createConnection(); + var connection2 = env.createConnection(); + var connection3 = env.createConnection(); + + // Assumes that the default ServerFlag.EXPLOSION_SEND_DISTANCE is set to 100 blocks + var player1 = connection1.connect(instance, new Pos(0, 41, 0)); + var player2 = connection2.connect(instance, new Pos(50, 41, 0)); + var player3 = connection3.connect(instance, new Pos(0, 41, 110)); + + var packetTracker1 = connection1.trackIncoming(ExplosionPacket.class); + var packetTracker2 = connection2.trackIncoming(ExplosionPacket.class); + var packetTracker3 = connection3.trackIncoming(ExplosionPacket.class); + + instance.explode(0, 41, 0, 1); + packetTracker1.assertSingle(); + packetTracker2.assertSingle(); + packetTracker3.assertEmpty(); + env.destroyInstance(instance, true); + } + + + class TestExplosionSupplierImpl implements ExplosionSupplier { + @Override + public Explosion createExplosion(float centerX, float centerY, float centerZ, float strength, CompoundBinaryTag additionalData) { + return new TestExplosionImpl(centerX, centerY, centerZ, strength); + } + + class TestExplosionImpl extends Explosion { + + TestExplosionImpl(float centerX, float centerY, float centerZ, float strength) { + super(centerX, centerY, centerZ, strength); + } + @Override + protected List prepare(Instance instance) { + return List.of(new Pos(getCenterX(), getCenterY(), getCenterZ())); + } + } + } + +}