Update position parameters to support rotation-based offsets (#2374)

This commit is contained in:
jie65535 2023-09-18 09:00:58 +08:00 committed by GitHub
parent 047feaf4aa
commit ff6a51db30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 73 additions and 16 deletions

View File

@ -1,5 +1,7 @@
package emu.grasscutter.command; package emu.grasscutter.command;
import emu.grasscutter.game.world.Position;
import java.util.*; import java.util.*;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.regex.*; import java.util.regex.*;
@ -65,4 +67,62 @@ public class CommandHelpers {
} }
return current; return current;
} }
public static Position parsePosition(String inputX, String inputY, String inputZ, Position curPos, Position curRot) {
Position offset = new Position();
Position target = new Position(curPos);
if (inputX.contains("~")) { // Relative
if (!inputX.equals("~")) { // Relative with offset
target.addX(Float.parseFloat(inputX.replace("~", "")));
}
} else if (inputX.contains("^")) {
if (!inputX.equals("^")) {
offset.setX(Float.parseFloat(inputX.replace("^", "")));
}
} else { // Absolute
target.setX(Float.parseFloat(inputX));
}
if (inputY.contains("~")) { // Relative
if (!inputY.equals("~")) { // Relative with offset
target.addY(Float.parseFloat(inputY.replace("~", "")));
}
} else if (inputY.contains("^")) {
if (!inputY.equals("^")) {
offset.setY(Float.parseFloat(inputY.replace("^", "")));
}
} else { // Absolute
target.setY(Float.parseFloat(inputY));
}
if (inputZ.contains("~")) { // Relative
if (!inputZ.equals("~")) { // Relative with offset
target.addZ(Float.parseFloat(inputZ.replace("~", "")));
}
} else if (inputZ.contains("^")) {
if (!inputZ.equals("^")) {
offset.setZ(Float.parseFloat(inputZ.replace("^", "")));
}
} else { // Absolute
target.setZ(Float.parseFloat(inputZ));
}
if (!offset.equal3d(Position.ZERO)) {
return calculateOffset(target, curRot, offset);
} else {
return target;
}
}
public static Position calculateOffset(Position pos, Position rot, Position offset) {
// Degrees to radians
float angleZ = (float) Math.toRadians(rot.getY());
float angleX = (float) Math.toRadians(rot.getY() + 90);
// Calculate offset based on current position and rotation
return new Position(
pos.getX() + offset.getZ() * (float)Math.sin(angleZ) + offset.getX() * (float)Math.sin(angleX),
pos.getY() + offset.getY(),
pos.getZ() + offset.getZ() * (float)Math.cos(angleZ) + offset.getX() * (float)Math.cos(angleX));
}
} }

View File

@ -54,8 +54,8 @@ public final class SpawnCommand implements CommandHandler {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
Position pos = targetPlayer.getPosition(); Position pos = new Position(targetPlayer.getPosition());
Position rot = targetPlayer.getRotation(); Position rot = new Position(targetPlayer.getRotation());
switch (args.size()) { switch (args.size()) {
case 7: case 7:
@ -69,9 +69,7 @@ public final class SpawnCommand implements CommandHandler {
} // Fallthrough } // Fallthrough
case 4: case 4:
try { try {
pos.setX(CommandHelpers.parseRelative(args.get(1), pos.getX())); pos = CommandHelpers.parsePosition(args.get(1), args.get(2), args.get(3), pos, rot);
pos.setY(CommandHelpers.parseRelative(args.get(2), pos.getY()));
pos.setZ(CommandHelpers.parseRelative(args.get(3), pos.getZ()));
} catch (NumberFormatException ignored) { } catch (NumberFormatException ignored) {
CommandHandler.sendMessage( CommandHandler.sendMessage(
sender, translate(sender, "commands.execution.argument_error")); sender, translate(sender, "commands.execution.argument_error"));

View File

@ -6,6 +6,8 @@ import emu.grasscutter.command.*;
import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.world.Position; import emu.grasscutter.game.world.Position;
import emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType; import emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType;
import emu.grasscutter.server.packet.send.PacketSceneEntityAppearNotify;
import java.util.List; import java.util.List;
@Command( @Command(
@ -18,10 +20,8 @@ public final class TeleportCommand implements CommandHandler {
@Override @Override
public void execute(Player sender, Player targetPlayer, List<String> args) { public void execute(Player sender, Player targetPlayer, List<String> args) {
Position pos = targetPlayer.getPosition(); Position pos = new Position(targetPlayer.getPosition());
float x = pos.getX(); Position rot = new Position(targetPlayer.getRotation());
float y = pos.getY();
float z = pos.getZ();
int sceneId = targetPlayer.getSceneId(); int sceneId = targetPlayer.getSceneId();
switch (args.size()) { switch (args.size()) {
@ -34,9 +34,7 @@ public final class TeleportCommand implements CommandHandler {
} // Fallthrough } // Fallthrough
case 3: case 3:
try { try {
x = CommandHelpers.parseRelative(args.get(0), x); pos = CommandHelpers.parsePosition(args.get(0), args.get(1), args.get(2), pos, rot);
y = CommandHelpers.parseRelative(args.get(1), y);
z = CommandHelpers.parseRelative(args.get(2), z);
} catch (NumberFormatException ignored) { } catch (NumberFormatException ignored) {
CommandHandler.sendMessage( CommandHandler.sendMessage(
sender, translate(sender, "commands.teleport.invalid_position")); sender, translate(sender, "commands.teleport.invalid_position"));
@ -47,19 +45,20 @@ public final class TeleportCommand implements CommandHandler {
return; return;
} }
Position target_pos = new Position(x, y, z);
boolean result = boolean result =
targetPlayer targetPlayer
.getWorld() .getWorld()
.transferPlayerToScene(targetPlayer, sceneId, TeleportType.COMMAND, target_pos); .transferPlayerToScene(targetPlayer, sceneId, TeleportType.COMMAND, pos);
if (!result) { if (!result) {
CommandHandler.sendMessage(sender, translate(sender, "commands.teleport.exists_error")); CommandHandler.sendMessage(sender, translate(sender, "commands.teleport.exists_error"));
} else { } else {
CommandHandler.sendMessage( CommandHandler.sendMessage(
sender,
translate(
sender, sender,
translate( "commands.teleport.success",
sender, "commands.teleport.success", targetPlayer.getNickname(), x, y, z, sceneId)); targetPlayer.getNickname(), pos.getX(), pos.getY(), pos.getZ(), sceneId));
} }
} }
} }