diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/ServerMain.java b/src/main/java/com/github/zly2006/carpetslsaddition/ServerMain.java index 2e289f7..8999949 100644 --- a/src/main/java/com/github/zly2006/carpetslsaddition/ServerMain.java +++ b/src/main/java/com/github/zly2006/carpetslsaddition/ServerMain.java @@ -2,6 +2,7 @@ package com.github.zly2006.carpetslsaddition; import carpet.CarpetExtension; import carpet.CarpetServer; +import com.github.zly2006.carpetslsaddition.command.BotAllCommand; import com.github.zly2006.carpetslsaddition.command.BotCommand; import com.github.zly2006.carpetslsaddition.command.HatCommand; import com.github.zly2006.carpetslsaddition.command.SitCommand; @@ -81,6 +82,7 @@ public class ServerMain implements ModInitializer, CarpetExtension { HatCommand.register(dispatcher); SitCommand.register(dispatcher); BotCommand.register(dispatcher); + BotAllCommand.register(dispatcher); LOGGER.info("[SLSA] commands registered: hat/sit/bot"); } catch (Throwable t) { LOGGER.error("[SLSA] failed to register commands", t); diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/command/BotAllCommand.java b/src/main/java/com/github/zly2006/carpetslsaddition/command/BotAllCommand.java new file mode 100644 index 0000000..d0b6afe --- /dev/null +++ b/src/main/java/com/github/zly2006/carpetslsaddition/command/BotAllCommand.java @@ -0,0 +1,84 @@ +package com.github.zly2006.carpetslsaddition.command; + +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.builder.LiteralArgumentBuilder; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; + +import java.util.ArrayList; +import java.util.List; + +import static net.minecraft.commands.Commands.literal; + +/** + * /botall —— 批量控制本模组生成的所有假人。 + * + *

与 {@link BotCommand} 的区别:{@code /bot } 操作单个指定玩家, + * 而 {@code /botall} 操作所有由本模组(Carpet SLS Addition)生成的假人(即 isBot() 为 true 的 EntityPlayerMPFake)。 + */ +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")) + .then(literal("sit").executes(BotAllCommand::sitAll)) + .then(literal("stand").executes(BotAllCommand::standAll)); + dispatcher.register(command); + } + + /** 收集所有本模组生成的假人。 */ + private static List collectBots(CommandSourceStack source) { + MinecraftServer server = source.getServer(); + List bots = new ArrayList<>(); + for (ServerPlayer player : server.getPlayerList().getPlayers()) { + if (player instanceof EntityPlayerMPFake && ((SLSBotAccessor) player).carpet_SLS_Addition$isBot()) { + bots.add(player); + } + } + return bots; + } + + /** 批量坐下。 */ + private static int sitAll(com.mojang.brigadier.context.CommandContext context) { + if (!SLSCarpetSettings.canUseSitCommand) { + Messenger.m(context.getSource(), "r 坐下功能未启用(canUseSitCommand)"); + return 0; + } + List bots = collectBots(context.getSource()); + int ok = 0; + for (ServerPlayer bot : bots) { + if (SitCommand.sitPlayer(bot)) { + ok++; + } + } + final int done = ok; + 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) { + List bots = collectBots(context.getSource()); + int ok = 0; + for (ServerPlayer bot : bots) { + if (bot.getVehicle() != null) { + bot.stopRiding(); + ok++; + } + } + final int done = ok; + context.getSource().sendSuccess( + () -> net.minecraft.network.chat.Component.literal( + "[SLSA] 已让 " + done + "/" + bots.size() + " 个假人站起"), + false); + return ok; + } +} \ No newline at end of file diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/command/SitCommand.java b/src/main/java/com/github/zly2006/carpetslsaddition/command/SitCommand.java index 5406532..13aae54 100644 --- a/src/main/java/com/github/zly2006/carpetslsaddition/command/SitCommand.java +++ b/src/main/java/com/github/zly2006/carpetslsaddition/command/SitCommand.java @@ -20,21 +20,27 @@ public class SitCommand { if (player == null) { return 0; } - - if (player.getVehicle() != null || !player.onGround()) { // 防止错误的坐下行为 - return 1; - } - - ServerLevel world = (ServerLevel) player.level(); - - ArmorStand armorStandEntity = new ArmorStand(world, player.getX(), player.getY(), player.getZ()); - ((SitEntity) armorStandEntity).setSitEntity(true); - world.addFreshEntity(armorStandEntity); - player.setShiftKeyDown(false); - player.startRiding(armorStandEntity); - + sitPlayer(player); return 1; }) ); } + + /** + * 让指定玩家原地坐下(生成一个标记为 SitEntity 的 ArmorStand 并骑乘)。 + * + * @return 若成功坐下返回 true,否则返回 false(如已在骑乘/不在地面)。 + */ + public static boolean sitPlayer(ServerPlayer player) { + if (player.getVehicle() != null || !player.onGround()) { // 防止错误的坐下行为 + return false; + } + ServerLevel world = (ServerLevel) player.level(); + ArmorStand armorStandEntity = new ArmorStand(world, player.getX(), player.getY(), player.getZ()); + ((SitEntity) armorStandEntity).setSitEntity(true); + world.addFreshEntity(armorStandEntity); + player.setShiftKeyDown(false); + player.startRiding(armorStandEntity); + return true; + } } \ No newline at end of file