From c42ebbe0e9cebaa087029fb5dbb892f0a4627e19 Mon Sep 17 00:00:00 2001 From: kayjaydee Date: Fri, 24 Apr 2026 14:55:12 +0200 Subject: [PATCH] feat(04-04): add tp subcommand teleporting to region AABB center (CMD-06) - AbstractPlayerCommand (tp only makes sense for a player caller) - Pattern mirrors TeleportToCoordinatesCommand:48-68 (read Transform+HeadRotation, build Teleport.createForPlayer(pos, bodyRotation).setHeadRotation(headRotation), store.addComponent) - Center computed componentwise: c = (min+max)/2 - Preserves caller body+head rotation (teleport in place, no look change) - Clear error on unknown region name --- .../command/GravityFlipTpSubCommand.java | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/main/java/com/mythlane/gravityflip/command/GravityFlipTpSubCommand.java diff --git a/src/main/java/com/mythlane/gravityflip/command/GravityFlipTpSubCommand.java b/src/main/java/com/mythlane/gravityflip/command/GravityFlipTpSubCommand.java new file mode 100644 index 0000000..c842b50 --- /dev/null +++ b/src/main/java/com/mythlane/gravityflip/command/GravityFlipTpSubCommand.java @@ -0,0 +1,104 @@ +package com.mythlane.gravityflip.command; + +import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.component.Store; +import com.hypixel.hytale.math.vector.Vector3d; +import com.hypixel.hytale.math.vector.Vector3f; +import com.hypixel.hytale.server.core.Message; +import com.hypixel.hytale.server.core.command.system.CommandContext; +import com.hypixel.hytale.server.core.command.system.arguments.system.RequiredArg; +import com.hypixel.hytale.server.core.command.system.arguments.types.ArgTypes; +import com.hypixel.hytale.server.core.command.system.basecommands.AbstractPlayerCommand; +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.entity.teleport.Teleport; +import com.hypixel.hytale.server.core.universe.PlayerRef; +import com.hypixel.hytale.server.core.universe.world.World; +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import com.mythlane.gravityflip.GravityFlipPlugin; +import com.mythlane.gravityflip.region.GravityFlipRegion; + +import javax.annotation.Nonnull; + +/** + * {@code /gravityflip tp } — téléporte le joueur appelant au centre de + * l'AABB d'une région Gravity Flip. Outil debug/builder (CMD-06). + * + *

Étend {@link AbstractPlayerCommand} : tp ne fait sens que pour un joueur, + * la base class gère automatiquement le message "must be player" pour un appel console. + * + *

Pattern Teleport copié ligne-à-ligne sur + * {@code com.hypixel.hytale.builtin.teleport.commands.teleport.variant.TeleportToCoordinatesCommand} + * (lignes 48-68) : + *

    + *
  1. Lire {@link TransformComponent} (rotation corps) et {@link HeadRotation} + * (rotation tête) pour préserver l'orientation du joueur.
  2. + *
  3. Calculer le centre componentwise : {@code c = (min + max) / 2}.
  4. + *
  5. Construire via {@code Teleport.createForPlayer(pos, rotation).setHeadRotation(...)}.
  6. + *
  7. {@code store.addComponent(ref, Teleport.getComponentType(), teleport)} — + * le {@code TeleportSystem} du core consomme le composant au prochain tick.
  8. + *
+ * + *

T-04-04-02 : permission auto-générée {@code mythlane.gravityflip.command.gravityflip.tp} + * sert de gate. Pas de restriction GameMode v1 (builder tool). + */ +public final class GravityFlipTpSubCommand extends AbstractPlayerCommand { + + private final GravityFlipPlugin plugin; + + private final RequiredArg nameArg = + this.withRequiredArg("name", "Nom de la région cible", ArgTypes.STRING); + + public GravityFlipTpSubCommand(GravityFlipPlugin plugin) { + super("tp", "Téléporte au centre d'une région Gravity Flip"); + this.plugin = plugin; + } + + @Override + protected void execute(@Nonnull CommandContext ctx, + @Nonnull Store store, + @Nonnull Ref ref, + @Nonnull PlayerRef playerRef, + @Nonnull World world) { + String name = nameArg.get(ctx); + GravityFlipRegion target = null; + for (GravityFlipRegion r : plugin.regions().all()) { + if (r.getName().equals(name)) { + target = r; + break; + } + } + if (target == null) { + ctx.sendMessage(Message.raw("[gravityflip] Région '" + name + "' introuvable.")); + return; + } + + Vector3d mn = target.getMin(); + Vector3d mx = target.getMax(); + double cx = (mn.x + mx.x) / 2.0; + double cy = (mn.y + mx.y) / 2.0; + double cz = (mn.z + mx.z) / 2.0; + + TransformComponent tc = store.getComponent(ref, TransformComponent.getComponentType()); + if (tc == null) { + ctx.sendMessage(Message.raw( + "[gravityflip] TransformComponent manquant — tp impossible.")); + return; + } + HeadRotation hr = store.getComponent(ref, HeadRotation.getComponentType()); + + // Préserve l'orientation courante : body rotation depuis Transform, head rotation + // si disponible (sinon on laisse la default côté Teleport.createForPlayer). + Vector3f bodyRotation = tc.getRotation().clone(); + Teleport teleport = Teleport.createForPlayer( + new Vector3d(cx, cy, cz), bodyRotation); + if (hr != null) { + teleport = teleport.setHeadRotation(hr.getRotation().clone()); + } + store.addComponent(ref, Teleport.getComponentType(), teleport); + + ctx.sendMessage(Message.raw(String.format( + "[gravityflip] Téléporté au centre de '%s' : (%.0f,%.0f,%.0f)", + name, cx, cy, cz))); + } +}