Merge pull request #442 from RinesThaix/bbCaching

Fixing BoundingBoxes caching
This commit is contained in:
TheMode 2021-08-31 15:19:51 +02:00 committed by GitHub
commit 2c0cd4ff7a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -7,7 +7,9 @@ import net.minestom.server.entity.Entity;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier; import java.util.function.Supplier;
/** /**
@ -18,13 +20,42 @@ public class BoundingBox {
private final Entity entity; private final Entity entity;
private final double x, y, z; private final double x, y, z;
private volatile Pos lastPosition; private final CachedFace bottomFace = new CachedFace(() -> List.of(
private List<Vec> bottomFace; new Vec(getMinX(), getMinY(), getMinZ()),
private List<Vec> topFace; new Vec(getMaxX(), getMinY(), getMinZ()),
private List<Vec> leftFace; new Vec(getMaxX(), getMinY(), getMaxZ()),
private List<Vec> rightFace; new Vec(getMinX(), getMinY(), getMaxZ())
private List<Vec> frontFace; ));
private List<Vec> backFace; private final CachedFace topFace = new CachedFace(() -> List.of(
new Vec(getMinX(), getMaxY(), getMinZ()),
new Vec(getMaxX(), getMaxY(), getMinZ()),
new Vec(getMaxX(), getMaxY(), getMaxZ()),
new Vec(getMinX(), getMaxY(), getMaxZ())
));
private final CachedFace leftFace = new CachedFace(() -> List.of(
new Vec(getMinX(), getMinY(), getMinZ()),
new Vec(getMinX(), getMaxY(), getMinZ()),
new Vec(getMinX(), getMaxY(), getMaxZ()),
new Vec(getMinX(), getMinY(), getMaxZ())
));
private final CachedFace rightFace = new CachedFace(() -> List.of(
new Vec(getMaxX(), getMinY(), getMinZ()),
new Vec(getMaxX(), getMaxY(), getMinZ()),
new Vec(getMaxX(), getMaxY(), getMaxZ()),
new Vec(getMaxX(), getMinY(), getMaxZ())
));
private final CachedFace frontFace = new CachedFace(() -> List.of(
new Vec(getMinX(), getMinY(), getMinZ()),
new Vec(getMaxX(), getMinY(), getMinZ()),
new Vec(getMaxX(), getMaxY(), getMinZ()),
new Vec(getMinX(), getMaxY(), getMinZ())
));
private final CachedFace backFace = new CachedFace(() -> List.of(
new Vec(getMinX(), getMinY(), getMaxZ()),
new Vec(getMaxX(), getMinY(), getMaxZ()),
new Vec(getMaxX(), getMaxY(), getMaxZ()),
new Vec(getMinX(), getMaxY(), getMaxZ())
));
/** /**
* Creates a {@link BoundingBox} linked to an {@link Entity} and with a specific size. * Creates a {@link BoundingBox} linked to an {@link Entity} and with a specific size.
@ -320,12 +351,7 @@ public class BoundingBox {
* @return the points at the bottom of the {@link BoundingBox} * @return the points at the bottom of the {@link BoundingBox}
*/ */
public @NotNull List<Vec> getBottomFace() { public @NotNull List<Vec> getBottomFace() {
this.bottomFace = get(bottomFace, () -> return bottomFace.get();
List.of(new Vec(getMinX(), getMinY(), getMinZ()),
new Vec(getMaxX(), getMinY(), getMinZ()),
new Vec(getMaxX(), getMinY(), getMaxZ()),
new Vec(getMinX(), getMinY(), getMaxZ())));
return bottomFace;
} }
/** /**
@ -334,12 +360,7 @@ public class BoundingBox {
* @return the points at the top of the {@link BoundingBox} * @return the points at the top of the {@link BoundingBox}
*/ */
public @NotNull List<Vec> getTopFace() { public @NotNull List<Vec> getTopFace() {
this.topFace = get(topFace, () -> return topFace.get();
List.of(new Vec(getMinX(), getMaxY(), getMinZ()),
new Vec(getMaxX(), getMaxY(), getMinZ()),
new Vec(getMaxX(), getMaxY(), getMaxZ()),
new Vec(getMinX(), getMaxY(), getMaxZ())));
return topFace;
} }
/** /**
@ -348,12 +369,7 @@ public class BoundingBox {
* @return the points on the left face of the {@link BoundingBox} * @return the points on the left face of the {@link BoundingBox}
*/ */
public @NotNull List<Vec> getLeftFace() { public @NotNull List<Vec> getLeftFace() {
this.leftFace = get(leftFace, () -> return leftFace.get();
List.of(new Vec(getMinX(), getMinY(), getMinZ()),
new Vec(getMinX(), getMaxY(), getMinZ()),
new Vec(getMinX(), getMaxY(), getMaxZ()),
new Vec(getMinX(), getMinY(), getMaxZ())));
return leftFace;
} }
/** /**
@ -362,12 +378,7 @@ public class BoundingBox {
* @return the points on the right face of the {@link BoundingBox} * @return the points on the right face of the {@link BoundingBox}
*/ */
public @NotNull List<Vec> getRightFace() { public @NotNull List<Vec> getRightFace() {
this.rightFace = get(rightFace, () -> return rightFace.get();
List.of(new Vec(getMaxX(), getMinY(), getMinZ()),
new Vec(getMaxX(), getMaxY(), getMinZ()),
new Vec(getMaxX(), getMaxY(), getMaxZ()),
new Vec(getMaxX(), getMinY(), getMaxZ())));
return rightFace;
} }
/** /**
@ -376,12 +387,7 @@ public class BoundingBox {
* @return the points at the front of the {@link BoundingBox} * @return the points at the front of the {@link BoundingBox}
*/ */
public @NotNull List<Vec> getFrontFace() { public @NotNull List<Vec> getFrontFace() {
this.frontFace = get(frontFace, () -> return frontFace.get();
List.of(new Vec(getMinX(), getMinY(), getMinZ()),
new Vec(getMaxX(), getMinY(), getMinZ()),
new Vec(getMaxX(), getMaxY(), getMinZ()),
new Vec(getMinX(), getMaxY(), getMinZ())));
return frontFace;
} }
/** /**
@ -390,12 +396,7 @@ public class BoundingBox {
* @return the points at the back of the {@link BoundingBox} * @return the points at the back of the {@link BoundingBox}
*/ */
public @NotNull List<Vec> getBackFace() { public @NotNull List<Vec> getBackFace() {
this.backFace = get(backFace, () -> List.of( return backFace.get();
new Vec(getMinX(), getMinY(), getMaxZ()),
new Vec(getMaxX(), getMinY(), getMaxZ()),
new Vec(getMaxX(), getMaxY(), getMaxZ()),
new Vec(getMinX(), getMaxY(), getMaxZ())));
return backFace;
} }
@Override @Override
@ -410,18 +411,42 @@ public class BoundingBox {
return result; return result;
} }
private @NotNull List<Vec> get(@Nullable List<Vec> face, Supplier<? extends List<Vec>> vecSupplier) {
final var lastPos = this.lastPosition;
final var entityPos = entity.getPosition();
if (face != null && lastPos != null && lastPos.samePoint(entityPos)) {
return face;
}
this.lastPosition = entityPos;
return vecSupplier.get();
}
private enum Axis { private enum Axis {
X, Y, Z X, Y, Z
} }
private class CachedFace {
private final AtomicReference<@Nullable PositionedPoints> reference = new AtomicReference<>(null);
private final Supplier<@NotNull List<Vec>> faceProducer;
private CachedFace(Supplier<@NotNull List<Vec>> faceProducer) {
this.faceProducer = faceProducer;
}
@NotNull List<Vec> get() {
//noinspection ConstantConditions
return reference.updateAndGet(value -> {
Pos entityPosition = entity.getPosition();
if (value == null || !value.lastPosition.samePoint(entityPosition)) {
return new PositionedPoints(entityPosition, faceProducer.get());
}
return value;
}).points;
}
}
private static class PositionedPoints {
private final @NotNull Pos lastPosition;
private final @NotNull List<Vec> points;
private PositionedPoints(@NotNull Pos lastPosition, @NotNull List<Vec> points) {
this.lastPosition = lastPosition;
this.points = points;
}
}
} }