reconstruct the access control cli

This commit is contained in:
2025-10-09 18:52:47 +08:00
parent 11d138751a
commit 1fb26cfb71
5 changed files with 716 additions and 182 deletions

View File

@@ -6,7 +6,7 @@
"groupName": "Admin",
"groupUsers": ["Selcon"],
"isAllowed": true,
"isWarnTarget": true
"isNotice": true
},
"defaultToastConfig": {
"title": {
@@ -17,7 +17,7 @@
"text": "Hello %groupName% %playerName%",
"color": "green"
},
"prefix": "桃花源",
"prefix": "Taohuayuan",
"brackets": "[]",
"bracketColor": ""
},
@@ -39,19 +39,19 @@
"groupName": "user",
"groupUsers": [],
"isAllowed": true,
"isWarnTarget": true
"isNotice": true
},
{
"groupName": "VIP",
"groupUsers": [],
"isAllowed": true,
"isWarnTarget": false
"isNotice": false
},
{
"groupName": "enemy",
"groupUsers": [],
"isAllowed": false,
"isWarnTarget": false,
"isNotice": false,
"toastConfig": {
"title": {
"text": "Warn",

View File

@@ -0,0 +1,672 @@
import { CCLog } from "@/lib/ccLog";
import { AccessConfig, UserGroupConfig, saveConfig } from "./config";
import { ChatBoxEvent, pullEventAs } from "@/lib/event";
import { parseBoolean } from "@/lib/common";
// CLI命令接口
interface CLICommand {
name: string;
description: string;
usage: string;
execute: (args: string[], executor: string, context: CLIContext) => CLIResult;
}
// CLI执行结果
interface CLIResult {
success: boolean;
message?: string;
shouldSaveConfig?: boolean;
}
// CLI上下文
interface CLIContext {
config: AccessConfig;
configFilepath: string;
log: CCLog;
chatBox: any; // eslint-disable-line @typescript-eslint/no-explicit-any
groupNames: string[];
}
// 基础命令处理器
class CLICommandProcessor {
private commands = new Map<string, CLICommand>();
private context: CLIContext;
constructor(context: CLIContext) {
this.context = context;
this.initializeCommands();
}
private initializeCommands() {
// 注册所有命令
this.registerCommand(new AddCommand());
this.registerCommand(new DelCommand());
this.registerCommand(new ListCommand());
this.registerCommand(new SetCommand());
this.registerCommand(new CreateGroupCommand());
this.registerCommand(new RemoveGroupCommand());
this.registerCommand(new EditCommand());
this.registerCommand(new ShowConfigCommand());
this.registerCommand(new HelpCommand());
}
private registerCommand(command: CLICommand) {
this.commands.set(command.name, command);
}
public processCommand(message: string, executor: string): CLIResult {
const params = message.split(" ");
// 移除 "@AC" 前缀
if (params.length < 2) {
return this.getHelpCommand().execute([], executor, this.context);
}
const commandName = params[1].replace("/", ""); // 移除 "/" 前缀
const args = params.slice(2);
const command = this.commands.get(commandName);
if (!command) {
return {
success: false,
message: `Unknown command: ${commandName}`,
};
}
return command.execute(args, executor, this.context);
}
private getHelpCommand(): CLICommand {
return this.commands.get("help")!;
}
public sendResponse(result: CLIResult, executor: string) {
if (result.message != null && result.message.length > 0) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
this.context.chatBox.sendMessageToPlayer(
result.message,
executor,
"AccessControl",
"[]",
undefined,
undefined,
true,
);
}
if (result.shouldSaveConfig === true) {
saveConfig(this.context.config, this.context.configFilepath);
}
}
}
// 添加用户命令
class AddCommand implements CLICommand {
name = "add";
description = "Add player to group";
usage = "add <userGroup> <playerName>";
execute(args: string[], _executor: string, context: CLIContext): CLIResult {
if (args.length !== 2) {
return {
success: false,
message: `Usage: ${this.usage}`,
};
}
const [groupName, playerName] = args;
if (groupName === "admin") {
context.config.adminGroupConfig.groupUsers.push(playerName);
return {
success: true,
message: `Add player ${playerName} to admin`,
shouldSaveConfig: true,
};
}
if (!context.groupNames.includes(groupName)) {
return {
success: false,
message: `Invalid group: ${groupName}. Available groups: ${context.groupNames.join(", ")}`,
};
}
const groupConfig = context.config.usersGroups.find(
(value) => value.groupName === groupName,
);
if (!groupConfig) {
return {
success: false,
message: `Group ${groupName} not found`,
};
}
if (groupConfig.groupUsers === undefined) {
groupConfig.groupUsers = [playerName];
} else {
groupConfig.groupUsers.push(playerName);
}
return {
success: true,
message: `Add player ${playerName} to ${groupConfig.groupName}`,
shouldSaveConfig: true,
};
}
}
// 删除用户命令
class DelCommand implements CLICommand {
name = "del";
description = "Delete player from group";
usage = "del <userGroup> <playerName>";
execute(args: string[], _executor: string, context: CLIContext): CLIResult {
if (args.length !== 2) {
return {
success: false,
message: `Usage: ${this.usage}`,
};
}
const [groupName, playerName] = args;
if (groupName === "admin") {
return {
success: false,
message: "Could't delete admin, please edit config",
};
}
if (!context.groupNames.includes(groupName)) {
return {
success: false,
message: `Invalid group: ${groupName}. Available groups: ${context.groupNames.join(", ")}`,
};
}
const groupConfig = context.config.usersGroups.find(
(value) => value.groupName === groupName,
);
if (!groupConfig) {
return {
success: false,
message: `Group ${groupName} not found`,
};
}
if (groupConfig.groupUsers === undefined) {
groupConfig.groupUsers = [];
} else {
groupConfig.groupUsers = groupConfig.groupUsers.filter(
(user) => user !== playerName,
);
}
return {
success: true,
message: `Delete ${groupConfig.groupName} ${playerName}`,
shouldSaveConfig: true,
};
}
}
// 列表命令
class ListCommand implements CLICommand {
name = "list";
description = "List all players with their groups";
usage = "list";
execute(_args: string[], _executor: string, context: CLIContext): CLIResult {
let message = `Admins : [ ${context.config.adminGroupConfig.groupUsers.join(", ")} ]\n`;
for (const groupConfig of context.config.usersGroups) {
const users = groupConfig.groupUsers ?? [];
message += `${groupConfig.groupName} : [ ${users.join(", ")} ]\n`;
}
return {
success: true,
message: message.trim(),
};
}
}
// 设置命令
class SetCommand implements CLICommand {
name = "set";
description = "Config access control settings";
usage = "set <option> <value>";
execute(args: string[], _executor: string, context: CLIContext): CLIResult {
if (args.length !== 2) {
return {
success: false,
message: `Usage: ${this.usage}\nOptions: warnInterval, detectInterval, detectRange`,
};
}
const [option, valueStr] = args;
const value = parseInt(valueStr);
if (isNaN(value)) {
return {
success: false,
message: `Invalid value: ${valueStr}. Must be a number.`,
};
}
switch (option) {
case "warnInterval":
context.config.warnInterval = value;
return {
success: true,
message: `Set warn interval to ${context.config.warnInterval}`,
shouldSaveConfig: true,
};
case "detectInterval":
context.config.detectInterval = value;
return {
success: true,
message: `Set detect interval to ${context.config.detectInterval}`,
shouldSaveConfig: true,
};
case "detectRange":
context.config.detectRange = value;
return {
success: true,
message: `Set detect range to ${context.config.detectRange}`,
shouldSaveConfig: true,
};
default:
return {
success: false,
message: `Unknown option: ${option}. Available options: warnInterval, detectInterval, detectRange`,
};
}
}
}
// 帮助命令
class HelpCommand implements CLICommand {
name = "help";
description = "Show command help";
usage = "help";
execute(_args: string[], _executor: string, context: CLIContext): CLIResult {
const helpMessage = `
Command Usage: @AC /<Command> [args]
Commands:
- add <userGroup> <playerName>
add player to group
userGroup: ${context.groupNames.join(", ")}
- del <userGroup> <playerName>
delete player in the group, except Admin
userGroup: ${context.groupNames.join(", ")}
- list
list all of the player with its group
- set <options> [params]
config access control settings
options: warnInterval, detectInterval, detectRange
- creategroup <groupName> <isAllowed> <isNotice>
create new user group
- removegroup <groupName>
remove user group (except admin groups)
- edit <target> [args]
edit various configurations
targets: group (edit group properties)
examples: edit group <groupName> <property> <value> (properties: isAllowed, isNotice)
- showconfig [type]
show configuration (type: groups/toast/all)
- help
show this help message
`;
return {
success: true,
message: helpMessage.trim(),
};
}
}
// 创建用户组命令
class CreateGroupCommand implements CLICommand {
name = "creategroup";
description = "Create new user group";
usage = "creategroup <groupName> <isAllowed> <isNotice>";
execute(args: string[], _executor: string, context: CLIContext): CLIResult {
if (args.length !== 3) {
return {
success: false,
message: `Usage: ${this.usage}\nExample: creategroup VIP2 true false`,
};
}
const [groupName, isAllowedStr, isNoticeStr] = args;
// 检查组名是否已存在
if (context.groupNames.includes(groupName) || groupName === "admin") {
return {
success: false,
message: `Group ${groupName} already exists`,
};
}
const isAllowed = isAllowedStr.toLowerCase() === "true";
const isNotice = isNoticeStr.toLowerCase() === "true";
const newGroup: UserGroupConfig = {
groupName,
isAllowed,
isNotice,
groupUsers: [],
};
context.config.usersGroups.push(newGroup);
context.groupNames.push(groupName);
return {
success: true,
message: `Created group ${groupName} (allowed: ${isAllowed}, notice: ${isNotice})`,
shouldSaveConfig: true,
};
}
}
// 删除用户组命令
class RemoveGroupCommand implements CLICommand {
name = "removegroup";
description = "Remove user group";
usage = "removegroup <groupName>";
execute(args: string[], _executor: string, context: CLIContext): CLIResult {
if (args.length !== 1) {
return {
success: false,
message: `Usage: ${this.usage}`,
};
}
const [groupName] = args;
if (groupName === "admin") {
return {
success: false,
message: "Cannot remove admin group",
};
}
const groupIndex = context.config.usersGroups.findIndex(
(group) => group.groupName === groupName,
);
if (groupIndex === -1) {
return {
success: false,
message: `Group ${groupName} not found`,
};
}
context.config.usersGroups.splice(groupIndex, 1);
const nameIndex = context.groupNames.indexOf(groupName);
if (nameIndex > -1) {
context.groupNames.splice(nameIndex, 1);
}
return {
success: true,
message: `Removed group ${groupName}`,
shouldSaveConfig: true,
};
}
}
// 统一编辑命令
class EditCommand implements CLICommand {
name = "edit";
description = "Edit various configurations (only group now)";
usage = "edit <target> [args]";
execute(args: string[], _executor: string, context: CLIContext): CLIResult {
if (args.length < 1) {
return {
success: false,
message: `Usage: ${this.usage}\nTargets: group`,
};
}
const [target, ...rest] = args;
switch (target) {
case "group":
return this.editGroup(rest, context);
default:
return {
success: false,
message: `Unknown target: ${target}. Available: group`,
};
}
}
private editGroup(args: string[], context: CLIContext): CLIResult {
if (args.length !== 3) {
return {
success: false,
message: `Usage: edit group <groupName> <property> <value>\nProperties: isAllowed, isNotice`,
};
}
const [groupName, property, valueStr] = args;
let groupConfig: UserGroupConfig | undefined;
if (groupName === "admin") {
groupConfig = context.config.adminGroupConfig;
} else {
groupConfig = context.config.usersGroups.find(
(group) => group.groupName === groupName,
);
}
if (!groupConfig) {
return {
success: false,
message: `Group ${groupName} not found`,
};
}
switch (property) {
case "isAllowed": {
const val = parseBoolean(valueStr);
if (val != undefined) {
groupConfig.isAllowed = val;
return {
success: true,
message: `Set ${groupName}.isAllowed to ${groupConfig.isAllowed}`,
shouldSaveConfig: true,
};
} else {
return {
success: false,
message: `Set ${groupName}.isAllowed failed`,
shouldSaveConfig: false,
};
}
}
case "isNotice": {
const val = parseBoolean(valueStr);
if (val != undefined) {
groupConfig.isNotice = val;
return {
success: true,
message: `Set ${groupName}.isNotice to ${groupConfig.isNotice}`,
shouldSaveConfig: true,
};
} else {
return {
success: false,
message: `Set ${groupName}.isAllowed failed`,
shouldSaveConfig: false,
};
}
}
default:
return {
success: false,
message: `Unknown property: ${property}. Available: isAllowed, isNotice`,
};
}
}
}
// 显示配置命令
class ShowConfigCommand implements CLICommand {
name = "showconfig";
description = "Show configuration";
usage = "showconfig [type]";
execute(args: string[], _executor: string, context: CLIContext): CLIResult {
const type = args[0] || "all";
switch (type) {
case "groups": {
let groupsMessage = `Admin Group: ${context.config.adminGroupConfig.groupName}\n`;
groupsMessage += ` Users: [${context.config.adminGroupConfig.groupUsers.join(", ")}]\n`;
groupsMessage += ` Allowed: ${context.config.adminGroupConfig.isAllowed}\n`;
groupsMessage += ` notice: ${context.config.adminGroupConfig.isNotice}\n\n`;
for (const group of context.config.usersGroups) {
groupsMessage += `Group: ${group.groupName}\n`;
groupsMessage += ` Users: [${(group.groupUsers ?? []).join(", ")}]\n`;
groupsMessage += ` Allowed: ${group.isAllowed}\n`;
groupsMessage += ` Notice: ${group.isNotice}\n`;
if (group.toastConfig !== undefined) {
groupsMessage += ` Custom Toast Config:\n`;
groupsMessage += ` Title: ${group.toastConfig.title.text}\n`;
groupsMessage += ` Message: ${group.toastConfig.msg.text}\n`;
if (group.toastConfig.prefix !== undefined) {
groupsMessage += ` Prefix: ${group.toastConfig.prefix}\n`;
}
if (group.toastConfig.brackets !== undefined) {
groupsMessage += ` Brackets: ${group.toastConfig.brackets}\n`;
}
if (group.toastConfig.bracketColor !== undefined) {
groupsMessage += ` Bracket Color: ${group.toastConfig.bracketColor}\n`;
}
}
groupsMessage += "\n";
}
return {
success: true,
message: groupsMessage.trim(),
};
}
case "toast": {
let toastMessage = "Default Toast Config:\n";
toastMessage += ` Title: ${context.config.defaultToastConfig.title.text}\n`;
toastMessage += ` Message: ${context.config.defaultToastConfig.msg.text}\n`;
toastMessage += ` Prefix: ${context.config.defaultToastConfig.prefix ?? "none"}\n`;
toastMessage += ` Brackets: ${context.config.defaultToastConfig.brackets ?? "none"}\n`;
toastMessage += ` Bracket Color: ${context.config.defaultToastConfig.bracketColor ?? "none"}\n\n`;
toastMessage += "Warn Toast Config:\n";
toastMessage += ` Title: ${context.config.warnToastConfig.title.text}\n`;
toastMessage += ` Message: ${context.config.warnToastConfig.msg.text}\n`;
toastMessage += ` Prefix: ${context.config.warnToastConfig.prefix ?? "none"}\n`;
toastMessage += ` Brackets: ${context.config.warnToastConfig.brackets ?? "none"}\n`;
toastMessage += ` Bracket Color: ${context.config.warnToastConfig.bracketColor ?? "none"}`;
return {
success: true,
message: toastMessage,
};
}
case "all": {
let allMessage = `Detect Range: ${context.config.detectRange}\n`;
allMessage += `Detect Interval: ${context.config.detectInterval}\n`;
allMessage += `Warn Interval: ${context.config.warnInterval}\n\n`;
allMessage +=
"Use 'showconfig groups' or 'showconfig toast' for detailed view";
return {
success: true,
message: allMessage,
};
}
default:
return {
success: false,
message: `Invalid type: ${type}. Available: groups, toast, all`,
};
}
}
}
// CLI循环处理器
export class AccessControlCLI {
private processor: CLICommandProcessor;
private context: CLIContext;
constructor(context: CLIContext) {
this.context = context;
this.processor = new CLICommandProcessor(context);
}
public startConfigLoop() {
while (true) {
const ev = pullEventAs(ChatBoxEvent, "chat");
if (ev === undefined) continue;
if (
!this.context.config.adminGroupConfig.groupUsers.includes(ev.username)
)
continue;
if (!ev.message.startsWith("@AC")) continue;
this.context.log.info(
`Received command "${ev.message}" from admin ${ev.username}`,
);
const result = this.processor.processCommand(ev.message, ev.username);
this.processor.sendResponse(result, ev.username);
if (!result.success) {
this.context.log.warn(`Command failed: ${result.message}`);
}
}
}
}
// 导出类型和工厂函数
export { CLIContext, CLIResult, CLICommand };
export function createAccessControlCLI(
config: AccessConfig,
configFilepath: string,
log: CCLog,
chatBox: any, // eslint-disable-line @typescript-eslint/no-explicit-any
groupNames: string[],
): AccessControlCLI {
const context: CLIContext = {
config,
configFilepath,
log,
chatBox, // eslint-disable-line @typescript-eslint/no-unsafe-assignment
groupNames,
};
return new AccessControlCLI(context);
}

View File

@@ -14,7 +14,7 @@ interface ToastConfig {
interface UserGroupConfig {
groupName: string;
isAllowed: boolean;
isWarnTarget: boolean;
isNotice: boolean;
groupUsers: string[];
toastConfig?: ToastConfig;
}
@@ -37,26 +37,26 @@ const defaultConfig: AccessConfig = {
groupName: "Admin",
groupUsers: ["Selcon"],
isAllowed: true,
isWarnTarget: false,
isNotice: false,
},
usersGroups: [
{
groupName: "user",
groupUsers: [],
isAllowed: true,
isWarnTarget: true,
isNotice: true,
},
{
groupName: "VIP",
groupUsers: [],
isAllowed: true,
isWarnTarget: false,
isNotice: false,
},
{
groupName: "enemies",
groupUsers: [],
isAllowed: false,
isWarnTarget: false,
isNotice: false,
toastConfig: {
title: {
text: "Warn",

View File

@@ -1,33 +1,22 @@
import { CCLog, DAY } from "@/lib/ccLog";
import {
ToastConfig,
UserGroupConfig,
loadConfig,
saveConfig,
setLog,
} from "./config";
import { ToastConfig, UserGroupConfig, loadConfig, setLog } from "./config";
import { createAccessControlCLI } from "./cli";
import * as peripheralManager from "../lib/PeripheralManager";
import { ChatBoxEvent, pullEventAs } from "@/lib/event";
import { quotestring } from "@sikongjueluo/dkjson-types";
const DEBUG = false;
const args = [...$vararg];
// Init Log
const log = new CCLog("accesscontrol.log", DAY);
setLog(log);
// Load Config
const configFilepath = `${shell.dir()}/access.config.json`;
const config = loadConfig(configFilepath);
log.info("Load config successfully!");
log.debug(textutils.serialise(config, { allow_repetitions: true }));
if (DEBUG) log.debug(textutils.serialise(config, { allow_repetitions: true }));
const groupNames = config.usersGroups.map((value) => value.groupName);
const warnTargetPlayers = config.adminGroupConfig.groupUsers.concat(
config.usersGroups
.filter((value) => value.isWarnTarget)
.map((value) => value.groupUsers ?? [])
.flat(),
);
let warnTargetPlayers: string[];
const playerDetector = peripheralManager.findByNameRequired("playerDetector");
const chatBox = peripheralManager.findByNameRequired("chatBox");
@@ -66,7 +55,7 @@ function sendToast(
groupConfig?.groupName,
),
player,
quotestring(toastConfig.prefix ?? config.defaultToastConfig.prefix!),
toastConfig.prefix ?? config.defaultToastConfig.prefix,
toastConfig.brackets ?? config.defaultToastConfig.brackets,
toastConfig.bracketColor ?? config.defaultToastConfig.bracketColor,
undefined,
@@ -74,9 +63,15 @@ function sendToast(
);
}
function sendWarn(player: string) {
function sendWarnAndNotice(player: string) {
const playerPos = playerDetector.getPlayerPos(player);
const onlinePlayers = playerDetector.getOnlinePlayers();
warnTargetPlayers = config.adminGroupConfig.groupUsers.concat(
config.usersGroups
.filter((value) => value.isNotice)
.map((value) => value.groupUsers ?? [])
.flat(),
);
const warnMsg = `Not Allowed Player ${player} Break in Home at Position ${playerPos?.x}, ${playerPos?.y}, ${playerPos?.z}`;
log.warn(warnMsg);
@@ -108,43 +103,11 @@ function sendWarn(player: string) {
}
}
function sendCommandHelp(targetPlayer: string) {
chatBox.sendMessageToPlayer(
`
Command Usage: @AC /<Command> [args]
Command:
- add <userGroup> <playerName>
add player to group
userGroup: ${groupNames.join(", ")}
- del <userGroup> <playerName>
delete player in the group, except Admin
userGroup: ${groupNames.join(", ")}
- list
list all of the player with its group
- set <options> [params]
config access control settins
options:
- warnInterval <number>
set the interval of warn, which is not allowed
- detectInterval <number>
set the interval of detecting players
- detectRange <number>
set the sphere range of detect
`,
targetPlayer,
"AccessControl",
"[]",
undefined,
undefined,
true,
);
}
function warnLoop() {
while (true) {
for (const player of notAllowedPlayers) {
if (inRangePlayers.includes(player)) {
sendWarn(player);
// sendWarnAndNotice(player);
} else {
notAllowedPlayers = notAllowedPlayers.filter(
(value) => value != player,
@@ -183,7 +146,7 @@ function mainLoop() {
if (!userGroupConfig.groupUsers.includes(player)) continue;
if (!userGroupConfig.isAllowed) {
sendWarn(player);
sendWarnAndNotice(player);
notAllowedPlayers.push(player);
continue;
}
@@ -199,7 +162,7 @@ function mainLoop() {
}
if (inUserGroup) continue;
sendWarn(player);
sendWarnAndNotice(player);
notAllowedPlayers.push(player);
}
@@ -208,132 +171,25 @@ function mainLoop() {
}
}
function configLoop() {
while (true) {
const ev = pullEventAs(ChatBoxEvent, "chat");
if (ev == undefined) continue;
if (!config.adminGroupConfig.groupUsers.includes(ev.username)) continue;
if (!ev.message.startsWith("@AC")) continue;
// log.info(`Received "${ev.message}" from admin ${ev.username}`);
const params = ev.message.split(" ");
if (params.length < 2) {
sendCommandHelp(ev.username);
continue;
}
if (params[1] == "/add" && params.length == 4) {
if (params[2] == "admin") {
config.adminGroupConfig.groupUsers.push(params[3]);
chatBox.sendMessageToPlayer(
`Add player ${params[3]} to admin`,
ev.username,
"AccessControl",
);
} else if (groupNames.includes(params[2])) {
const groupConfig = config.usersGroups.find(
(value) => value.groupName == params[2],
)!;
if (groupConfig.groupUsers == undefined)
groupConfig.groupUsers = [params[3]];
else groupConfig.groupUsers.push(params[3]);
chatBox.sendMessageToPlayer(
`Add player ${params[3]} to ${groupConfig.groupName}`,
ev.username,
"AccessControl",
);
} else {
sendCommandHelp(ev.username);
continue;
}
} else if (params[1] == "/del" && params.length == 4) {
if (params[2] == "admin") {
chatBox.sendMessageToPlayer(
`Could't delete admin, please edit config`,
ev.username,
"AccessControl",
);
} else if (groupNames.includes(params[2])) {
const groupConfig = config.usersGroups.find(
(value) => value.groupName == params[2],
)!;
if (groupConfig.groupUsers == undefined) groupConfig.groupUsers = [];
else
groupConfig.groupUsers = groupConfig.groupUsers.filter(
(user) => user != params[3],
);
chatBox.sendMessageToPlayer(
`Delete ${groupConfig.groupName} ${params[3]}`,
ev.username,
"AccessControl",
);
} else {
sendCommandHelp(ev.username);
continue;
}
} else if (params[1] == "/list") {
chatBox.sendMessageToPlayer(
`Admins : [ ${config.adminGroupConfig.groupUsers.join(", ")} ]`,
ev.username,
"AccessControl",
);
for (const groupConfig of config.usersGroups) {
chatBox.sendMessageToPlayer(
`${groupConfig.groupName} : [ ${config.adminGroupConfig.groupUsers.join(", ")} ]`,
ev.username,
"AccessControl",
);
}
} else if (params[1] == "/set" && params.length == 4) {
if (params[2] == "warnInterval") {
config.warnInterval = parseInt(params[3]);
chatBox.sendMessageToPlayer(
`Set warn interval to ${config.warnInterval}`,
ev.username,
"AccessControl",
);
} else if (params[2] == "detectInterval") {
config.detectInterval = parseInt(params[3]);
chatBox.sendMessageToPlayer(
`Set detect interval to ${config.detectInterval}`,
ev.username,
"AccessControl",
);
} else if (params[2] == "detectRange") {
config.detectRange = parseInt(params[3]);
chatBox.sendMessageToPlayer(
`Set detect range to ${config.detectRange}`,
ev.username,
"AccessControl",
);
} else {
sendCommandHelp(ev.username);
continue;
}
} else {
sendCommandHelp(ev.username);
continue;
}
saveConfig(config, configFilepath);
}
}
function main(args: string[]) {
log.debug("Starting access control system, get args: " + args.join(", "));
log.info("Starting access control system, get args: " + args.join(", "));
if (args.length == 1) {
if (args[0] == "start") {
// 创建CLI处理器
const cli = createAccessControlCLI(
config,
configFilepath,
log,
chatBox,
groupNames,
);
parallel.waitForAll(
() => {
mainLoop();
},
() => {
configLoop();
void cli.startConfigLoop();
},
() => {
warnLoop();

6
src/lib/common.ts Normal file
View File

@@ -0,0 +1,6 @@
export function parseBoolean(obj: string): boolean | undefined {
const str = obj.toLowerCase();
if (str === "true") return true;
else if (str === "false") return false;
else return undefined;
}