hytale-server/com/hypixel/hytale/server/npc/movement/GroupSteeringAccumulator.java

164 lines
6.3 KiB
Java

package com.hypixel.hytale.server.npc.movement;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.math.vector.Vector3f;
import com.hypixel.hytale.server.core.modules.entity.component.HeadRotation;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.server.core.modules.physics.component.Velocity;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.server.npc.util.NPCPhysicsMath;
import javax.annotation.Nonnull;
public class GroupSteeringAccumulator {
@Nonnull
private static final ComponentType<EntityStore, TransformComponent> TRANSFORM_COMPONENT_TYPE = TransformComponent.getComponentType();
private final Vector3d sumOfVelocities = new Vector3d();
private final Vector3d sumOfDistances = new Vector3d();
private final Vector3d sumOfPositions = new Vector3d();
private final Vector3d temp = new Vector3d();
private int count;
private double x;
private double y;
private double z;
private double xViewDirection;
private double yViewDirection;
private double zViewDirection;
private Vector3d componentSelector = Vector3d.ALL_ONES;
private double maxRangeSquared = Double.MAX_VALUE;
private double maxDistance = Double.MAX_VALUE;
private float collisionViewHalfAngleCosine = 1.0F;
public void begin(double x, double y, double z, double xViewDirection, double yViewDirection, double zViewDirection) {
this.x = x;
this.y = y;
this.z = z;
this.xViewDirection = xViewDirection;
this.yViewDirection = yViewDirection;
this.zViewDirection = zViewDirection;
this.sumOfDistances.assign(0.0);
this.sumOfPositions.assign(0.0);
this.sumOfVelocities.assign(0.0);
this.count = 0;
}
public void begin(@Nonnull Ref<EntityStore> ref, @Nonnull ComponentAccessor<EntityStore> componentAccessor) {
HeadRotation headRotationComponent = componentAccessor.getComponent(ref, HeadRotation.getComponentType());
assert headRotationComponent != null;
Vector3f headRotation = headRotationComponent.getRotation();
NPCPhysicsMath.getViewDirection(headRotation, this.temp);
this.temp.normalize();
TransformComponent transformComponent = componentAccessor.getComponent(ref, TRANSFORM_COMPONENT_TYPE);
assert transformComponent != null;
Vector3d position = transformComponent.getPosition();
this.begin(position.getX(), position.getY(), position.getZ(), this.temp.x, this.temp.y, this.temp.z);
}
public void processEntity(@Nonnull Ref<EntityStore> ref, @Nonnull ComponentAccessor<EntityStore> componentAccessor) {
Velocity velocityComponent = componentAccessor.getComponent(ref, Velocity.getComponentType());
assert velocityComponent != null;
Vector3d velocity = velocityComponent.getVelocity();
TransformComponent transformComponent = componentAccessor.getComponent(ref, TRANSFORM_COMPONENT_TYPE);
assert transformComponent != null;
Vector3d position = transformComponent.getPosition();
double xPosition = position.getX();
double yPosition = position.getY();
double zPosition = position.getZ();
double dx = xPosition - this.x;
double dy = yPosition - this.y;
double dz = zPosition - this.z;
if (NPCPhysicsMath.dotProduct(dx, dy, dz, this.componentSelector) < this.maxRangeSquared
&& NPCPhysicsMath.isInViewCone(this.xViewDirection, this.yViewDirection, this.zViewDirection, this.collisionViewHalfAngleCosine, dx, dy, dz)) {
this.sumOfDistances.add(dx, dy, dz);
this.sumOfPositions.add(xPosition, yPosition, zPosition);
this.sumOfVelocities.add(velocity);
this.count++;
}
}
public void processEntity(
@Nonnull Ref<EntityStore> ref,
double distanceWeight,
double positionWeight,
double velocityWeight,
@Nonnull ComponentAccessor<EntityStore> componentAccessor
) {
TransformComponent transformComponent = componentAccessor.getComponent(ref, TRANSFORM_COMPONENT_TYPE);
assert transformComponent != null;
Vector3d position = transformComponent.getPosition();
Velocity velocityComponent = componentAccessor.getComponent(ref, Velocity.getComponentType());
assert velocityComponent != null;
Vector3d velocity = velocityComponent.getVelocity();
double dx = position.getX() - this.x;
double dy = position.getY() - this.y;
double dz = position.getZ() - this.z;
double d = NPCPhysicsMath.dotProduct(dx, dy, dz, this.componentSelector);
if (d < this.maxRangeSquared
&& NPCPhysicsMath.isInViewCone(this.xViewDirection, this.yViewDirection, this.zViewDirection, this.collisionViewHalfAngleCosine, dx, dy, dz)) {
d = 1.0 - Math.sqrt(d) / this.maxDistance;
double w = Math.pow(d, distanceWeight);
this.sumOfDistances.add(dx * w, dy * w, dz * w);
w = Math.pow(d, positionWeight);
this.sumOfPositions.addScaled(position, w);
w = Math.pow(d, velocityWeight);
this.sumOfVelocities.addScaled(velocity, w);
this.count++;
}
}
public void end() {
if (this.count > 0) {
double scale = 1.0 / this.count;
this.sumOfDistances.scale(scale).scale(this.componentSelector);
this.sumOfPositions.scale(scale).scale(this.componentSelector);
this.sumOfVelocities.scale(scale).scale(this.componentSelector);
}
}
public void setComponentSelector(Vector3d componentSelector) {
this.componentSelector = componentSelector;
}
public void setMaxRange(double maxRange) {
this.maxRangeSquared = maxRange * maxRange;
this.maxDistance = maxRange;
}
public void setViewConeHalfAngleCosine(float collisionViewHalfAngleCosine) {
this.collisionViewHalfAngleCosine = collisionViewHalfAngleCosine;
}
@Nonnull
public Vector3d getSumOfVelocities() {
return this.sumOfVelocities;
}
@Nonnull
public Vector3d getSumOfDistances() {
return this.sumOfDistances;
}
@Nonnull
public Vector3d getSumOfPositions() {
return this.sumOfPositions;
}
public int getCount() {
return this.count;
}
}