Add item pickup functionality

This commit is contained in:
filoghost 2021-07-31 17:27:21 +02:00
parent 089d1eaa7c
commit 54d089bf04
3 changed files with 98 additions and 2 deletions

View File

@ -0,0 +1,75 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.plugin.hologram.tracking;
import org.bukkit.Location;
import org.bukkit.entity.Player;
public class CollisionHelper {
private static final double PLAYER_WIDTH_RADIUS = 0.6 / 2;
private static final double PLAYER_HEIGHT_RADIUS = 1.8 / 2;
private static final double ITEM_WIDTH_RADIUS = 0.25 / 2;
private static final double ITEM_HEIGHT_RADIUS = 0.25 / 2;
// The server increases the player's bounding box in all directions before checking if it intersects with an item
private static final double PLAYER_GROW_WIDTH = 1;
private static final double PLAYER_GROW_HEIGHT = 0.5;
private static final double REQUIRED_DISTANCE_X = PLAYER_WIDTH_RADIUS + PLAYER_GROW_WIDTH + ITEM_WIDTH_RADIUS;
private static final double REQUIRED_DISTANCE_Z = REQUIRED_DISTANCE_X;
private static final double REQUIRED_DISTANCE_Y = PLAYER_HEIGHT_RADIUS + PLAYER_GROW_HEIGHT + ITEM_HEIGHT_RADIUS;
public static boolean isInPickupRange(Player player, double itemX, double itemY, double itemZ) {
/*
* Normally, the server determines if a player is picking up a dropped item
* by checking if the bounding boxes of the player and the item intersect.
*
* This can be simplified: for each direction (X, Y, Z), check if the distance between the centers of the bounding boxes
* is lower than the sum of the radius (half the length) of each box.
*
* If the condition is satisfied for all directions, the bounding boxes intersect. Visual example:
*
* Box #1
* ._____________.
* | |
* | | Box #2
* | * .___|_______________.
* | | | |
* |_________|___| * |
* | |
* |___________________|
*
* *------>
* Radius #1
*
* <---------*
* Radius #2
*
* *------------*
* Distance between centers
*
*
* In the example above, the distance between the centers is lower than the sum of the two radii,
* so the boxes collide in that direction.
*/
Location playerLocation = player.getLocation();
// The Y position is on lowest point of the bounding box, not in the center
double playerCenterY = playerLocation.getY() + PLAYER_HEIGHT_RADIUS;
double itemCenterY = itemY + ITEM_HEIGHT_RADIUS;
double xDiff = Math.abs(playerLocation.getX() - itemX);
double zDiff = Math.abs(playerLocation.getZ() - itemZ);
double yDiff = Math.abs(playerCenterY - itemCenterY);
return xDiff <= REQUIRED_DISTANCE_X
&& yDiff <= REQUIRED_DISTANCE_Y
&& zDiff <= REQUIRED_DISTANCE_Z;
}
}

View File

@ -9,9 +9,11 @@ import me.filoghost.holographicdisplays.common.nms.EntityID;
import me.filoghost.holographicdisplays.common.nms.NMSManager;
import me.filoghost.holographicdisplays.common.nms.NMSPacketList;
import me.filoghost.holographicdisplays.plugin.hologram.base.BaseItemLine;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.MustBeInvokedByOverriders;
import java.util.Collection;
import java.util.Objects;
public class ItemLineTracker extends ClickableLineTracker<BaseItemLine> {
@ -31,6 +33,20 @@ public class ItemLineTracker extends ClickableLineTracker<BaseItemLine> {
this.itemEntityID = nmsManager.newEntityID();
}
@MustBeInvokedByOverriders
@Override
protected void update(Collection<? extends Player> onlinePlayers) {
super.update(onlinePlayers);
if (spawnItemEntities && hasTrackedPlayers()) {
for (Player trackedPlayer : getTrackedPlayers()) {
if (CollisionHelper.isInPickupRange(trackedPlayer, locationX, locationY, locationZ)) {
line.onPickup(trackedPlayer);
}
}
}
}
@Override
protected boolean updatePlaceholders() {
return false;

View File

@ -46,7 +46,8 @@ public abstract class LineTracker<T extends BaseHologramLine> {
lineChanged = true;
}
protected final void update(Collection<? extends Player> onlinePlayers) {
@MustBeInvokedByOverriders
protected void update(Collection<? extends Player> onlinePlayers) {
boolean sendChangesPackets = false;
// First, detect the changes if the flag is on and set it off
@ -115,10 +116,14 @@ public abstract class LineTracker<T extends BaseHologramLine> {
protected abstract boolean shouldTrackPlayer(Player player);
private boolean hasTrackedPlayers() {
protected final boolean hasTrackedPlayers() {
return !trackedPlayers.isEmpty();
}
protected final Set<Player> getTrackedPlayers() {
return trackedPlayers;
}
public final boolean isTrackedPlayer(Player player) {
return trackedPlayers.contains(player);
}