mirror of
https://github.com/filoghost/HolographicDisplays.git
synced 2025-02-22 06:51:20 +01:00
Add item pickup functionality
This commit is contained in:
parent
089d1eaa7c
commit
54d089bf04
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user