feat: 新增/botlist假人名单管理,/botall按名单过滤
名单持久化到config/slsa-bot-list.json。名单非空时/botall只操作名单内假人,为空时操作所有。支持add/remove/clear/show/addall。
This commit is contained in:
1 parent
541ffe5ed2
commit
ccbf442413
4 files changed
+208
-2
No files matched your search
@@ -4,6 +4,7 @@ import carpet.CarpetExtension;
|
|||||||
import carpet.CarpetServer;
|
import carpet.CarpetServer;
|
||||||
import com.github.zly2006.carpetslsaddition.command.BotAllCommand;
|
import com.github.zly2006.carpetslsaddition.command.BotAllCommand;
|
||||||
import com.github.zly2006.carpetslsaddition.command.BotCommand;
|
import com.github.zly2006.carpetslsaddition.command.BotCommand;
|
||||||
|
import com.github.zly2006.carpetslsaddition.command.BotListCommand;
|
||||||
import com.github.zly2006.carpetslsaddition.command.HatCommand;
|
import com.github.zly2006.carpetslsaddition.command.HatCommand;
|
||||||
import com.github.zly2006.carpetslsaddition.command.SitCommand;
|
import com.github.zly2006.carpetslsaddition.command.SitCommand;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
@@ -83,6 +84,7 @@ public class ServerMain implements ModInitializer, CarpetExtension {
|
|||||||
SitCommand.register(dispatcher);
|
SitCommand.register(dispatcher);
|
||||||
BotCommand.register(dispatcher);
|
BotCommand.register(dispatcher);
|
||||||
BotAllCommand.register(dispatcher);
|
BotAllCommand.register(dispatcher);
|
||||||
|
BotListCommand.register(dispatcher);
|
||||||
LOGGER.info("[SLSA] commands registered: hat/sit/bot");
|
LOGGER.info("[SLSA] commands registered: hat/sit/bot");
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
LOGGER.error("[SLSA] failed to register commands", t);
|
LOGGER.error("[SLSA] failed to register commands", t);
|
||||||
|
|||||||
@@ -112,18 +112,21 @@ public class BotAllCommand {
|
|||||||
return c -> batchAp(c, action);
|
return c -> batchAp(c, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 收集所有本模组生成的假人。 */
|
/** 收集所有本模组生成的假人(受名单限制:名单非空时只取名单内的)。 */
|
||||||
private static List<ServerPlayer> collectBots(CommandSourceStack source) {
|
private static List<ServerPlayer> collectBots(CommandSourceStack source) {
|
||||||
MinecraftServer server = source.getServer();
|
MinecraftServer server = source.getServer();
|
||||||
List<ServerPlayer> bots = new ArrayList<>();
|
List<ServerPlayer> bots = new ArrayList<>();
|
||||||
|
boolean filterByList = !com.github.zly2006.carpetslsaddition.util.BotListManager.isEmpty();
|
||||||
for (ServerPlayer player : server.getPlayerList().getPlayers()) {
|
for (ServerPlayer player : server.getPlayerList().getPlayers()) {
|
||||||
if (player instanceof EntityPlayerMPFake && ((SLSBotAccessor) player).carpet_SLS_Addition$isBot()) {
|
if (player instanceof EntityPlayerMPFake && ((SLSBotAccessor) player).carpet_SLS_Addition$isBot()) {
|
||||||
|
if (filterByList && !com.github.zly2006.carpetslsaddition.util.BotListManager.contains(player.getScoreboardName())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
bots.add(player);
|
bots.add(player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return bots;
|
return bots;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int sitAll(CommandContext<CommandSourceStack> context) {
|
private static int sitAll(CommandContext<CommandSourceStack> context) {
|
||||||
if (!SLSCarpetSettings.canUseSitCommand) {
|
if (!SLSCarpetSettings.canUseSitCommand) {
|
||||||
context.getSource().sendSuccess(() -> net.minecraft.network.chat.Component.literal(
|
context.getSource().sendSuccess(() -> net.minecraft.network.chat.Component.literal(
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
package com.github.zly2006.carpetslsaddition.command;
|
||||||
|
|
||||||
|
import carpet.patches.EntityPlayerMPFake;
|
||||||
|
import com.github.zly2006.carpetslsaddition.util.BotListManager;
|
||||||
|
import com.github.zly2006.carpetslsaddition.util.access.SLSBotAccessor;
|
||||||
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
|
import net.minecraft.commands.Commands;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static net.minecraft.commands.Commands.argument;
|
||||||
|
import static net.minecraft.commands.Commands.literal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* /botlist —— 维护"受控假人名单",供 /botall 限定操作范围。
|
||||||
|
*
|
||||||
|
* <p>名单持久化在 config/slsa-bot-list.json,重启保留。
|
||||||
|
*/
|
||||||
|
public class BotListCommand {
|
||||||
|
|
||||||
|
public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
|
||||||
|
LiteralArgumentBuilder<CommandSourceStack> command = literal("botlist")
|
||||||
|
.requires(source -> Commands.LEVEL_OWNERS.check(source.permissions())
|
||||||
|
|| me.lucko.fabric.api.permissions.v0.Permissions.check(source, "slsaddition.command.bot"))
|
||||||
|
.then(literal("show").executes(BotListCommand::show))
|
||||||
|
.then(literal("clear").executes(c -> {
|
||||||
|
BotListManager.clear();
|
||||||
|
c.getSource().sendSuccess(() -> Component.literal("[SLSA] 已清空假人名单"), false);
|
||||||
|
return 1;
|
||||||
|
}))
|
||||||
|
.then(literal("add")
|
||||||
|
.then(argument("names", StringArgumentType.greedyString())
|
||||||
|
.executes(c -> add(c.getSource(), StringArgumentType.getString(c, "names")))))
|
||||||
|
.then(literal("remove")
|
||||||
|
.then(argument("names", StringArgumentType.greedyString())
|
||||||
|
.executes(c -> remove(c.getSource(), StringArgumentType.getString(c, "names")))))
|
||||||
|
.then(literal("addall").executes(BotListCommand::addAll));
|
||||||
|
dispatcher.register(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int show(com.mojang.brigadier.context.CommandContext<CommandSourceStack> c) {
|
||||||
|
Set<String> names = BotListManager.getNames();
|
||||||
|
if (names.isEmpty()) {
|
||||||
|
c.getSource().sendSuccess(() -> Component.literal("[SLSA] 假人名单为空(此时 /botall 操作所有假人)"), false);
|
||||||
|
} else {
|
||||||
|
c.getSource().sendSuccess(() -> Component.literal(
|
||||||
|
"[SLSA] 假人名单(" + names.size() + "):" + String.join(", ", names)), false);
|
||||||
|
}
|
||||||
|
return names.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int add(CommandSourceStack source, String raw) {
|
||||||
|
String[] parts = raw.trim().split("\\s+");
|
||||||
|
int n = 0;
|
||||||
|
for (String p : parts) {
|
||||||
|
if (!p.isEmpty() && BotListManager.add(p)) {
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final int added = n;
|
||||||
|
source.sendSuccess(() -> Component.literal(
|
||||||
|
"[SLSA] 已添加 " + added + " 个名字,名单共 " + BotListManager.getNames().size() + " 个"), false);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int remove(CommandSourceStack source, String raw) {
|
||||||
|
String[] parts = raw.trim().split("\\s+");
|
||||||
|
int n = 0;
|
||||||
|
for (String p : parts) {
|
||||||
|
if (!p.isEmpty() && BotListManager.remove(p)) {
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final int removed = n;
|
||||||
|
source.sendSuccess(() -> Component.literal(
|
||||||
|
"[SLSA] 已移除 " + removed + " 个名字,名单共 " + BotListManager.getNames().size() + " 个"), false);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 把当前所有在线 SLS 假人加入名单。 */
|
||||||
|
private static int addAll(com.mojang.brigadier.context.CommandContext<CommandSourceStack> c) {
|
||||||
|
int n = 0;
|
||||||
|
for (ServerPlayer player : c.getSource().getServer().getPlayerList().getPlayers()) {
|
||||||
|
if (player instanceof EntityPlayerMPFake && ((SLSBotAccessor) player).carpet_SLS_Addition$isBot()) {
|
||||||
|
if (BotListManager.add(player.getScoreboardName())) {
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final int added = n;
|
||||||
|
c.getSource().sendSuccess(() -> Component.literal(
|
||||||
|
"[SLSA] 已把 " + added + " 个在线假人加入名单,名单共 " + BotListManager.getNames().size() + " 个"), false);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
package com.github.zly2006.carpetslsaddition.util;
|
||||||
|
|
||||||
|
import com.github.zly2006.carpetslsaddition.ServerMain;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 假人名单管理器:维护一份"受控假人名字"列表,持久化到 config/slsa-bot-list.json。
|
||||||
|
*
|
||||||
|
* <p>用途:{@code /botlist add cute wazi} 把名字加入名单后,{@code /botall} 的操作范围
|
||||||
|
* 就限定为名单内的假人(名单为空时操作所有 SLS 假人)。
|
||||||
|
*/
|
||||||
|
public final class BotListManager {
|
||||||
|
|
||||||
|
private BotListManager() {}
|
||||||
|
|
||||||
|
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||||
|
|
||||||
|
/** 名字列表(保序、去重)。 */
|
||||||
|
private static final Set<String> NAMES = new LinkedHashSet<>();
|
||||||
|
|
||||||
|
private static Path configPath;
|
||||||
|
|
||||||
|
private static Path path() {
|
||||||
|
if (configPath == null) {
|
||||||
|
configPath = FabricLoader.getInstance().getConfigDir().resolve("slsa-bot-list.json");
|
||||||
|
}
|
||||||
|
return configPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 加载名单(服务器启动时调用)。 */
|
||||||
|
public static void load() {
|
||||||
|
NAMES.clear();
|
||||||
|
Path p = path();
|
||||||
|
if (!Files.exists(p)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try (Reader r = Files.newBufferedReader(p)) {
|
||||||
|
Set<String> loaded = GSON.fromJson(r, new TypeToken<LinkedHashSet<String>>() {}.getType());
|
||||||
|
if (loaded != null) {
|
||||||
|
NAMES.addAll(loaded);
|
||||||
|
}
|
||||||
|
ServerMain.LOGGER.info("[SLSA] loaded bot list: {} entries", NAMES.size());
|
||||||
|
} catch (Exception e) {
|
||||||
|
ServerMain.LOGGER.error("[SLSA] failed to load bot list", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 保存名单。 */
|
||||||
|
public static void save() {
|
||||||
|
Path p = path();
|
||||||
|
try {
|
||||||
|
Files.createDirectories(p.getParent());
|
||||||
|
try (Writer w = Files.newBufferedWriter(p)) {
|
||||||
|
GSON.toJson(NAMES, w);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
ServerMain.LOGGER.error("[SLSA] failed to save bot list", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean add(String name) {
|
||||||
|
boolean added = NAMES.add(name);
|
||||||
|
if (added) save();
|
||||||
|
return added;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean remove(String name) {
|
||||||
|
boolean removed = NAMES.remove(name);
|
||||||
|
if (removed) save();
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clear() {
|
||||||
|
NAMES.clear();
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 返回名单快照。 */
|
||||||
|
public static Set<String> getNames() {
|
||||||
|
return new LinkedHashSet<>(NAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean contains(String name) {
|
||||||
|
return NAMES.contains(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isEmpty() {
|
||||||
|
return NAMES.isEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user