|
18 | 18 | import net.minecraft.world.level.ChunkPos;
|
19 | 19 | import net.minecraft.world.level.Level;
|
20 | 20 | import net.minecraft.world.phys.AABB;
|
| 21 | +import net.minecraft.world.phys.Vec2; |
21 | 22 | import net.minecraft.world.phys.Vec3;
|
22 | 23 | import net.minecraft.world.phys.shapes.Shapes;
|
23 | 24 | import net.neoforged.neoforge.common.Tags;
|
24 | 25 | import net.neoforged.neoforge.entity.PartEntity;
|
25 | 26 | import org.joml.Quaternionf;
|
26 |
| -import org.joml.Vector2f; |
27 | 27 | import org.joml.Vector3f;
|
28 | 28 |
|
29 | 29 | import javax.annotation.Nullable;
|
@@ -426,13 +426,13 @@ public void teleport(Entity entity) {
|
426 | 426 | if (getLinkedPortal() != null) {
|
427 | 427 | Vec3 teleportTo = getTeleportTo(entity, linkedPortal);
|
428 | 428 | // Adjust the entity's rotation to match the exit portal's direction
|
429 |
| - Vector2f newLookAngle = transformLookAngle(entity, linkedPortal); |
| 429 | + Vec2 newLookAngle = transformLookAngle(entity, linkedPortal); |
430 | 430 | entity.resetFallDistance();
|
431 | 431 |
|
432 | 432 | Vec3 newMotion = calculateVelocity(entity);
|
433 | 433 |
|
434 | 434 | // Teleport the entity to the new location and set its rotation
|
435 |
| - boolean success = entity.teleportTo((ServerLevel) linkedPortal.level(), teleportTo.x(), teleportTo.y(), teleportTo.z(), new HashSet<>(), newLookAngle.y(), newLookAngle.x()); |
| 435 | + boolean success = entity.teleportTo((ServerLevel) linkedPortal.level(), teleportTo.x(), teleportTo.y(), teleportTo.z(), new HashSet<>(), newLookAngle.y, newLookAngle.x); |
436 | 436 |
|
437 | 437 | if (success) {
|
438 | 438 | entity.resetFallDistance();
|
@@ -491,86 +491,22 @@ public static Vec3 transformMotion(Vec3 motion, Direction from, Direction to) {
|
491 | 491 | /**
|
492 | 492 | * Adjust the entity's look angle (pitch and yaw) for seamless transitions between portals.
|
493 | 493 | *
|
494 |
| - * <p>Transitioning between two 'vertical' portals will keep the vertical look, but transform the horizontal |
495 |
| - * look. For example, if you enter a portal looking at the portal and 10 degrees to the right, you will |
496 |
| - * leave the exit portal looking away from the portal and 10 degrees to the right. And if you walk in |
497 |
| - * backwards, you will walk out looking at the exit portal.</p> |
498 |
| - * |
499 |
| - * <p>Transitioning between two 'horizontal' (ceiling/floor) portals, the horizontal look is kept, |
500 |
| - * but the vertical look is flipped such that if you enter a floor portal looking down at it, you will exit a |
501 |
| - * ceiling portal looking down out of it, or another floor portal looking up out of it.</p> |
502 |
| - * |
503 |
| - * <p>Transitions between vertical and horizontal portals currently leave the look angle untouched. |
504 |
| - * Similar ideas could be applied to enhance this (albeit with a more complex implementation), but these use cases |
505 |
| - * are less common, and the lack of seamless angle adjustment is less jarring than with axis aligned pairs.</p> |
506 |
| - * |
507 |
| - * @param entity entity |
| 494 | + * @param entity entity |
508 | 495 | * @param destination destination portal
|
509 |
| - * @return adjusted (pitch, yaw) |
510 |
| - */ |
511 |
| - private Vector2f transformLookAngle(Entity entity, PortalEntity destination) { |
512 |
| - final Direction myDirection = this.getDirection(); |
513 |
| - final boolean verticalEntry = myDirection.getAxis() != Direction.Axis.Y; |
514 |
| - final Direction destDirection = destination.getDirection(); |
515 |
| - final boolean verticalExit = destDirection.getAxis() != Direction.Axis.Y; |
516 |
| - final float entityYaw = entity.getYRot(); |
517 |
| - final float entityPitch = entity.getXRot(); |
518 |
| - |
519 |
| - float newYaw = entityYaw; |
520 |
| - float newPitch = entityPitch; |
521 |
| - |
522 |
| - if (verticalEntry && verticalExit) { // Handle vertical-to-vertical portal transitions (N/E/S/W) |
523 |
| - final float entryFacingYaw = getDirectFacingYaw(myDirection); |
524 |
| - final float exitAwayYaw = getDirectFacingAwayYaw(destDirection); |
525 |
| - |
526 |
| - // Calculate deviation from facing the entry portal |
527 |
| - final float yawDeviation = Mth.wrapDegrees(entityYaw - entryFacingYaw); |
528 |
| - |
529 |
| - // Apply deviation to the direction facing AWAY from the exit portal |
530 |
| - newYaw = Mth.wrapDegrees(exitAwayYaw + yawDeviation); |
531 |
| - } else if (!verticalEntry && !verticalExit) { // Both portals are horizontal (U/D to U/D) |
532 |
| - // Keep horizontal look |
533 |
| - newYaw = entityYaw; |
534 |
| - // If we enter looking at the portal, we should exit looking away (and vice versa) |
535 |
| - newPitch = myDirection == destDirection ? -entityPitch : entityPitch; |
536 |
| - } |
537 |
| - |
538 |
| - // Normalize angles to valid ranges |
539 |
| - newYaw = Mth.wrapDegrees(newYaw); |
540 |
| - newPitch = Math.max(-90, Math.min(90, newPitch)); |
541 |
| - |
542 |
| - return new Vector2f(newPitch, newYaw); |
543 |
| - } |
544 |
| - |
545 |
| - /** |
546 |
| - * Returns the yaw for looking directly away from the front of the portal. |
547 |
| - * |
548 |
| - * @param direction direction |
549 |
| - * @return yaw |
550 |
| - */ |
551 |
| - private static float getDirectFacingAwayYaw(Direction direction) { |
552 |
| - return switch (direction) { |
553 |
| - case NORTH -> 180; |
554 |
| - case SOUTH -> 0; |
555 |
| - case EAST -> -90; |
556 |
| - case WEST -> 90; |
557 |
| - default -> 0; |
558 |
| - }; |
559 |
| - } |
560 |
| - |
561 |
| - /** |
562 |
| - * Returns the yaw for looking directly at the front of the portal. |
563 |
| - * |
564 |
| - * @param direction direction |
565 |
| - * @return yaw |
| 496 | + * @return adjusted (xrot, yrot) |
566 | 497 | */
|
567 |
| - private static float getDirectFacingYaw(Direction direction) { |
568 |
| - return switch (direction) { |
569 |
| - case NORTH -> 0; |
570 |
| - case SOUTH -> 180; |
571 |
| - case EAST -> 90; |
572 |
| - case WEST -> -90; |
573 |
| - default -> 0; |
574 |
| - }; |
| 498 | + private Vec2 transformLookAngle(Entity entity, PortalEntity destination) { |
| 499 | + final Vec3 newLook = transformMotion(entity.getLookAngle(), getDirection(), destination.getDirection().getOpposite()); |
| 500 | + return toDegrees(newLook); |
| 501 | + } |
| 502 | + |
| 503 | + private static Vec2 toDegrees(Vec3 vector) { |
| 504 | + double x = vector.x; |
| 505 | + double y = vector.y; |
| 506 | + double z = vector.z; |
| 507 | + double hyp = Math.sqrt(x * x + z * z); |
| 508 | + float xrot = Mth.wrapDegrees((float)(-(Mth.atan2(y, hyp) * 180.0F / (float)Math.PI))); |
| 509 | + float yrot = Mth.wrapDegrees((float)(Mth.atan2(z, x) * 180.0F / (float)Math.PI) - 90.0F); |
| 510 | + return new Vec2(xrot, yrot); |
575 | 511 | }
|
576 | 512 | }
|
0 commit comments