Skip to content

Commit

Permalink
feat: added EntityLookAtPlayerTrait
Browse files Browse the repository at this point in the history
  • Loading branch information
PMK744 committed Jan 22, 2025
1 parent 632bf07 commit 86a35ca
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 10 deletions.
43 changes: 33 additions & 10 deletions packages/core/src/entity/traits/attribute/movement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,12 @@ class EntityMovementTrait extends EntityAttributeTrait {
packet.runtimeId = this.entity.runtimeId;
packet.flags = MoveDeltaFlags.All;
packet.x = this.entity.position.x;
packet.y = this.entity.position.y - 0.1; // Adjust the y position

// Asjust the y position of the entity
packet.y = this.entity.isPlayer()
? this.entity.position.y
: this.entity.position.y - 0.1;

packet.z = this.entity.position.z;
packet.yaw = this.entity.rotation.yaw;
packet.headYaw = this.entity.rotation.headYaw;
Expand Down Expand Up @@ -101,17 +106,35 @@ class EntityMovementTrait extends EntityAttributeTrait {
}

public lookAt(position: BlockPosition | Vector3f) {
const direction = position.subtract(this.entity.position).floor();
const headYaw = -Math.atan2(direction.x, direction.z) * (180 / Math.PI);
const horizontalDistance = Math.sqrt(
Math.pow(direction.x, 2) + Math.pow(direction.z, 2)
);
const pitch =
-Math.atan2(direction.y, horizontalDistance) * (180 / Math.PI);
// Convert the block position to a vector
const vector = BlockPosition.toVector3f(position);

this.entity.rotation.headYaw = headYaw;
// Calculate the direction to the target position
const direction = this.calculateDirection(this.entity.position, vector);

// Calculate the yaw and pitch from the direction
let yaw = Math.atan2(direction.z, direction.x) * (180 / Math.PI) - 90;

// Calculate the pitch from the direction
const pitch =
-Math.atan2(
direction.y,
Math.sqrt(direction.x * direction.x + direction.z * direction.z)
) *
(180 / Math.PI);

// Normalize the yaw if it is out of range
if (yaw > 180) yaw -= 360;
if (yaw < -180) yaw += 360;

// Normalize the pitch if it is out of range
if (pitch > 180) yaw -= 360;
if (pitch < -180) yaw += 360;

// Set the entity rotation
this.entity.rotation.yaw = yaw;
this.entity.rotation.headYaw = yaw;
this.entity.rotation.pitch = pitch;
this.entity.rotation.yaw = headYaw;
}

/**
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/entity/traits/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export * from "./effects";
export * from "./visibility";
export * from "./equipment";
export * from "./npc";
export * from "./look-at-player";
59 changes: 59 additions & 0 deletions packages/core/src/entity/traits/look-at-player.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { EntityIdentifier } from "../../enums";

import { EntityMovementTrait } from "./attribute";
import { EntityTrait } from "./trait";

class EntityLookAtPlayerTrait extends EntityTrait {
public static readonly identifier = "look-at-player";
public static readonly types = [EntityIdentifier.Npc];

/**
* The radius of the entity to look at the player.
*/
public radius = 5;

public onTick(): void {
// Check if the current tick is even.
const currentTick = this.entity.world.currentTick;
if (currentTick % 2n !== 0n) return;

// Check if the entity has a movement trait.
if (!this.entity.hasTrait(EntityMovementTrait)) return;

// Get the dimension of the entity.
const dimension = this.entity.dimension;

// Get all the players near the entity.
const players = dimension
.getEntities({
position: this.entity.position,
maxDistance: this.radius
})
.filter((entity) => entity.isPlayer());

// Check if there are no players.
if (players.length === 0) return;

// Find the closest player.
const player = players.reduce((closest, current) =>
closest.position.distance(this.entity.position) <
current.position.distance(this.entity.position)
? closest
: current
);

// Check if the player exists.
if (!player) return;

// Get the movement trait of the entity.
const movement = this.entity.getTrait(EntityMovementTrait);

// Clone the position of the player, and increase the y value by 0.9.
const position = player.position.clone();

// Make the entity look at the player
return movement.lookAt(position);
}
}

export { EntityLookAtPlayerTrait };
8 changes: 8 additions & 0 deletions packages/protocol/src/proto/types/vector3f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,14 @@ class Vector3f extends DataType implements IPosition {
);
}

/**
* Clones this 3D vector into a new 3D vector.
* @returns The cloned 3D vector.
*/
public clone(): Vector3f {
return new Vector3f(this.x, this.y, this.z);
}

/**
* Converts this array to a 3D vector.
* @returns The 3D vector that was converted.
Expand Down

0 comments on commit 86a35ca

Please sign in to comment.