From 541ffe5ed25d2d7a05709dab3357bb5b7d39a083 Mon Sep 17 00:00:00 2001
From: Ap_Tx <3045929398@qq.com>
Date: Mon, 5 Oct 2026 10:45:29 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20/botall=E6=94=AF=E6=8C=81=E5=85=A8?=
=?UTF-8?q?=E5=A5=97=E5=81=87=E4=BA=BA=E6=93=8D=E4=BD=9C=EF=BC=88=E7=A7=BB?=
=?UTF-8?q?=E5=8A=A8/=E7=9C=8B=E5=90=91/=E5=8A=A8=E4=BD=9C/=E9=AA=91?=
=?UTF-8?q?=E4=B9=98=E7=AD=89=EF=BC=89?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
镜像BotCommand的action结构,对isBot()假人批量执行。修复权限判断用Commands.LEVEL_OWNERS.check。
---
.../command/BotAllCommand.java | 112 +++++++++++++++---
1 file changed, 93 insertions(+), 19 deletions(-)
diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/command/BotAllCommand.java b/src/main/java/com/github/zly2006/carpetslsaddition/command/BotAllCommand.java
index d0b6afe..9b6d0a7 100644
--- a/src/main/java/com/github/zly2006/carpetslsaddition/command/BotAllCommand.java
+++ b/src/main/java/com/github/zly2006/carpetslsaddition/command/BotAllCommand.java
@@ -1,36 +1,117 @@
package com.github.zly2006.carpetslsaddition.command;
+import carpet.fakes.ServerPlayerInterface;
+import carpet.helpers.EntityPlayerActionPack;
import carpet.patches.EntityPlayerMPFake;
-import carpet.utils.Messenger;
import com.github.zly2006.carpetslsaddition.SLSCarpetSettings;
import com.github.zly2006.carpetslsaddition.util.access.SLSBotAccessor;
import com.mojang.brigadier.CommandDispatcher;
+import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
+import com.mojang.brigadier.context.CommandContext;
import net.minecraft.commands.CommandSourceStack;
+import net.minecraft.commands.Commands;
+import net.minecraft.commands.arguments.coordinates.RotationArgument;
+import net.minecraft.commands.arguments.coordinates.Vec3Argument;
+import net.minecraft.core.Direction;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import java.util.ArrayList;
import java.util.List;
+import java.util.function.Consumer;
+import static net.minecraft.commands.Commands.argument;
import static net.minecraft.commands.Commands.literal;
/**
* /botall —— 批量控制本模组生成的所有假人。
*
*
与 {@link BotCommand} 的区别:{@code /bot } 操作单个指定玩家,
- * 而 {@code /botall} 操作所有由本模组(Carpet SLS Addition)生成的假人(即 isBot() 为 true 的 EntityPlayerMPFake)。
+ * 而 {@code /botall} 对其余命令中出现的所有本模组假人(isBot()==true)批量执行同一操作。
*/
public class BotAllCommand {
public static void register(CommandDispatcher dispatcher) {
LiteralArgumentBuilder command = literal("botall")
- .requires(source -> source.hasPermission(4) || me.lucko.fabric.api.permissions.v0.Permissions.check(source, "slsaddition.command.bot"))
+ .requires(source -> Commands.LEVEL_OWNERS.check(source.permissions()) || me.lucko.fabric.api.permissions.v0.Permissions.check(source, "slsaddition.command.bot"))
+ .then(literal("stop").executes(batch(EntityPlayerActionPack::stopAll)))
+ .then(actionCommand("use", EntityPlayerActionPack.ActionType.USE))
+ .then(actionCommand("jump", EntityPlayerActionPack.ActionType.JUMP))
+ .then(actionCommand("attack", EntityPlayerActionPack.ActionType.ATTACK))
+ .then(actionCommand("drop", EntityPlayerActionPack.ActionType.DROP_ITEM))
+ .then(dropCommand("dropStack", true))
+ .then(actionCommand("swapHands", EntityPlayerActionPack.ActionType.SWAP_HANDS))
+ .then(literal("hotbar").then(argument("slot", IntegerArgumentType.integer(1, 9))
+ .executes(c -> batchAp(c, ap -> ap.setSlot(IntegerArgumentType.getInteger(c, "slot"))))))
+ .then(literal("mount").executes(batch(ap -> ap.mount(true)))
+ .then(literal("anything").executes(batch(ap -> ap.mount(false)))))
+ .then(literal("dismount").executes(batch(EntityPlayerActionPack::dismount)))
+ .then(literal("sneak").executes(batch(ap -> ap.setSneaking(true))))
+ .then(literal("unsneak").executes(batch(ap -> ap.setSneaking(false))))
+ .then(literal("sprint").executes(batch(ap -> ap.setSprinting(true))))
+ .then(literal("unsprint").executes(batch(ap -> ap.setSprinting(false))))
+ .then(literal("look")
+ .then(literal("north").executes(batch(ap -> ap.look(Direction.NORTH))))
+ .then(literal("south").executes(batch(ap -> ap.look(Direction.SOUTH))))
+ .then(literal("east").executes(batch(ap -> ap.look(Direction.EAST))))
+ .then(literal("west").executes(batch(ap -> ap.look(Direction.WEST))))
+ .then(literal("up").executes(batch(ap -> ap.look(Direction.UP))))
+ .then(literal("down").executes(batch(ap -> ap.look(Direction.DOWN))))
+ .then(literal("at").then(argument("position", Vec3Argument.vec3())
+ .executes(c -> batchAp(c, ap -> ap.lookAt(Vec3Argument.getVec3(c, "position"))))))
+ .then(argument("direction", RotationArgument.rotation())
+ .executes(c -> batchAp(c, ap -> ap.look(RotationArgument.getRotation(c, "direction").getRotation(c.getSource()))))))
+ .then(literal("turn")
+ .then(literal("left").executes(batch(ap -> ap.turn(-90, 0))))
+ .then(literal("right").executes(batch(ap -> ap.turn(90, 0))))
+ .then(literal("back").executes(batch(ap -> ap.turn(180, 0))))
+ .then(argument("rotation", RotationArgument.rotation())
+ .executes(c -> batchAp(c, ap -> ap.turn(RotationArgument.getRotation(c, "rotation").getRotation(c.getSource()))))))
+ .then(literal("move").executes(batch(EntityPlayerActionPack::stopMovement))
+ .then(literal("forward").executes(batch(ap -> ap.setForward(1))))
+ .then(literal("backward").executes(batch(ap -> ap.setForward(-1))))
+ .then(literal("left").executes(batch(ap -> ap.setStrafing(1))))
+ .then(literal("right").executes(batch(ap -> ap.setStrafing(-1)))))
.then(literal("sit").executes(BotAllCommand::sitAll))
.then(literal("stand").executes(BotAllCommand::standAll));
dispatcher.register(command);
}
+ private static LiteralArgumentBuilder actionCommand(String name, EntityPlayerActionPack.ActionType type) {
+ return literal(name)
+ .executes(batch(ap -> ap.start(type, EntityPlayerActionPack.Action.once())))
+ .then(literal("once").executes(batch(ap -> ap.start(type, EntityPlayerActionPack.Action.once()))))
+ .then(literal("continuous").executes(batch(ap -> ap.start(type, EntityPlayerActionPack.Action.continuous()))))
+ .then(literal("interval").then(argument("ticks", IntegerArgumentType.integer(1))
+ .executes(c -> batchAp(c, ap -> ap.start(type, EntityPlayerActionPack.Action.interval(IntegerArgumentType.getInteger(c, "ticks")))))));
+ }
+
+ private static LiteralArgumentBuilder dropCommand(String name, boolean dropAll) {
+ return literal(name)
+ .then(literal("all").executes(batch(ap -> ap.drop(-2, dropAll))))
+ .then(literal("mainhand").executes(batch(ap -> ap.drop(-1, dropAll))))
+ .then(literal("offhand").executes(batch(ap -> ap.drop(40, dropAll))))
+ .then(argument("slot", IntegerArgumentType.integer(0, 40))
+ .executes(c -> batchAp(c, ap -> ap.drop(IntegerArgumentType.getInteger(c, "slot"), dropAll))));
+ }
+
+ /** 批量执行一个 action pack 操作。 */
+ private static int batchAp(CommandContext context, Consumer action) {
+ List bots = collectBots(context.getSource());
+ for (ServerPlayer bot : bots) {
+ action.accept(((ServerPlayerInterface) bot).getActionPack());
+ }
+ final int n = bots.size();
+ context.getSource().sendSuccess(
+ () -> net.minecraft.network.chat.Component.literal("[SLSA] 已对 " + n + " 个假人执行操作"), false);
+ return n;
+ }
+
+ private static com.mojang.brigadier.Command batch(Consumer action) {
+ return c -> batchAp(c, action);
+ }
+
/** 收集所有本模组生成的假人。 */
private static List collectBots(CommandSourceStack source) {
MinecraftServer server = source.getServer();
@@ -43,29 +124,24 @@ public class BotAllCommand {
return bots;
}
- /** 批量坐下。 */
- private static int sitAll(com.mojang.brigadier.context.CommandContext context) {
+ private static int sitAll(CommandContext context) {
if (!SLSCarpetSettings.canUseSitCommand) {
- Messenger.m(context.getSource(), "r 坐下功能未启用(canUseSitCommand)");
+ context.getSource().sendSuccess(() -> net.minecraft.network.chat.Component.literal(
+ "[SLSA] 坐下功能未启用(canUseSitCommand)"), false);
return 0;
}
List bots = collectBots(context.getSource());
int ok = 0;
for (ServerPlayer bot : bots) {
- if (SitCommand.sitPlayer(bot)) {
- ok++;
- }
+ if (SitCommand.sitPlayer(bot)) ok++;
}
final int done = ok;
- context.getSource().sendSuccess(
- () -> net.minecraft.network.chat.Component.literal(
- "[SLSA] 已让 " + done + "/" + bots.size() + " 个假人坐下"),
- false);
+ context.getSource().sendSuccess(() -> net.minecraft.network.chat.Component.literal(
+ "[SLSA] 已让 " + done + "/" + bots.size() + " 个假人坐下"), false);
return ok;
}
- /** 批量站起(下坐骑)。 */
- private static int standAll(com.mojang.brigadier.context.CommandContext context) {
+ private static int standAll(CommandContext context) {
List bots = collectBots(context.getSource());
int ok = 0;
for (ServerPlayer bot : bots) {
@@ -75,10 +151,8 @@ public class BotAllCommand {
}
}
final int done = ok;
- context.getSource().sendSuccess(
- () -> net.minecraft.network.chat.Component.literal(
- "[SLSA] 已让 " + done + "/" + bots.size() + " 个假人站起"),
- false);
+ context.getSource().sendSuccess(() -> net.minecraft.network.chat.Component.literal(
+ "[SLSA] 已让 " + done + "/" + bots.size() + " 个假人站起"), false);
return ok;
}
}
\ No newline at end of file