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
This commit is contained in:
@@ -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 <name>} — téléporte le joueur appelant au centre de
|
||||||
|
* l'AABB d'une région Gravity Flip. Outil debug/builder (CMD-06).
|
||||||
|
*
|
||||||
|
* <p>É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.
|
||||||
|
*
|
||||||
|
* <p>Pattern Teleport copié ligne-à-ligne sur
|
||||||
|
* {@code com.hypixel.hytale.builtin.teleport.commands.teleport.variant.TeleportToCoordinatesCommand}
|
||||||
|
* (lignes 48-68) :
|
||||||
|
* <ol>
|
||||||
|
* <li>Lire {@link TransformComponent} (rotation corps) et {@link HeadRotation}
|
||||||
|
* (rotation tête) pour préserver l'orientation du joueur.</li>
|
||||||
|
* <li>Calculer le centre componentwise : {@code c = (min + max) / 2}.</li>
|
||||||
|
* <li>Construire via {@code Teleport.createForPlayer(pos, rotation).setHeadRotation(...)}.</li>
|
||||||
|
* <li>{@code store.addComponent(ref, Teleport.getComponentType(), teleport)} —
|
||||||
|
* le {@code TeleportSystem} du core consomme le composant au prochain tick.</li>
|
||||||
|
* </ol>
|
||||||
|
*
|
||||||
|
* <p>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<String> 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<EntityStore> store,
|
||||||
|
@Nonnull Ref<EntityStore> 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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user