Merge branch 'Minestom:master' into instance-based-threading

This commit is contained in:
Leon 2025-01-05 16:41:59 +00:00 committed by GitHub
commit 97dc3713fe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 147 additions and 7 deletions

View File

@ -21,11 +21,11 @@ public record BoundingBox(Vec relativeStart, Vec relativeEnd) implements Shape {
final static BoundingBox ZERO = new BoundingBox(Vec.ZERO, Vec.ZERO);
public BoundingBox(double width, double height, double depth, Point offset) {
this(new Vec(-width / 2.0, 0.0, -depth / 2.0).add(offset), new Vec(width / 2.0, height, depth / 2.0).add(offset));
this(Vec.fromPoint(offset), new Vec(width, height, depth).add(offset));
}
public BoundingBox(double width, double height, double depth) {
this(width, height, depth, Vec.ZERO);
this(width, height, depth, new Vec(-width / 2, 0, -depth / 2));
}
@Override

View File

@ -33,7 +33,7 @@ final class BlockLight implements Light {
ShortArrayFIFOQueue lightSources = new ShortArrayFIFOQueue();
// Apply section light
blockPalette.getAllPresent((x, y, z, stateId) -> {
final Block block = Block.fromStateId((short) stateId);
final Block block = Block.fromStateId(stateId);
assert block != null;
final byte lightEmission = (byte) block.registry().lightEmission();

View File

@ -112,7 +112,7 @@ public final class LightCompute {
}
public static Block getBlock(Palette palette, int x, int y, int z) {
return Block.fromStateId((short) palette.get(x, y, z));
return Block.fromStateId(palette.get(x, y, z));
}
public static byte[] bake(byte[] content1, byte[] content2) {

View File

@ -1,7 +1,9 @@
package net.minestom.server.listener;
import net.minestom.server.ServerFlag;
import net.minestom.server.collision.BoundingBox;
import net.minestom.server.coordinate.Point;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.coordinate.Vec;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.LivingEntity;
@ -20,8 +22,11 @@ public class UseEntityListener {
return;
if (ServerFlag.ENFORCE_INTERACTION_LIMIT) {
double range = Math.pow(player.getAttributeValue(Attribute.ENTITY_INTERACTION_RANGE) + 1, 2); // Add 1 additional block for people with less than stellar ping
if (player.getDistanceSquared(entity) > range) {
final double maxDistanceSquared = Math.pow(player.getAttributeValue(Attribute.ENTITY_INTERACTION_RANGE) + 1, 2);
final double distSquared = getDistSquared(player, entity);
if (distSquared > maxDistanceSquared) {
return;
}
}
@ -36,4 +41,33 @@ public class UseEntityListener {
EventDispatcher.call(new PlayerEntityInteractEvent(player, entity, interactAt.hand(), interactPosition));
}
}
}
private static double getDistSquared(Player player, Entity entity) {
final Pos playerPos = player.getPosition();
final double eyeHeight = player.getEyeHeight();
final double px = playerPos.x();
final double py = playerPos.y() + eyeHeight;
final double pz = playerPos.z();
final BoundingBox box = entity.getBoundingBox();
final double halfWidth = box.width() / 2;
final double height = box.height();
final Pos entityPos = entity.getPosition();
final double minX = entityPos.x() - halfWidth;
final double maxX = entityPos.x() + halfWidth;
final double minY = entityPos.y();
final double maxY = entityPos.y() + height;
final double minZ = entityPos.z() - halfWidth;
final double maxZ = entityPos.z() + halfWidth;
final double clampX = Math.max(minX, Math.min(px, maxX));
final double clampY = Math.max(minY, Math.min(py, maxY));
final double clampZ = Math.max(minZ, Math.min(pz, maxZ));
final double dx = px - clampX;
final double dy = py - clampY;
final double dz = pz - clampZ;
return dx * dx + dy * dy + dz * dz;
}
}

View File

@ -0,0 +1,106 @@
package net.minestom.server.listener;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.EntityType;
import net.minestom.server.entity.Player;
import net.minestom.server.entity.PlayerHand;
import net.minestom.server.entity.attribute.Attribute;
import net.minestom.server.event.player.PlayerEntityInteractEvent;
import net.minestom.server.instance.Instance;
import net.minestom.server.network.packet.client.play.ClientInteractEntityPacket;
import net.minestom.testing.Env;
import net.minestom.testing.EnvTest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
@EnvTest
public class UseEntityListenerTest {
private Player player;
private Entity targetEntity;
private boolean eventWasCalled;
@BeforeEach
public void setup(Env env) {
Instance instance = env.createFlatInstance();
player = env.createPlayer(instance, new Pos(0, 0, 0));
player.getAttribute(Attribute.ENTITY_INTERACTION_RANGE).setBaseValue(5.0);
targetEntity = new Entity(EntityType.SLIME);
targetEntity.setInstance(instance, new Pos(2, 0, 2)).join();
eventWasCalled = false;
player.eventNode().addListener(PlayerEntityInteractEvent.class, event -> {
if (event.getPlayer().equals(player) && event.getTarget().equals(targetEntity)) {
eventWasCalled = true;
}
});
}
@Test
public void testInteractionWithinRange() {
ClientInteractEntityPacket packet = new ClientInteractEntityPacket(
targetEntity.getEntityId(),
new ClientInteractEntityPacket.InteractAt(0, 0, 0, PlayerHand.MAIN),
false
);
UseEntityListener.useEntityListener(packet, player);
assertTrue(eventWasCalled, "Expected PlayerEntityInteractEvent to be called for nearby target");
}
@Test
public void testInteractionOutOfRange() {
player.getAttribute(Attribute.ENTITY_INTERACTION_RANGE).setBaseValue(1.0);
targetEntity.teleport(new Pos(10, 0, 10)).join();
ClientInteractEntityPacket packet = new ClientInteractEntityPacket(
targetEntity.getEntityId(),
new ClientInteractEntityPacket.InteractAt(0, 0, 0, PlayerHand.MAIN),
false
);
eventWasCalled = false;
UseEntityListener.useEntityListener(packet, player);
assertFalse(eventWasCalled, "Expected PlayerEntityInteractEvent NOT to be called for out-of-range target");
}
@Test
public void testInteractionConsideringHitboxAndEyePosition() {
player.getAttribute(Attribute.ENTITY_INTERACTION_RANGE).setBaseValue(1.5);
targetEntity.teleport(new Pos(1.6, 0, 0)).join();
ClientInteractEntityPacket packet = new ClientInteractEntityPacket(
targetEntity.getEntityId(),
new ClientInteractEntityPacket.InteractAt(0, 0, 0, PlayerHand.MAIN),
false
);
eventWasCalled = false;
UseEntityListener.useEntityListener(packet, player);
assertTrue(eventWasCalled, "Expected PlayerEntityInteractEvent to be called considering hitbox size and eye position");
}
@Test
public void testInteractionConsideringEyeHeight() {
player.teleport(new Pos(0, 1.6, 0)).join();
targetEntity.teleport(new Pos(0, 1.6, 2)).join();
ClientInteractEntityPacket packet = new ClientInteractEntityPacket(
targetEntity.getEntityId(),
new ClientInteractEntityPacket.InteractAt(0, 0, 0, PlayerHand.MAIN),
false
);
eventWasCalled = false;
UseEntityListener.useEntityListener(packet, player);
assertTrue(eventWasCalled, "Expected PlayerEntityInteractEvent to be called considering eye height");
}
}