/* * This file is a part of the SteamWar software. * * Copyright (C) 2022 SteamWar.de-Serverteam * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package de.steamwar.bausystem.utils; import lombok.experimental.UtilityClass; import org.bukkit.FluidCollisionMode; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.util.BoundingBox; import org.bukkit.util.RayTraceResult; import org.bukkit.util.Vector; import java.util.List; @UtilityClass public class RayTraceUtils { public static RayTraceResult trace(Player player, Location to, List entityList) { if (player.getGameMode() == GameMode.SPECTATOR) { return null; } Location startPos = to.clone().add(0.0, player.getEyeHeight(), 0.0); Vector direction = to.getDirection(); RayTraceResult blocks = player.getWorld().rayTraceBlocks(startPos, direction, 10.0, FluidCollisionMode.NEVER, true); Entity nearestHitEntity = null; RayTraceResult nearestHitResult = null; double nearestDistanceSq = Double.MAX_VALUE; for (Entity entity : entityList) { BoundingBox boundingBox = entity.getBoundingBox(); RayTraceResult hitResult = boundingBox.rayTrace(startPos.toVector(), direction, 10.0); if (hitResult != null) { double distanceSq = startPos.toVector().distanceSquared(hitResult.getHitPosition()); if (distanceSq < nearestDistanceSq) { nearestHitEntity = entity; nearestHitResult = hitResult; nearestDistanceSq = distanceSq; } } } RayTraceResult entities = nearestHitEntity == null ? null : new RayTraceResult(nearestHitResult.getHitPosition(), nearestHitEntity, nearestHitResult.getHitBlockFace()); if (blocks == null) { return entities; } else if (entities == null) { return blocks; } else { Vector startVec = startPos.toVector(); double blockHitDistance = startVec.distance(blocks.getHitPosition()); double entityHitDistanceSquared = startVec.distanceSquared(entities.getHitPosition()); return entityHitDistanceSquared < blockHitDistance * blockHitDistance ? entities : blocks; } } }