2020-09-22 15:11:20 +02:00
|
|
|
package com.minelittlepony.unicopia.projectile;
|
2018-09-12 01:29:49 +02:00
|
|
|
|
2021-08-04 15:38:03 +02:00
|
|
|
import org.jetbrains.annotations.Nullable;
|
2019-02-01 00:07:19 +01:00
|
|
|
|
2021-01-29 17:37:41 +01:00
|
|
|
import com.minelittlepony.unicopia.mixin.MixinPersistentProjectileEntity;
|
|
|
|
|
2018-09-12 01:29:49 +02:00
|
|
|
import net.minecraft.entity.Entity;
|
2020-01-16 12:35:46 +01:00
|
|
|
import net.minecraft.entity.projectile.ProjectileEntity;
|
2019-02-01 00:07:19 +01:00
|
|
|
import net.minecraft.util.math.Vec3d;
|
2018-09-12 01:29:49 +02:00
|
|
|
|
2021-01-29 17:37:41 +01:00
|
|
|
public interface ProjectileUtil {
|
2018-09-12 01:29:49 +02:00
|
|
|
|
2019-02-08 22:39:02 +01:00
|
|
|
/**
|
|
|
|
* Checks if the given entity is a projectile.
|
|
|
|
*/
|
2021-01-29 17:37:41 +01:00
|
|
|
static boolean isProjectile(Entity e) {
|
2020-06-26 11:44:47 +02:00
|
|
|
return e instanceof ProjectileEntity;
|
2019-02-08 22:39:02 +01:00
|
|
|
}
|
|
|
|
|
2021-01-29 17:37:41 +01:00
|
|
|
/**
|
|
|
|
* Checks if the given entity is a projectile that is not stuck in the ground.
|
|
|
|
*/
|
|
|
|
static boolean isFlyingProjectile(Entity e) {
|
|
|
|
return isProjectile(e) && !(e instanceof MixinPersistentProjectileEntity && ((MixinPersistentProjectileEntity)e).isInGround());
|
|
|
|
}
|
|
|
|
|
2019-02-08 22:39:02 +01:00
|
|
|
/**
|
|
|
|
* Checks if the given projectile was thrown by the given entity
|
|
|
|
*/
|
2021-01-29 17:37:41 +01:00
|
|
|
static <T extends Entity> boolean isProjectileThrownBy(Entity throwable, @Nullable T e) {
|
2020-06-26 11:44:47 +02:00
|
|
|
return e != null && isProjectile(throwable) && e.equals(((ProjectileEntity) throwable).getOwner());
|
2019-02-08 22:39:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-02-01 00:07:19 +01:00
|
|
|
* Sets the velocity and heading for a projectile.
|
|
|
|
*
|
|
|
|
* @param throwable The projectile
|
|
|
|
* @param heading The directional heaving vector
|
|
|
|
* @param velocity Velocity
|
|
|
|
* @param inaccuracy Inaccuracy
|
|
|
|
* @return True the projectile's heading was set, false otherwise
|
|
|
|
*/
|
2021-01-29 17:37:41 +01:00
|
|
|
static void setThrowableHeading(Entity throwable, Vec3d heading, float velocity, float inaccuracy) {
|
2019-02-01 00:07:19 +01:00
|
|
|
|
2020-06-26 11:44:47 +02:00
|
|
|
if (throwable instanceof ProjectileEntity) {
|
|
|
|
((ProjectileEntity)throwable).setVelocity(heading.x, heading.y, heading.z, velocity, inaccuracy);
|
2019-02-08 22:39:02 +01:00
|
|
|
} else {
|
2020-01-16 12:35:46 +01:00
|
|
|
heading = heading.normalize().multiply(velocity);
|
|
|
|
|
|
|
|
Vec3d vel = throwable.getVelocity();
|
2019-02-01 00:07:19 +01:00
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
throwable.addVelocity(heading.x - vel.x, heading.y - vel.y, heading.z - vel.z);
|
2019-02-08 22:39:02 +01:00
|
|
|
}
|
|
|
|
}
|
2021-02-16 22:12:09 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Reverses a projectile's direction to deflect it off a surface.
|
|
|
|
*/
|
|
|
|
static void ricochet(Entity projectile, Vec3d pos, float absorbtionRate) {
|
|
|
|
Vec3d position = projectile.getPos();
|
|
|
|
Vec3d motion = projectile.getVelocity();
|
|
|
|
|
|
|
|
Vec3d normal = position.subtract(pos).normalize();
|
|
|
|
Vec3d approach = motion.subtract(normal);
|
|
|
|
|
|
|
|
if (approach.length() < motion.length()) {
|
|
|
|
normal = normal.multiply(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
setThrowableHeading(projectile, normal, (float)motion.length() * absorbtionRate, 0);
|
|
|
|
}
|
2018-09-12 01:29:49 +02:00
|
|
|
}
|