mirror of
https://github.com/tanyaofei/minecraft-fakeplayer.git
synced 2025-09-14 11:16:46 +08:00
添加 look, jump, move 命令
This commit is contained in:
parent
703b13515a
commit
f9e19ae7f7
@ -28,6 +28,9 @@
|
|||||||
+ /fp config get - 查看个性化配置
|
+ /fp config get - 查看个性化配置
|
||||||
+ /fp drop - 丢弃手上物品
|
+ /fp drop - 丢弃手上物品
|
||||||
+ /fp dropinv - 丢弃背包物品
|
+ /fp dropinv - 丢弃背包物品
|
||||||
|
+ /fp look - 让假人看向指定位置
|
||||||
|
+ /fp move - 让家人移动
|
||||||
|
+ /fp jump - 让假人跳跃
|
||||||
+ /fp attack - 让假人点击鼠标左键 **(实验性)**
|
+ /fp attack - 让假人点击鼠标左键 **(实验性)**
|
||||||
+ /fp use - 让假人点击鼠标右键 **(实验性)**
|
+ /fp use - 让假人点击鼠标右键 **(实验性)**
|
||||||
+ /fp cmd - 让假人执行他有权限执行的命令
|
+ /fp cmd - 让假人执行他有权限执行的命令
|
||||||
|
@ -21,7 +21,7 @@ public abstract class AbstractCommand {
|
|||||||
|
|
||||||
protected final FakeplayerManager fakeplayerManager = FakeplayerManager.instance;
|
protected final FakeplayerManager fakeplayerManager = FakeplayerManager.instance;
|
||||||
|
|
||||||
public static Argument<Player> targetArgument(@NotNull String nodeName) {
|
public static Argument<Player> target(@NotNull String nodeName) {
|
||||||
return new CustomArgument<>(new StringArgument(nodeName), info -> {
|
return new CustomArgument<>(new StringArgument(nodeName), info -> {
|
||||||
var sender = info.sender();
|
var sender = info.sender();
|
||||||
return sender.isOp()
|
return sender.isOp()
|
||||||
@ -44,7 +44,7 @@ public abstract class AbstractCommand {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Argument<List<Player>> multiTargetArgument(@NotNull String nodeName) {
|
public static Argument<List<Player>> targets(@NotNull String nodeName) {
|
||||||
return new CustomArgument<List<Player>, String>(new StringArgument(nodeName), info -> {
|
return new CustomArgument<List<Player>, String>(new StringArgument(nodeName), info -> {
|
||||||
var sender = info.sender();
|
var sender = info.sender();
|
||||||
var arg = info.currentInput();
|
var arg = info.currentInput();
|
||||||
|
@ -2,10 +2,19 @@ package io.github.hello09x.fakeplayer.command;
|
|||||||
|
|
||||||
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException;
|
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException;
|
||||||
import dev.jorel.commandapi.executors.CommandArguments;
|
import dev.jorel.commandapi.executors.CommandArguments;
|
||||||
|
import dev.jorel.commandapi.executors.CommandExecutor;
|
||||||
import io.github.hello09x.fakeplayer.entity.action.Action;
|
import io.github.hello09x.fakeplayer.entity.action.Action;
|
||||||
import io.github.hello09x.fakeplayer.entity.action.ActionSetting;
|
import io.github.hello09x.fakeplayer.entity.action.ActionSetting;
|
||||||
import io.github.hello09x.fakeplayer.entity.action.PlayerActionManager;
|
import io.github.hello09x.fakeplayer.entity.action.PlayerActionManager;
|
||||||
|
import io.github.hello09x.fakeplayer.util.MathUtils;
|
||||||
|
import io.github.hello09x.fakeplayer.util.Unwrapper;
|
||||||
|
import io.papermc.paper.entity.LookAnchor;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.bukkit.Location;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import static net.kyori.adventure.text.Component.text;
|
import static net.kyori.adventure.text.Component.text;
|
||||||
@ -19,9 +28,36 @@ public class ActionCommand extends AbstractCommand {
|
|||||||
|
|
||||||
private final PlayerActionManager actionManager = PlayerActionManager.instance;
|
private final PlayerActionManager actionManager = PlayerActionManager.instance;
|
||||||
|
|
||||||
|
private static String toLocationString(@NotNull Location location) {
|
||||||
|
return StringUtils.joinWith(", ",
|
||||||
|
MathUtils.round(location.getX(), 0.5),
|
||||||
|
MathUtils.round(location.getY(), 0.5),
|
||||||
|
MathUtils.round(location.getZ(), 0.5));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandExecutor action(@NotNull Action action, @NotNull ActionSetting setting) {
|
||||||
|
return (sender, args) -> action(sender, args, action, setting.clone());
|
||||||
|
}
|
||||||
|
|
||||||
public void action(@NotNull CommandSender sender, @NotNull CommandArguments args, @NotNull Action action, @NotNull ActionSetting setting) throws WrapperCommandSyntaxException {
|
public void action(@NotNull CommandSender sender, @NotNull CommandArguments args, @NotNull Action action, @NotNull ActionSetting setting) throws WrapperCommandSyntaxException {
|
||||||
var target = getTarget(sender, args);
|
var target = getTarget(sender, args);
|
||||||
actionManager.setAction(target, action, setting);
|
actionManager.setAction(target, action, setting);
|
||||||
|
|
||||||
|
String desc;
|
||||||
|
if (setting.equals(ActionSetting.stop())) {
|
||||||
|
desc = " 已停止";
|
||||||
|
} else if (setting.equals(ActionSetting.once())) {
|
||||||
|
desc = "";
|
||||||
|
} else {
|
||||||
|
desc = " 开始";
|
||||||
|
}
|
||||||
|
|
||||||
|
sender.sendMessage(textOfChildren(
|
||||||
|
text(target.getName()),
|
||||||
|
text(desc, GRAY),
|
||||||
|
text(" "),
|
||||||
|
text(action.name, GRAY)
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sneak(@NotNull CommandSender sender, @NotNull CommandArguments args) throws WrapperCommandSyntaxException {
|
public void sneak(@NotNull CommandSender sender, @NotNull CommandArguments args) throws WrapperCommandSyntaxException {
|
||||||
@ -36,10 +72,77 @@ public class ActionCommand extends AbstractCommand {
|
|||||||
|
|
||||||
sender.sendMessage(textOfChildren(
|
sender.sendMessage(textOfChildren(
|
||||||
text(target.getName(), WHITE),
|
text(target.getName(), WHITE),
|
||||||
text("现在", GRAY),
|
text(" 现在", GRAY),
|
||||||
text(sneaking ? "潜行中" : "取消了潜行", GRAY)
|
text(sneaking ? "潜行中" : "取消了潜行", GRAY)
|
||||||
));
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void lookAt(@NotNull CommandSender sender, @NotNull CommandArguments args) throws WrapperCommandSyntaxException {
|
||||||
|
var target = getTarget(sender, args);
|
||||||
|
var location = (Location) args.get("location");
|
||||||
|
target.lookAt(location, LookAnchor.EYES);
|
||||||
|
sender.sendMessage(textOfChildren(
|
||||||
|
text(target.getName(), WHITE),
|
||||||
|
text(" 正在看向 ", GRAY),
|
||||||
|
text(toLocationString(location), GRAY)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandExecutor look(@NotNull Direction direction) {
|
||||||
|
return (sender, args) -> {
|
||||||
|
var target = getTarget(sender, args);
|
||||||
|
look(target, direction);
|
||||||
|
sender.sendMessage(textOfChildren(
|
||||||
|
text(target.getName(), WHITE),
|
||||||
|
text(" 看向 ", GRAY),
|
||||||
|
text(switch (direction) {
|
||||||
|
case DOWN -> "下方";
|
||||||
|
case UP -> "上方";
|
||||||
|
case NORTH -> "北边";
|
||||||
|
case SOUTH -> "南边";
|
||||||
|
case WEST -> "西边";
|
||||||
|
case EAST -> "东边";
|
||||||
|
}, GRAY)
|
||||||
|
));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void look(
|
||||||
|
@NotNull Player target,
|
||||||
|
@NotNull Direction direction
|
||||||
|
) {
|
||||||
|
var player = Unwrapper.getServerPlayer(target);
|
||||||
|
switch (direction) {
|
||||||
|
case NORTH -> look(player, 180, 0);
|
||||||
|
case SOUTH -> look(player, 0, 0);
|
||||||
|
case EAST -> look(player, -90, 0);
|
||||||
|
case WEST -> look(player, 90, 0);
|
||||||
|
case UP -> look(player, player.getYRot(), -90);
|
||||||
|
case DOWN -> look(player, player.getYRot(), 90);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void look(@NotNull ServerPlayer player, float yaw, float pitch) {
|
||||||
|
player.setYRot(yaw % 360);
|
||||||
|
player.setXRot(MathUtils.clamp(pitch, -90, 90));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandExecutor move(float forward, float strafing) {
|
||||||
|
return (sender, args) -> {
|
||||||
|
var target = getTarget(sender, args);
|
||||||
|
var player = Unwrapper.getServerPlayer(target);
|
||||||
|
float vel = target.isSneaking() ? 0.3F : 1.0F;
|
||||||
|
if (forward != 0.0F) {
|
||||||
|
player.zza = vel * forward;
|
||||||
|
}
|
||||||
|
if (strafing != 0.0F) {
|
||||||
|
player.xxa = vel * strafing;
|
||||||
|
}
|
||||||
|
sender.sendMessage(textOfChildren(
|
||||||
|
text(target.getName()),
|
||||||
|
text(" 动了一下", GRAY)
|
||||||
|
));
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,17 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import static net.kyori.adventure.text.Component.text;
|
import static net.kyori.adventure.text.Component.text;
|
||||||
import static net.kyori.adventure.text.format.NamedTextColor.RED;
|
import static net.kyori.adventure.text.Component.textOfChildren;
|
||||||
|
import static net.kyori.adventure.text.format.NamedTextColor.*;
|
||||||
|
|
||||||
public class CmdCommand extends AbstractCommand {
|
public class CmdCommand extends AbstractCommand {
|
||||||
|
|
||||||
public final static CmdCommand instance = new CmdCommand();
|
public final static CmdCommand instance = new CmdCommand();
|
||||||
|
|
||||||
|
private static String toCommandString(@NotNull CommandResult command) {
|
||||||
|
return "/" + command.command().getName() + String.join(" ", command.args());
|
||||||
|
}
|
||||||
|
|
||||||
public void cmd(@NotNull CommandSender sender, @NotNull CommandArguments args) throws WrapperCommandSyntaxException {
|
public void cmd(@NotNull CommandSender sender, @NotNull CommandArguments args) throws WrapperCommandSyntaxException {
|
||||||
var target = getTarget(sender, args);
|
var target = getTarget(sender, args);
|
||||||
var cmd = Objects.requireNonNull((CommandResult) args.get("command"));
|
var cmd = Objects.requireNonNull((CommandResult) args.get("command"));
|
||||||
@ -25,7 +30,20 @@ public class CmdCommand extends AbstractCommand {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.execute(target);
|
if (!cmd.execute(target)) {
|
||||||
|
sender.sendMessage(textOfChildren(
|
||||||
|
text(target.getName(), WHITE),
|
||||||
|
text(" 执行命令失败: ", GRAY),
|
||||||
|
text(toCommandString(cmd), RED),
|
||||||
|
text(" , 请检查命令是否正确以及假人是否有权限", GRAY)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
sender.sendMessage(textOfChildren(
|
||||||
|
text(target.getName(), WHITE),
|
||||||
|
text(" 成功执行了命令: ", GRAY),
|
||||||
|
text(toCommandString(cmd), YELLOW)
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,12 +8,15 @@ import dev.jorel.commandapi.arguments.MultiLiteralArgument;
|
|||||||
import dev.jorel.commandapi.executors.CommandExecutor;
|
import dev.jorel.commandapi.executors.CommandExecutor;
|
||||||
import io.github.hello09x.fakeplayer.entity.action.Action;
|
import io.github.hello09x.fakeplayer.entity.action.Action;
|
||||||
import io.github.hello09x.fakeplayer.entity.action.ActionSetting;
|
import io.github.hello09x.fakeplayer.entity.action.ActionSetting;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import static io.github.hello09x.fakeplayer.command.AbstractCommand.multiTargetArgument;
|
import static io.github.hello09x.fakeplayer.command.AbstractCommand.target;
|
||||||
import static io.github.hello09x.fakeplayer.command.AbstractCommand.targetArgument;
|
import static io.github.hello09x.fakeplayer.command.AbstractCommand.targets;
|
||||||
|
import static io.github.hello09x.fakeplayer.command.ConfigCommand.config;
|
||||||
|
import static io.github.hello09x.fakeplayer.command.ConfigCommand.configValue;
|
||||||
|
|
||||||
public class Commands {
|
public class Commands {
|
||||||
|
|
||||||
@ -28,11 +31,11 @@ public class Commands {
|
|||||||
private final static String PERMISSION_CMD = "fakeplayer.cmd";
|
private final static String PERMISSION_CMD = "fakeplayer.cmd";
|
||||||
|
|
||||||
public static void register() {
|
public static void register() {
|
||||||
new CommandAPICommand("fakeplayer")
|
command("fakeplayer")
|
||||||
.withAliases("fp")
|
.withAliases("fp")
|
||||||
.withHelp(
|
.withHelp(
|
||||||
"假人相关命令",
|
"假人",
|
||||||
"fakeplayer 可以用来创建一个模拟为玩家的假人, 能保持附近区块的刷新、触发怪物生成。同时还提供了一些操作命令让你控制假人的物品、动作等等。"
|
"可以创建模拟玩家的假人, 能保持附近区块的刷新、触发怪物生成。同时还提供了一些操作命令让你控制假人的物品、动作等等。"
|
||||||
)
|
)
|
||||||
.withUsage(
|
.withUsage(
|
||||||
"§6/fp spawn §7- §f创建假人",
|
"§6/fp spawn §7- §f创建假人",
|
||||||
@ -47,133 +50,179 @@ public class Commands {
|
|||||||
"§6/fp health [假人] §7- §f查看生命值",
|
"§6/fp health [假人] §7- §f查看生命值",
|
||||||
"§6/fp exp [假人] §7- §f查看经验值",
|
"§6/fp exp [假人] §7- §f查看经验值",
|
||||||
"§6/fp expme [假人] §7- §f转移经验值",
|
"§6/fp expme [假人] §7- §f转移经验值",
|
||||||
|
"§6/fp attack <once|continuous|interval|stop> [假人] §7- §攻击/破坏",
|
||||||
|
"§6/fp use <once|continuous|interval|stop> [假人] §7- §f使用/交互/放置",
|
||||||
|
"§6/fp jump <once|continuous|interval|stop> [假人] §7- §f跳跃",
|
||||||
"§6/fp drop [假人] [-a|--all] §7- §f丢弃手上物品",
|
"§6/fp drop [假人] [-a|--all] §7- §f丢弃手上物品",
|
||||||
"§6/fp dropinv [假人] §7- §f丢弃背包物品",
|
"§6/fp dropinv [假人] §7- §f丢弃背包物品",
|
||||||
"§6/fp sneak [假人] §7- §f开启/取消潜行",
|
"§6/fp look <north|south|east|west|up|down|at> §7- §f看向指定位置",
|
||||||
"§6/fp attack <once|continuous|interval|stop> [假人] §7- §f模拟鼠标左键",
|
"§6/fp move <forward|backward|left|right> §7- §f移动假人",
|
||||||
"§6/fp use <once|continuous|interval|stop> [假人] §7- §f模拟鼠标右键",
|
"§6/fp cmd §7- §f执行命令",
|
||||||
"§6/fp cmd §7- §f让假人执行命令",
|
|
||||||
"§6/fp reload §7- §f重载配置文件"
|
"§6/fp reload §7- §f重载配置文件"
|
||||||
)
|
)
|
||||||
.withSubcommands(
|
.withSubcommands(
|
||||||
new CommandAPICommand("help")
|
command("help")
|
||||||
.withAliases("?")
|
.withAliases("?")
|
||||||
.withOptionalArguments(new IntegerArgument("page", 1))
|
.withOptionalArguments(new IntegerArgument("page", 1))
|
||||||
.executesPlayer(HelpCommand.instance::help),
|
.executesPlayer(HelpCommand.instance::help),
|
||||||
|
|
||||||
new CommandAPICommand("spawn")
|
command("spawn")
|
||||||
.withPermission(PERMISSION_SPAWN)
|
.withPermission(PERMISSION_SPAWN)
|
||||||
.withOptionalArguments(new LocationArgument("location").withPermission(PERMISSION_SPAWN_LOCATION))
|
.withOptionalArguments(location("location").withPermission(PERMISSION_SPAWN_LOCATION))
|
||||||
.executes(SpawnCommand.instance::spawn),
|
.executes(SpawnCommand.instance::spawn),
|
||||||
new CommandAPICommand("kill")
|
command("kill")
|
||||||
.withPermission(PERMISSION_SPAWN)
|
.withPermission(PERMISSION_SPAWN)
|
||||||
.withOptionalArguments(multiTargetArgument("targets"))
|
.withOptionalArguments(targets("targets"))
|
||||||
.executes(SpawnCommand.instance::kill),
|
.executes(SpawnCommand.instance::kill),
|
||||||
new CommandAPICommand("list")
|
command("list")
|
||||||
.withPermission(PERMISSION_SPAWN)
|
.withPermission(PERMISSION_SPAWN)
|
||||||
.withOptionalArguments(new IntegerArgument("page", 1), new IntegerArgument("size", 1))
|
.withOptionalArguments(integer("page", 1), integer("size", 1))
|
||||||
.executes(SpawnCommand.instance::list),
|
.executes(SpawnCommand.instance::list),
|
||||||
new CommandAPICommand("distance")
|
command("distance")
|
||||||
.withPermission(PERMISSION_SPAWN)
|
.withPermission(PERMISSION_SPAWN)
|
||||||
.withOptionalArguments(targetArgument("target"))
|
.withOptionalArguments(target("target"))
|
||||||
.executesPlayer(SpawnCommand.instance::distance),
|
.executesPlayer(SpawnCommand.instance::distance),
|
||||||
|
|
||||||
new CommandAPICommand("exp")
|
command("exp")
|
||||||
.withPermission(PERMISSION_PROFILE)
|
.withPermission(PERMISSION_PROFILE)
|
||||||
.withOptionalArguments(targetArgument("target"))
|
.withOptionalArguments(target("target"))
|
||||||
.executes(ProfileCommand.instance::exp),
|
.executes(ProfileCommand.instance::exp),
|
||||||
new CommandAPICommand("health")
|
command("health")
|
||||||
.withPermission(PERMISSION_PROFILE)
|
.withPermission(PERMISSION_PROFILE)
|
||||||
.withOptionalArguments(targetArgument("target"))
|
.withOptionalArguments(target("target"))
|
||||||
.executes(ProfileCommand.instance::health),
|
.executes(ProfileCommand.instance::health),
|
||||||
|
|
||||||
new CommandAPICommand("tp")
|
command("tp")
|
||||||
.withPermission(PERMISSION_TP)
|
.withPermission(PERMISSION_TP)
|
||||||
.withOptionalArguments(targetArgument("target"))
|
.withOptionalArguments(target("target"))
|
||||||
.executesPlayer(TpCommand.instance::tp),
|
.executesPlayer(TpCommand.instance::tp),
|
||||||
new CommandAPICommand("tphere")
|
command("tphere")
|
||||||
.withPermission(PERMISSION_TP)
|
.withPermission(PERMISSION_TP)
|
||||||
.withOptionalArguments(targetArgument("target"))
|
.withOptionalArguments(target("target"))
|
||||||
.executesPlayer(TpCommand.instance::tphere),
|
.executesPlayer(TpCommand.instance::tphere),
|
||||||
new CommandAPICommand("tps")
|
command("tps")
|
||||||
.withPermission(PERMISSION_TP)
|
.withPermission(PERMISSION_TP)
|
||||||
.withOptionalArguments(targetArgument("target"))
|
.withOptionalArguments(target("target"))
|
||||||
.executesPlayer(TpCommand.instance::tps),
|
.executesPlayer(TpCommand.instance::tps),
|
||||||
|
|
||||||
new CommandAPICommand("config")
|
command("config")
|
||||||
.withSubcommands(
|
.withSubcommands(
|
||||||
new CommandAPICommand("get")
|
command("get")
|
||||||
.withArguments(ConfigCommand.configArgument("config"))
|
.withArguments(config("config"))
|
||||||
.executesPlayer(ConfigCommand.instance::getConfig),
|
.executesPlayer(ConfigCommand.instance::getConfig),
|
||||||
new CommandAPICommand("set")
|
command("set")
|
||||||
.withArguments(
|
.withArguments(
|
||||||
ConfigCommand.configArgument("config"),
|
config("config"),
|
||||||
ConfigCommand.configValueArgument("config", "value"))
|
configValue("config", "value"))
|
||||||
.executesPlayer(ConfigCommand.instance::setConfig)
|
.executesPlayer(ConfigCommand.instance::setConfig)
|
||||||
),
|
),
|
||||||
new CommandAPICommand("attack")
|
command("attack")
|
||||||
.withPermission(PERMISSION_EXPERIMENTAL_ACTION)
|
.withPermission(PERMISSION_EXPERIMENTAL_ACTION)
|
||||||
.withSubcommands(buildActionCommand(Action.ATTACK)),
|
.withSubcommands(action(Action.ATTACK)),
|
||||||
new CommandAPICommand("use")
|
command("use")
|
||||||
.withPermission(PERMISSION_EXPERIMENTAL_ACTION)
|
.withPermission(PERMISSION_EXPERIMENTAL_ACTION)
|
||||||
.withSubcommands(buildActionCommand(Action.USE)),
|
.withSubcommands(action(Action.USE)),
|
||||||
new CommandAPICommand("drop")
|
command("jump")
|
||||||
|
.withPermission(PERMISSION_ACTION)
|
||||||
|
.withSubcommands(action(Action.JUMP)),
|
||||||
|
command("drop")
|
||||||
.withPermission(PERMISSION_ACTION)
|
.withPermission(PERMISSION_ACTION)
|
||||||
.withOptionalArguments(
|
.withOptionalArguments(
|
||||||
targetArgument("target"),
|
target("target"),
|
||||||
new MultiLiteralArgument("all", List.of("-a", "--all")))
|
literals("all", "-a", "--all"))
|
||||||
.executes((CommandExecutor) (sender, args) -> ActionCommand.instance.action(
|
.executes((CommandExecutor) (sender, args) -> ActionCommand.instance.action(
|
||||||
sender,
|
sender,
|
||||||
args,
|
args,
|
||||||
args.getOptional("all").isPresent() ? Action.DROP_STACK : Action.DROP_ITEM,
|
args.getOptional("all").isPresent() ? Action.DROP_STACK : Action.DROP_ITEM,
|
||||||
ActionSetting.once())),
|
ActionSetting.once())),
|
||||||
new CommandAPICommand("dropinv")
|
command("dropinv")
|
||||||
.withPermission(PERMISSION_ACTION)
|
.withPermission(PERMISSION_ACTION)
|
||||||
.withOptionalArguments(targetArgument("target"))
|
.withOptionalArguments(target("target"))
|
||||||
.executes((CommandExecutor) (sender, args) -> ActionCommand.instance.action(sender, args, Action.DROP_INVENTORY, ActionSetting.once())),
|
.executes(ActionCommand.instance.action(Action.DROP_INVENTORY, ActionSetting.once())),
|
||||||
new CommandAPICommand("sneak")
|
command("sneak")
|
||||||
.withPermission(PERMISSION_ACTION)
|
.withPermission(PERMISSION_ACTION)
|
||||||
.withOptionalArguments(targetArgument("target"))
|
.withOptionalArguments(target("target"))
|
||||||
.withOptionalArguments(new MultiLiteralArgument("sneaking", List.of("true", "false")))
|
.withOptionalArguments(literals("sneaking", "true", "false"))
|
||||||
.executes(ActionCommand.instance::sneak),
|
.executes(ActionCommand.instance::sneak),
|
||||||
|
command("look")
|
||||||
|
.withPermission(PERMISSION_ACTION)
|
||||||
|
.withSubcommands(
|
||||||
|
command("north")
|
||||||
|
.withOptionalArguments(target("target"))
|
||||||
|
.executes(ActionCommand.instance.look(Direction.NORTH)),
|
||||||
|
command("south")
|
||||||
|
.withOptionalArguments(target("target"))
|
||||||
|
.executes(ActionCommand.instance.look(Direction.SOUTH)),
|
||||||
|
command("west")
|
||||||
|
.withOptionalArguments(target("target"))
|
||||||
|
.executes(ActionCommand.instance.look(Direction.WEST)),
|
||||||
|
command("east")
|
||||||
|
.withOptionalArguments(target("target"))
|
||||||
|
.executes(ActionCommand.instance.look(Direction.EAST)),
|
||||||
|
command("up")
|
||||||
|
.withOptionalArguments(target("target"))
|
||||||
|
.executes(ActionCommand.instance.look(Direction.UP)),
|
||||||
|
command("down")
|
||||||
|
.withOptionalArguments(target("target"))
|
||||||
|
.executes(ActionCommand.instance.look(Direction.DOWN)),
|
||||||
|
command("at")
|
||||||
|
.withArguments(new LocationArgument("location"))
|
||||||
|
.withOptionalArguments(target("target"))
|
||||||
|
.executes(ActionCommand.instance::lookAt)
|
||||||
|
),
|
||||||
|
command("move")
|
||||||
|
.withPermission(PERMISSION_ACTION)
|
||||||
|
.withSubcommands(
|
||||||
|
command("forward")
|
||||||
|
.withOptionalArguments(target("target"))
|
||||||
|
.executes(ActionCommand.instance.move(1, 0)),
|
||||||
|
command("backward")
|
||||||
|
.withOptionalArguments(target("target"))
|
||||||
|
.executes(ActionCommand.instance.move(-1, 0)),
|
||||||
|
command("left")
|
||||||
|
.withOptionalArguments(target("target"))
|
||||||
|
.executes(ActionCommand.instance.move(0, 1)),
|
||||||
|
command("right")
|
||||||
|
.withOptionalArguments(target("target"))
|
||||||
|
.executes(ActionCommand.instance.move(0, -1))
|
||||||
|
),
|
||||||
|
|
||||||
new CommandAPICommand("expme")
|
command("expme")
|
||||||
.withPermission(PERMISSION_EXP)
|
.withPermission(PERMISSION_EXP)
|
||||||
.withOptionalArguments(targetArgument("target"))
|
.withOptionalArguments(target("target"))
|
||||||
.executesPlayer(ExpCommand.instance::expme),
|
.executesPlayer(ExpCommand.instance::expme),
|
||||||
|
|
||||||
new CommandAPICommand("cmd")
|
command("cmd")
|
||||||
.withPermission(PERMISSION_CMD)
|
.withPermission(PERMISSION_CMD)
|
||||||
.withArguments(
|
.withArguments(
|
||||||
targetArgument("target"),
|
target("target"),
|
||||||
new CommandArgument("command"))
|
new CommandArgument("command"))
|
||||||
.executes(CmdCommand.instance::cmd),
|
.executes(CmdCommand.instance::cmd),
|
||||||
|
|
||||||
new CommandAPICommand("reload")
|
command("reload")
|
||||||
.withPermission(PERMISSION_ADMIN)
|
.withPermission(PERMISSION_ADMIN)
|
||||||
.executes(ReloadCommand.instance::reload)
|
.executes(ReloadCommand.instance::reload)
|
||||||
|
|
||||||
).register();
|
).register();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CommandAPICommand[] buildActionCommand(@NotNull Action action) {
|
private static CommandAPICommand[] action(@NotNull Action action) {
|
||||||
return new CommandAPICommand[]{
|
return new CommandAPICommand[]{
|
||||||
new CommandAPICommand("once")
|
command("once")
|
||||||
.withOptionalArguments(targetArgument("target"))
|
.withOptionalArguments(target("target"))
|
||||||
.executes((CommandExecutor) (sender, args) -> ActionCommand.instance.action(sender, args, action, ActionSetting.once())
|
.executes(ActionCommand.instance.action(action, ActionSetting.once())
|
||||||
),
|
),
|
||||||
new CommandAPICommand("continuous")
|
command("continuous")
|
||||||
.withOptionalArguments(targetArgument("target"))
|
.withOptionalArguments(target("target"))
|
||||||
.executes((CommandExecutor) (sender, args) -> ActionCommand.instance.action(sender, args, action, ActionSetting.continuous())
|
.executes(ActionCommand.instance.action(action, ActionSetting.continuous())),
|
||||||
|
command("stop")
|
||||||
|
.withOptionalArguments(target("target"))
|
||||||
|
.executes(ActionCommand.instance.action(action, ActionSetting.stop())
|
||||||
),
|
),
|
||||||
new CommandAPICommand("stop")
|
command("interval")
|
||||||
.withOptionalArguments(targetArgument("target"))
|
|
||||||
.executes((CommandExecutor) (sender, args) -> ActionCommand.instance.action(sender, args, action, ActionSetting.stop())
|
|
||||||
),
|
|
||||||
new CommandAPICommand("interval")
|
|
||||||
.withOptionalArguments(
|
.withOptionalArguments(
|
||||||
new IntegerArgument("interval", 1),
|
integer("interval", 1),
|
||||||
targetArgument("target"))
|
target("target"))
|
||||||
.executes((sender, args) -> {
|
.executes((sender, args) -> {
|
||||||
int interval = (int) args.getOptional("interval").orElse(1);
|
int interval = (int) args.getOptional("interval").orElse(1);
|
||||||
ActionCommand.instance.action(sender, args, action, ActionSetting.interval(interval));
|
ActionCommand.instance.action(sender, args, action, ActionSetting.interval(interval));
|
||||||
@ -181,5 +230,21 @@ public class Commands {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static CommandAPICommand command(@NotNull String name) {
|
||||||
|
return new CommandAPICommand(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IntegerArgument integer(String name, int min) {
|
||||||
|
return new IntegerArgument(name, min);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LocationArgument location(String name) {
|
||||||
|
return new LocationArgument(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MultiLiteralArgument literals(String name, String... literals) {
|
||||||
|
return new MultiLiteralArgument(name, Arrays.asList(literals));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ public class ConfigCommand extends AbstractCommand {
|
|||||||
|
|
||||||
private final UserConfigRepository repository = UserConfigRepository.instance;
|
private final UserConfigRepository repository = UserConfigRepository.instance;
|
||||||
|
|
||||||
public static Argument<Config<Object>> configArgument(String nodeName) {
|
public static Argument<Config<Object>> config(String nodeName) {
|
||||||
return new CustomArgument<>(new StringArgument(nodeName), info -> {
|
return new CustomArgument<>(new StringArgument(nodeName), info -> {
|
||||||
var arg = info.currentInput();
|
var arg = info.currentInput();
|
||||||
try {
|
try {
|
||||||
@ -35,7 +35,7 @@ public class ConfigCommand extends AbstractCommand {
|
|||||||
}).replaceSuggestions(ArgumentSuggestions.strings(Arrays.stream(Configs.values()).map(Config::name).toList()));
|
}).replaceSuggestions(ArgumentSuggestions.strings(Arrays.stream(Configs.values()).map(Config::name).toList()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Argument<Object> configValueArgument(String configNodeName, String nodeName) {
|
public static Argument<Object> configValue(String configNodeName, String nodeName) {
|
||||||
return new CustomArgument<>(new StringArgument(nodeName), info -> {
|
return new CustomArgument<>(new StringArgument(nodeName), info -> {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
var config = Objects.requireNonNull((Config<Object>) info.previousArgs().get(configNodeName));
|
var config = Objects.requireNonNull((Config<Object>) info.previousArgs().get(configNodeName));
|
||||||
|
@ -26,12 +26,11 @@ public class SpawnCommand extends AbstractCommand {
|
|||||||
|
|
||||||
private static String toLocationString(@NotNull Location location) {
|
private static String toLocationString(@NotNull Location location) {
|
||||||
return location.getWorld().getName()
|
return location.getWorld().getName()
|
||||||
+ " 世界: "
|
+ ": "
|
||||||
+ StringUtils.joinWith(", ",
|
+ StringUtils.joinWith(", ",
|
||||||
MathUtils.round(location.getX(), 0.5),
|
MathUtils.round(location.getX(), 0.5),
|
||||||
MathUtils.round(location.getY(), 0.5),
|
MathUtils.round(location.getY(), 0.5),
|
||||||
MathUtils.round(location.getZ(), 0.5));
|
MathUtils.round(location.getZ(), 0.5));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void spawn(@NotNull CommandSender sender, CommandArguments args) {
|
public void spawn(@NotNull CommandSender sender, CommandArguments args) {
|
||||||
@ -131,9 +130,9 @@ public class SpawnCommand extends AbstractCommand {
|
|||||||
|
|
||||||
var distance = location1.distance(location2);
|
var distance = location1.distance(location2);
|
||||||
sender.sendMessage(textOfChildren(
|
sender.sendMessage(textOfChildren(
|
||||||
text("你与 "),
|
text("你与 ", GRAY),
|
||||||
text(target.getName()),
|
text(target.getName()),
|
||||||
text(" 相距 "),
|
text(" 相距 ", GRAY),
|
||||||
text(MathUtils.round(distance, 0.5), WHITE)
|
text(MathUtils.round(distance, 0.5), WHITE)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -130,6 +130,7 @@ public class FakePlayer {
|
|||||||
bukkitPlayer.setInvulnerable(invulnerable);
|
bukkitPlayer.setInvulnerable(invulnerable);
|
||||||
bukkitPlayer.setCollidable(collidable);
|
bukkitPlayer.setCollidable(collidable);
|
||||||
bukkitPlayer.setCanPickupItems(pickupItems);
|
bukkitPlayer.setCanPickupItems(pickupItems);
|
||||||
|
bukkitPlayer.getInventory().clear(); // 一些同步背包的插件可能在 JOIN 的时候恢复背包, 这个时候清空掉防止物品被复制了
|
||||||
new BukkitRunnable() {
|
new BukkitRunnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package io.github.hello09x.fakeplayer.entity.action;
|
package io.github.hello09x.fakeplayer.entity.action;
|
||||||
|
|
||||||
import io.github.hello09x.fakeplayer.util.Tracer;
|
import io.github.hello09x.fakeplayer.util.Tracer;
|
||||||
import net.minecraft.core.BlockPos;
|
import lombok.AllArgsConstructor;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.world.InteractionHand;
|
import net.minecraft.world.InteractionHand;
|
||||||
@ -13,14 +13,15 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
|
|
||||||
import static net.minecraft.network.protocol.game.ServerboundPlayerActionPacket.Action.*;
|
import static net.minecraft.network.protocol.game.ServerboundPlayerActionPacket.Action.*;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
public enum Action {
|
public enum Action {
|
||||||
|
|
||||||
USE {
|
USE("交互/使用/放置") {
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("resource")
|
@SuppressWarnings("resource")
|
||||||
public boolean tick(@NotNull ActionPack ap) {
|
public boolean tick(@NotNull ActionPack ap, @NotNull ActionSetting setting) {
|
||||||
if (ap.itemUseFreeze > 0) {
|
if (ap.use.freeze > 0) {
|
||||||
ap.itemUseFreeze--;
|
ap.use.freeze--;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +43,7 @@ public enum Action {
|
|||||||
var result = player.gameMode.useItemOn(player, world, player.getItemInHand(hand), hand, blockHit);
|
var result = player.gameMode.useItemOn(player, world, player.getItemInHand(hand), hand, blockHit);
|
||||||
if (result.consumesAction()) {
|
if (result.consumesAction()) {
|
||||||
player.swing(hand);
|
player.swing(hand);
|
||||||
ap.itemUseFreeze = 3;
|
ap.use.freeze = 3;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,18 +56,18 @@ public enum Action {
|
|||||||
boolean itemFrameEmpty = (entity instanceof ItemFrame) && ((ItemFrame) entity).getItem().isEmpty();
|
boolean itemFrameEmpty = (entity instanceof ItemFrame) && ((ItemFrame) entity).getItem().isEmpty();
|
||||||
var pos = entityHit.getLocation().subtract(entity.getX(), entity.getY(), entity.getZ());
|
var pos = entityHit.getLocation().subtract(entity.getX(), entity.getY(), entity.getZ());
|
||||||
if (entity.interactAt(player, pos, hand).consumesAction()) {
|
if (entity.interactAt(player, pos, hand).consumesAction()) {
|
||||||
ap.itemUseFreeze = 3;
|
ap.use.freeze = 3;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (player.interactOn(entity, hand).consumesAction() && !(handWasEmpty && itemFrameEmpty)) {
|
if (player.interactOn(entity, hand).consumesAction() && !(handWasEmpty && itemFrameEmpty)) {
|
||||||
ap.itemUseFreeze = 3;
|
ap.use.freeze = 3;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var handItem = player.getItemInHand(hand);
|
var handItem = player.getItemInHand(hand);
|
||||||
if (player.gameMode.useItem(player, player.level(), handItem, hand).consumesAction()) {
|
if (player.gameMode.useItem(player, player.level(), handItem, hand).consumesAction()) {
|
||||||
ap.itemUseFreeze = 3;
|
ap.use.freeze = 3;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,16 +75,16 @@ public enum Action {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop(@NotNull ActionPack ap) {
|
public void stop(@NotNull ActionPack ap, @NotNull ActionSetting setting) {
|
||||||
ap.itemUseFreeze = 0;
|
ap.use.freeze = 0;
|
||||||
ap.player.releaseUsingItem();
|
ap.player.releaseUsingItem();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
ATTACK {
|
ATTACK("攻击/破坏") {
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("resource")
|
@SuppressWarnings("resource")
|
||||||
public boolean tick(@NotNull ActionPack ap) {
|
public boolean tick(@NotNull ActionPack ap, @NotNull ActionSetting setting) {
|
||||||
var player = ap.player;
|
var player = ap.player;
|
||||||
var hit = getTarget(player);
|
var hit = getTarget(player);
|
||||||
switch (hit.getType()) {
|
switch (hit.getType()) {
|
||||||
@ -96,8 +97,8 @@ public enum Action {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case BLOCK -> {
|
case BLOCK -> {
|
||||||
if (ap.blockHitFreeze > 0) {
|
if (ap.attack.freeze > 0) {
|
||||||
ap.blockHitFreeze--;
|
ap.attack.freeze--;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,8 +110,8 @@ public enum Action {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ap.curBlockPos != null && player.level().getBlockState(ap.curBlockPos).isAir()) {
|
if (ap.attack.pos != null && player.level().getBlockState(ap.attack.pos).isAir()) {
|
||||||
ap.curBlockPos = null;
|
ap.attack.pos = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,11 +125,11 @@ public enum Action {
|
|||||||
player.level().getMaxBuildHeight(),
|
player.level().getMaxBuildHeight(),
|
||||||
-1
|
-1
|
||||||
);
|
);
|
||||||
ap.blockHitFreeze = 5;
|
ap.attack.freeze = 5;
|
||||||
} else if (ap.curBlockPos == null || !ap.curBlockPos.equals(pos)) {
|
} else if (ap.attack.pos == null || !ap.attack.pos.equals(pos)) {
|
||||||
if (ap.curBlockPos != null) {
|
if (ap.attack.pos != null) {
|
||||||
player.gameMode.handleBlockBreakAction(
|
player.gameMode.handleBlockBreakAction(
|
||||||
ap.curBlockPos,
|
ap.attack.pos,
|
||||||
ABORT_DESTROY_BLOCK,
|
ABORT_DESTROY_BLOCK,
|
||||||
side,
|
side,
|
||||||
player.level().getMaxBuildHeight(),
|
player.level().getMaxBuildHeight(),
|
||||||
@ -144,20 +145,20 @@ public enum Action {
|
|||||||
-1
|
-1
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!state.isAir() && ap.curBlockPgs == 0) {
|
if (!state.isAir() && ap.attack.progress == 0) {
|
||||||
state.attack(player.level(), pos, player);
|
state.attack(player.level(), pos, player);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!state.isAir() && state.getDestroyProgress(player, player.level(), pos) >= 1) {
|
if (!state.isAir() && state.getDestroyProgress(player, player.level(), pos) >= 1) {
|
||||||
ap.curBlockPos = null;
|
ap.attack.pos = null;
|
||||||
broken = true;
|
broken = true;
|
||||||
} else {
|
} else {
|
||||||
ap.curBlockPos = pos;
|
ap.attack.pos = pos;
|
||||||
ap.curBlockPgs = 0;
|
ap.attack.progress = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ap.curBlockPgs += state.getDestroyProgress(player, player.level(), pos);
|
ap.attack.progress += state.getDestroyProgress(player, player.level(), pos);
|
||||||
if (ap.curBlockPgs >= 1) {
|
if (ap.attack.progress >= 1) {
|
||||||
player.gameMode.handleBlockBreakAction(
|
player.gameMode.handleBlockBreakAction(
|
||||||
pos,
|
pos,
|
||||||
STOP_DESTROY_BLOCK,
|
STOP_DESTROY_BLOCK,
|
||||||
@ -165,11 +166,11 @@ public enum Action {
|
|||||||
player.level().getMaxBuildHeight(),
|
player.level().getMaxBuildHeight(),
|
||||||
-1
|
-1
|
||||||
);
|
);
|
||||||
ap.curBlockPos = null;
|
ap.attack.pos = null;
|
||||||
ap.blockHitFreeze = 5;
|
ap.attack.freeze = 5;
|
||||||
broken = true;
|
broken = true;
|
||||||
}
|
}
|
||||||
player.level().destroyBlockProgress(-1, pos, (int) (ap.curBlockPgs * 10));
|
player.level().destroyBlockProgress(-1, pos, (int) (ap.attack.progress * 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
player.resetLastActionTime();
|
player.resetLastActionTime();
|
||||||
@ -181,30 +182,52 @@ public enum Action {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop(@NotNull ActionPack ap) {
|
@SuppressWarnings("resource")
|
||||||
if (ap.curBlockPos == null) {
|
public void stop(@NotNull ActionPack ap, @NotNull ActionSetting setting) {
|
||||||
|
if (ap.attack.pos == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var player = ap.player;
|
var player = ap.player;
|
||||||
player.level().destroyBlockProgress(-1, ap.curBlockPos, -1);
|
player.level().destroyBlockProgress(-1, ap.attack.pos, -1);
|
||||||
player.gameMode.handleBlockBreakAction(
|
player.gameMode.handleBlockBreakAction(
|
||||||
ap.curBlockPos,
|
ap.attack.pos,
|
||||||
ABORT_DESTROY_BLOCK,
|
ABORT_DESTROY_BLOCK,
|
||||||
Direction.DOWN,
|
Direction.DOWN,
|
||||||
player.level().getMaxBuildHeight(),
|
player.level().getMaxBuildHeight(),
|
||||||
-1
|
-1
|
||||||
);
|
);
|
||||||
ap.curBlockPos = null;
|
ap.attack.pos = null;
|
||||||
ap.blockHitFreeze = 0;
|
ap.attack.freeze = 0;
|
||||||
ap.curBlockPgs = 0;
|
ap.attack.progress = 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
JUMP("跳") {
|
||||||
|
@Override
|
||||||
|
public boolean tick(@NotNull ActionPack ap, @NotNull ActionSetting setting) {
|
||||||
|
var player = ap.player;
|
||||||
|
if (setting.limit == 1) {
|
||||||
|
if (player.onGround()) {
|
||||||
|
player.jumpFromGround();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
player.setJumping(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void inactiveTick(@NotNull ActionPack ap, @NotNull ActionSetting setting) {
|
||||||
|
ap.player.setJumping(false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
DROP_ITEM {
|
DROP_ITEM("丢弃手上物品") {
|
||||||
@Override
|
@Override
|
||||||
public boolean tick(@NotNull ActionPack ap) {
|
public boolean tick(@NotNull ActionPack ap, @NotNull ActionSetting setting) {
|
||||||
var player = ap.player;
|
var player = ap.player;
|
||||||
player.resetLastActionTime();
|
player.resetLastActionTime();
|
||||||
player.drop(false);
|
player.drop(false);
|
||||||
@ -212,9 +235,9 @@ public enum Action {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
DROP_STACK {
|
DROP_STACK("丢弃手上整组物品") {
|
||||||
@Override
|
@Override
|
||||||
public boolean tick(@NotNull ActionPack ap) {
|
public boolean tick(@NotNull ActionPack ap, @NotNull ActionSetting setting) {
|
||||||
var player = ap.player;
|
var player = ap.player;
|
||||||
player.resetLastActionTime();
|
player.resetLastActionTime();
|
||||||
player.drop(true);
|
player.drop(true);
|
||||||
@ -222,9 +245,9 @@ public enum Action {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
DROP_INVENTORY {
|
DROP_INVENTORY("丢弃背包物品") {
|
||||||
@Override
|
@Override
|
||||||
public boolean tick(@NotNull ActionPack ap) {
|
public boolean tick(@NotNull ActionPack ap, @NotNull ActionSetting setting) {
|
||||||
var player = ap.player;
|
var player = ap.player;
|
||||||
dropInventory(player);
|
dropInventory(player);
|
||||||
return true;
|
return true;
|
||||||
@ -232,6 +255,8 @@ public enum Action {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
public final String name;
|
||||||
|
|
||||||
static HitResult getTarget(ServerPlayer player) {
|
static HitResult getTarget(ServerPlayer player) {
|
||||||
double reach = player.gameMode.isCreative() ? 5 : 4.5f;
|
double reach = player.gameMode.isCreative() ? 5 : 4.5f;
|
||||||
return Tracer.rayTrace(player, 1, reach, false);
|
return Tracer.rayTrace(player, 1, reach, false);
|
||||||
@ -244,31 +269,13 @@ public enum Action {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract boolean tick(@NotNull ActionPack ap);
|
|
||||||
|
|
||||||
public void stop(@NotNull ActionPack ap) {}
|
public abstract boolean tick(@NotNull ActionPack ap, @NotNull ActionSetting setting);
|
||||||
|
|
||||||
public void inactiveTick(@NotNull ActionPack ap) {
|
public void stop(@NotNull ActionPack ap, @NotNull ActionSetting setting) {}
|
||||||
this.stop(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ActionPack {
|
|
||||||
|
|
||||||
public final ServerPlayer player;
|
|
||||||
|
|
||||||
// attack
|
|
||||||
public BlockPos curBlockPos;
|
|
||||||
public float curBlockPgs;
|
|
||||||
public int blockHitFreeze;
|
|
||||||
|
|
||||||
|
|
||||||
// use
|
|
||||||
public int itemUseFreeze;
|
|
||||||
|
|
||||||
public ActionPack(ServerPlayer player) {
|
|
||||||
this.player = player;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public void inactiveTick(@NotNull ActionPack ap, @NotNull ActionSetting setting) {
|
||||||
|
this.stop(ap, setting);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,13 +5,13 @@ import net.minecraft.server.level.ServerPlayer;
|
|||||||
public class ActionManager {
|
public class ActionManager {
|
||||||
|
|
||||||
public final Action action;
|
public final Action action;
|
||||||
public final Action.ActionPack actionPack;
|
public final ActionPack actionPack;
|
||||||
public ActionSetting setting;
|
public ActionSetting setting;
|
||||||
|
|
||||||
public ActionManager(ServerPlayer player, Action action, ActionSetting setting) {
|
public ActionManager(ServerPlayer player, Action action, ActionSetting setting) {
|
||||||
this.action = action;
|
this.action = action;
|
||||||
this.setting = setting;
|
this.setting = setting;
|
||||||
this.actionPack = new Action.ActionPack(player);
|
this.actionPack = new ActionPack(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tick() {
|
public void tick() {
|
||||||
@ -26,7 +26,7 @@ public class ActionManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var done = action.tick(this.actionPack);
|
var done = action.tick(this.actionPack, this.setting);
|
||||||
if (done) {
|
if (done) {
|
||||||
if (setting.times > 0) {
|
if (setting.times > 0) {
|
||||||
setting.times--;
|
setting.times--;
|
||||||
@ -36,11 +36,11 @@ public class ActionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void inactiveTick() {
|
public void inactiveTick() {
|
||||||
action.inactiveTick(this.actionPack);
|
action.inactiveTick(this.actionPack, this.setting);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stop() {
|
public void stop() {
|
||||||
action.stop(this.actionPack);
|
action.stop(this.actionPack, this.setting);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
package io.github.hello09x.fakeplayer.entity.action;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
|
||||||
|
public class ActionPack {
|
||||||
|
|
||||||
|
public final ServerPlayer player;
|
||||||
|
|
||||||
|
public final AttackActionPack attack = new AttackActionPack();
|
||||||
|
|
||||||
|
public final UseActionPack use = new UseActionPack();
|
||||||
|
|
||||||
|
public ActionPack(ServerPlayer player) {
|
||||||
|
this.player = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static class AttackActionPack {
|
||||||
|
public BlockPos pos;
|
||||||
|
public float progress;
|
||||||
|
public int freeze;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static class UseActionPack {
|
||||||
|
public int freeze;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,9 +1,17 @@
|
|||||||
package io.github.hello09x.fakeplayer.entity.action;
|
package io.github.hello09x.fakeplayer.entity.action;
|
||||||
|
|
||||||
public class ActionSetting {
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@EqualsAndHashCode
|
||||||
|
public class ActionSetting implements Cloneable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 次数
|
* 总次数
|
||||||
|
*/
|
||||||
|
public final int limit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 剩余次数
|
||||||
*/
|
*/
|
||||||
public int times;
|
public int times;
|
||||||
|
|
||||||
@ -18,31 +26,38 @@ public class ActionSetting {
|
|||||||
public int wait;
|
public int wait;
|
||||||
|
|
||||||
public ActionSetting(int times, int interval) {
|
public ActionSetting(int times, int interval) {
|
||||||
this.times = times;
|
this(times, interval, 0);
|
||||||
this.interval = interval;
|
|
||||||
this.wait = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionSetting(int times, int interval, int wait) {
|
public ActionSetting(int times, int interval, int wait) {
|
||||||
|
this.limit = times;
|
||||||
this.times = times;
|
this.times = times;
|
||||||
this.interval = interval;
|
this.interval = interval;
|
||||||
this.wait = wait;
|
this.wait = wait;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ActionSetting once() {
|
public static ActionSetting once() {
|
||||||
return new ActionSetting(1, 1, 0);
|
return new ActionSetting(1, 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ActionSetting stop() {
|
public static ActionSetting stop() {
|
||||||
return new ActionSetting(0, 1, 0);
|
return new ActionSetting(0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ActionSetting interval(int interval) {
|
public static ActionSetting interval(int interval) {
|
||||||
return new ActionSetting(-1, interval, 0);
|
return new ActionSetting(-1, interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ActionSetting continuous() {
|
public static ActionSetting continuous() {
|
||||||
return new ActionSetting(-1, 1, 0);
|
return new ActionSetting(-1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionSetting clone() {
|
||||||
|
return new ActionSetting(
|
||||||
|
this.times,
|
||||||
|
this.interval,
|
||||||
|
this.wait
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ public class PlayerListeners implements Listener {
|
|||||||
* 拒绝假人用过的 ID 上线
|
* 拒绝假人用过的 ID 上线
|
||||||
*/
|
*/
|
||||||
@EventHandler(ignoreCancelled = true)
|
@EventHandler(ignoreCancelled = true)
|
||||||
public void handleUsedIdLogin(@NotNull AsyncPlayerPreLoginEvent event) {
|
public void onLogin(@NotNull AsyncPlayerPreLoginEvent event) {
|
||||||
if (event.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) {
|
if (event.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -49,7 +49,7 @@ public class PlayerListeners implements Listener {
|
|||||||
* 死亡退出游戏
|
* 死亡退出游戏
|
||||||
*/
|
*/
|
||||||
@EventHandler(ignoreCancelled = true)
|
@EventHandler(ignoreCancelled = true)
|
||||||
public void handlePlayerDeath(@NotNull PlayerDeathEvent event) {
|
public void onDead(@NotNull PlayerDeathEvent event) {
|
||||||
var player = event.getPlayer();
|
var player = event.getPlayer();
|
||||||
if (!manager.isFake(player)) {
|
if (!manager.isFake(player)) {
|
||||||
return;
|
return;
|
||||||
@ -63,7 +63,7 @@ public class PlayerListeners implements Listener {
|
|||||||
* 退出游戏掉落背包
|
* 退出游戏掉落背包
|
||||||
*/
|
*/
|
||||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||||
public void handlePlayerQuit(@NotNull PlayerQuitEvent event) {
|
public void onQuit(@NotNull PlayerQuitEvent event) {
|
||||||
var player = event.getPlayer();
|
var player = event.getPlayer();
|
||||||
if (!manager.isFake(player)) {
|
if (!manager.isFake(player)) {
|
||||||
return;
|
return;
|
||||||
|
@ -122,7 +122,7 @@ public class FakeplayerManager {
|
|||||||
|
|
||||||
usedIdRepository.add(bukkitPlayer.getUniqueId());
|
usedIdRepository.add(bukkitPlayer.getUniqueId());
|
||||||
dispatchCommands(bukkitPlayer, properties.getPreparingCommands());
|
dispatchCommands(bukkitPlayer, properties.getPreparingCommands());
|
||||||
performCommands(bukkitPlayer);
|
performCommands(bukkitPlayer, properties.getSelfCommands());
|
||||||
|
|
||||||
bukkitPlayer.teleport(spawnAt); // 当前 tick 必须传到出生点否则无法触发区块刷新
|
bukkitPlayer.teleport(spawnAt); // 当前 tick 必须传到出生点否则无法触发区块刷新
|
||||||
spawnAt.getWorld().playSound(spawnAt, Sound.ENTITY_ENDERMAN_TELEPORT, 1.0F, 1.0F);
|
spawnAt.getWorld().playSound(spawnAt, Sound.ENTITY_ENDERMAN_TELEPORT, 1.0F, 1.0F);
|
||||||
@ -239,9 +239,7 @@ public class FakeplayerManager {
|
|||||||
Metadatas.NAME_SEQUENCE.get(fakePlayer).asInt()
|
Metadatas.NAME_SEQUENCE.get(fakePlayer).asInt()
|
||||||
);
|
);
|
||||||
Arrays.stream(Metadatas.values()).forEach(meta -> meta.remove(fakePlayer));
|
Arrays.stream(Metadatas.values()).forEach(meta -> meta.remove(fakePlayer));
|
||||||
if (properties.isDropInventoryOnQuiting()) {
|
Action.dropInventory(Unwrapper.getServerPlayer(fakePlayer));
|
||||||
Action.dropInventory(Unwrapper.getServerPlayer(fakePlayer));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -298,12 +296,15 @@ public class FakeplayerManager {
|
|||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void performCommands(@NotNull Player player) {
|
public void performCommands(@NotNull Player player, @NotNull List<String> commands) {
|
||||||
|
if (commands.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!isFake(player)) {
|
if (!isFake(player)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var cmd : properties.getSelfCommands()) {
|
for (var cmd : commands) {
|
||||||
cmd = cmd.trim();
|
cmd = cmd.trim();
|
||||||
if (cmd.startsWith("/")) {
|
if (cmd.startsWith("/")) {
|
||||||
cmd = cmd.substring(1);
|
cmd = cmd.substring(1);
|
||||||
@ -327,7 +328,7 @@ public class FakeplayerManager {
|
|||||||
|
|
||||||
var server = Bukkit.getServer();
|
var server = Bukkit.getServer();
|
||||||
var sender = Bukkit.getConsoleSender();
|
var sender = Bukkit.getConsoleSender();
|
||||||
for (var cmd : properties.getPreparingCommands()) {
|
for (var cmd : commands) {
|
||||||
cmd = cmd.trim();
|
cmd = cmd.trim();
|
||||||
if (cmd.startsWith("/")) {
|
if (cmd.startsWith("/")) {
|
||||||
cmd = cmd.substring(1);
|
cmd = cmd.substring(1);
|
||||||
|
@ -77,11 +77,6 @@ public class FakeplayerProperties extends AbstractProperties<FakeplayerPropertie
|
|||||||
*/
|
*/
|
||||||
private boolean simulateLogin;
|
private boolean simulateLogin;
|
||||||
|
|
||||||
/**
|
|
||||||
* 下线时是否丢弃背包
|
|
||||||
*/
|
|
||||||
private boolean dropInventoryOnQuiting;
|
|
||||||
|
|
||||||
public FakeplayerProperties(@NotNull JavaPlugin plugin, @NotNull String version) {
|
public FakeplayerProperties(@NotNull JavaPlugin plugin, @NotNull String version) {
|
||||||
super(plugin, version);
|
super(plugin, version);
|
||||||
}
|
}
|
||||||
@ -102,7 +97,6 @@ public class FakeplayerProperties extends AbstractProperties<FakeplayerPropertie
|
|||||||
this.destroyCommands = file.getStringList("destroy-commands");
|
this.destroyCommands = file.getStringList("destroy-commands");
|
||||||
this.nameTemplate = file.getString("name-template", "");
|
this.nameTemplate = file.getString("name-template", "");
|
||||||
this.simulateLogin = file.getBoolean("simulate-login", false);
|
this.simulateLogin = file.getBoolean("simulate-login", false);
|
||||||
this.dropInventoryOnQuiting = file.getBoolean("drop-inventory-on-quiting", true);
|
|
||||||
|
|
||||||
if (this.nameTemplate.startsWith("-")) {
|
if (this.nameTemplate.startsWith("-")) {
|
||||||
log.warning("假人名称模版不能以 - 开头, 该配置不会生效: " + this.nameTemplate);
|
log.warning("假人名称模版不能以 - 开头, 该配置不会生效: " + this.nameTemplate);
|
||||||
|
@ -10,5 +10,9 @@ public class MathUtils {
|
|||||||
return Math.floor(num / base) * base;
|
return Math.floor(num / base) * base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static float clamp(float value, float min, float max) {
|
||||||
|
return value < min ? min : Math.min(value, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,16 +24,6 @@ name-template: ''
|
|||||||
# 如果玩家只是切换服务器, 那么不会触发跟随下线
|
# 如果玩家只是切换服务器, 那么不会触发跟随下线
|
||||||
follow-quiting: true
|
follow-quiting: true
|
||||||
|
|
||||||
# 下线时是否丢弃背包
|
|
||||||
# 如果服务器有背包同步之类的插件,请验证是否会有复制 bug
|
|
||||||
# 这个 bug 原因是先保存了背包再丢弃背包的物品导致地上和背包各一份
|
|
||||||
# 验证方法如下:
|
|
||||||
# 1. 创建假人,并给他一点东西
|
|
||||||
# 2. kick 掉假人, 此时他会丢弃背包的物品
|
|
||||||
# 3. 重新创建假人, 看看他背包的物品是否多了一份
|
|
||||||
drop-inventory-on-quiting: true
|
|
||||||
|
|
||||||
# 是否检测 IP
|
|
||||||
# 如果启用, 则一个 IP 只能创建 `maximum` 个假人
|
# 如果启用, 则一个 IP 只能创建 `maximum` 个假人
|
||||||
# 能够避免玩家开小号疯狂创建假人
|
# 能够避免玩家开小号疯狂创建假人
|
||||||
detect-ip: true
|
detect-ip: true
|
||||||
@ -75,7 +65,7 @@ destroy-commands:
|
|||||||
|
|
||||||
# 自执行命令
|
# 自执行命令
|
||||||
# 假人在诞生时会以自己的身份按顺序执行命令
|
# 假人在诞生时会以自己的身份按顺序执行命令
|
||||||
# 你可以在这里做一些 /register 之类的命令
|
# 你可以在这里做添加 /register 和 /login 命令来防止 `AuthMe` 等插件踢掉超时未登陆的玩家
|
||||||
self-commands:
|
self-commands:
|
||||||
- ''
|
- ''
|
||||||
- ''
|
- ''
|
||||||
|
@ -32,7 +32,7 @@ permissions:
|
|||||||
default: op
|
default: op
|
||||||
|
|
||||||
fakeplayer.action:
|
fakeplayer.action:
|
||||||
description: '拥有 drop, dropinv, sneak 命令权限'
|
description: '拥有 drop, dropinv, sneak, look, move, jump 命令权限'
|
||||||
default: op
|
default: op
|
||||||
|
|
||||||
fakeplayer.experimental.action:
|
fakeplayer.experimental.action:
|
||||||
|
Loading…
Reference in New Issue
Block a user