From dc1aa3e1377f1bc9572f464b41f4384a6a367001 Mon Sep 17 00:00:00 2001 From: zhong_bai <54356787+zhongbai2333@users.noreply.github.com> Date: Tue, 4 Feb 2025 22:40:18 +0800 Subject: [PATCH] =?UTF-8?q?Create:=20#3=20=E7=8B=AC=E7=AB=8B=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F=E4=BB=BB=E9=9C=80=E8=A6=81=E6=9B=B4=E5=A4=9A=E5=9F=BA?= =?UTF-8?q?=E7=A1=80=E5=91=BD=E4=BB=A4=EF=BC=8C=E5=8C=85=E6=8B=ACPlugin?= =?UTF-8?q?=EF=BC=8Clist=EF=BC=8Cinfo=E7=AD=89=E7=AD=89=20;=20Fix:=20#13?= =?UTF-8?q?=20=E7=8B=AC=E7=AB=8B=E7=89=88=E6=9C=AC=E5=91=BD=E4=BB=A4?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E6=89=A7=E8=A1=8C,=20#14=20=E7=8B=AC?= =?UTF-8?q?=E7=AB=8B=E7=89=88=E6=9C=AC=E5=8A=A0=E8=BD=BD=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E6=97=B6=E4=BC=9A=E5=87=BA=E7=8E=B0=E5=86=B2=E7=AA=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- connect_core/cli/cli_core.py | 8 ++ connect_core/cli/command_core.py | 45 ++++++----- connect_core/cli/commands.py | 84 +++++++++++++++++++-- connect_core/interface/control_interface.py | 24 ++++-- connect_core/plugin/init_plugin.py | 5 +- 5 files changed, 131 insertions(+), 35 deletions(-) diff --git a/connect_core/cli/cli_core.py b/connect_core/cli/cli_core.py index bef83f7..af73f71 100644 --- a/connect_core/cli/cli_core.py +++ b/connect_core/cli/cli_core.py @@ -6,11 +6,16 @@ from connect_core.interface.control_interface import CoreControlInterface from connect_core.account.register_system import register_system_main from connect_core.cli.commands import ServerCommand, ClientCommand +from connect_core.cli.command_core import CommandLineInterface +command_core = None class Server(object): def __init__(self) -> None: + global command_core self._control_interface = CoreControlInterface() + command_core = CommandLineInterface(self._control_interface) + command_core.start() self._control_interface.info(self._control_interface.tr("cli.starting.welcome")) register_system_main(self._control_interface) init_plugin_main(self._control_interface) @@ -45,7 +50,10 @@ def start_servers(self) -> None: class Client(object): def __init__(self) -> None: + global command_core self._control_interface = CoreControlInterface() + command_core = CommandLineInterface(self._control_interface) + command_core.start() _config = self._control_interface.get_config() self._control_interface.info( self._control_interface.tr( diff --git a/connect_core/cli/command_core.py b/connect_core/cli/command_core.py index 6be4d5c..4895d87 100644 --- a/connect_core/cli/command_core.py +++ b/connect_core/cli/command_core.py @@ -6,17 +6,18 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: - from connect_core.api.interface import PluginControlInterface + from connect_core.api.interface import CoreControlInterface # 命令行界面类 class CommandLineInterface: - def __init__(self, interface: "PluginControlInterface", prompt: str = ">>> "): + + def __init__(self, interface: "CoreControlInterface", prompt: str = ">>> "): """ 初始化命令行界面类,设置默认提示符和补全器。 Args: - connect_interface (PluginControlInterface): API接口 + connect_interface (CoreControlInterface): API接口 """ self.prompt = prompt self.completer = {} @@ -56,14 +57,21 @@ def add_command(self, sid, command, action): action (callable): 执行该命令的函数。 """ commands = command.split() - self.commands.setdefault(sid, {}) - for key in commands[:-1]: # 迭代到倒数第二个元素,创建或找到路径 - if key not in self.commands[sid]: - self.commands[sid][key] = {} # 如果没有这个键,创建一个新的空字典 - self.commands[sid] = self.commands[sid][key] + + # 确保 sid 存在,并初始化为空字典 + if sid not in self.commands: + self.commands[sid] = {} + + cmd_dict = self.commands[sid] # 先取得命令字典 + + # 遍历命令路径中的每一部分,逐级进入字典 + for key in commands[:-1]: # 遍历到倒数第二个元素,创建或找到路径 + if key not in cmd_dict: + cmd_dict[key] = {} # 如果没有这个键,创建一个新的空字典 + cmd_dict = cmd_dict[key] # 进入下一层级 # 对于最后一个元素,赋予值 - self.commands[sid][commands[-1]] = action + cmd_dict[commands[-1]] = action def remove_command(self, sid, command): """ @@ -136,7 +144,7 @@ def handle_input(self, text): if sid not in self.commands: self.interface.warn(f"未知插件ID: {sid}") return None - + # 如果只输入了sid,没有其他命令,默认执行 sid help if not params: params = ["help"] @@ -150,13 +158,16 @@ def handle_input(self, text): # 如果命令存在并且当前路径是字典 if isinstance(command, dict) and key in command: command = command[key] - # 如果遇到占位符,进行替换 - elif ( - isinstance(command, dict) - and isinstance(command.get(key), str) - and re.match(r"<.*>", key) - ): - final_params.append(key.strip("<>")) # 提取参数 + # 如果遇到占位符,进行替换并提取参数 + elif isinstance(command, dict): + # 查找命令中带占位符的键 + for cmd_key in command.keys(): + match = re.match(r"<([^>]+)>", cmd_key) # 匹配占位符 + if match: + # 如果占位符匹配,则将用户输入的参数替换占位符 + final_params.append(key) # 用实际值替换占位符 + command = command[cmd_key] # 进入下一层字典 + break else: self.interface.warn(f"未知命令: {key}") return None # 如果路径不存在或某层不是字典,则返回 None diff --git a/connect_core/cli/commands.py b/connect_core/cli/commands.py index f282245..a17f875 100644 --- a/connect_core/cli/commands.py +++ b/connect_core/cli/commands.py @@ -1,8 +1,12 @@ +import os from typing import TYPE_CHECKING +from connect_core.tools import auto_trigger +from connect_core.plugin.init_plugin import load_plugin, reload_plugin, unload_plugin, get_plugins if TYPE_CHECKING: from connect_core.interface.control_interface import CoreControlInterface + class Command(object): def __init__(self, control_interface: "CoreControlInterface"): self._control_interface = control_interface @@ -12,12 +16,26 @@ def _reg_commands(self): # Register commands here self._control_interface.add_command("help", self._handle_help) self._control_interface.add_command("list", self._handle_list) + self._control_interface.add_command( + "plugin load ", self._handle_plugin_load + ) + self._control_interface.add_command( + "plugin reload ", self._handle_plugin_reload + ) + self._control_interface.add_command( + "plugin unload ", self._handle_plugin_unload + ) self._completer_words["help"] = None self._completer_words["list"] = None - self._control_interface.set_completer_words(self._completer_words) - self._control_interface.flush_cli() + self._completer_words["plugin"] = { + "load": None, + "reload": None, + "unload": None, + } + self._get_file_list() + self._reload_completer() - def _handle_help(self, args: list): + def _handle_help(self, *_): if self._control_interface.is_server(): self._control_interface.info( self._control_interface.tr("commands.server_help") @@ -27,27 +45,60 @@ def _handle_help(self, args: list): self._control_interface.tr("commands.client_help") ) - def _handle_list(self, args: list): + def _handle_list(self, *_): self._control_interface.info("==list==") for num, key in enumerate(self._control_interface.get_server_list()): self._control_interface.info(f"{num + 1}. {key}") + def _handle_plugin_load(self, path: str): + # Implement plugin loading logic here + load_plugin(path) + + def _handle_plugin_reload(self, id: str): + # Implement plugin reloading logic here + reload_plugin(id) + + def _handle_plugin_unload(self, id: str): + # Implement plugin unload logic here + unload_plugin(id) + + @auto_trigger(5, "plugin_file_list") + def _get_file_list(self): + file_list = {} + id_list = {} + for i in os.listdir("./plugins/"): + file_list[i] = None + for i in get_plugins(): + id_list[i] = None + if self._completer_words["plugin"]["load"] != file_list: + self._completer_words["plugin"]["load"] = file_list + self._reload_completer() + if self._completer_words["plugin"]["reload"] != id_list: + self._completer_words["plugin"]["reload"] = id_list + self._completer_words["plugin"]["unload"] = id_list + self._reload_completer() + + def _reload_completer(self): + self._control_interface.set_completer_words(self._completer_words) + self._control_interface.flush_cli() + class ServerCommand(Command): def __init__(self, control_interface: "CoreControlInterface"): super().__init__(control_interface) self._reg_commands() + self._reg_server_commands() def _reg_server_commands(self): # Register commands here self._control_interface.add_command("getkey", self._handle_getkey) self._completer_words["getkey"] = None - self._control_interface.set_completer_words(self._completer_words) - self._control_interface.flush_cli() + self._reload_completer() - def _handle_getkey(self, args: list): + def _handle_getkey(self, *_): from connect_core.account.register_system import get_password + self._control_interface.info( self._control_interface.tr("cli.starting.welcome_password", get_password()) ) @@ -57,4 +108,23 @@ class ClientCommand(Command): def __init__(self, control_interface: "CoreControlInterface"): super().__init__(control_interface) + self._reg_commands() self._reg_client_commands() + + def _reg_client_commands(self): + self._control_interface.add_command("info", self._handle_info) + self._completer_words["info"] = None + self._reload_completer() + + def _handle_info(self, *_): + """ + 显示主服务器信息。 + """ + self._control_interface.info("==info==") + server_id = self._control_interface.get_server_id() + if server_id: + self._control_interface.info( + f"Main Server Connected! Server ID: {server_id}" + ) + else: + self._control_interface.info("Main Server Disconnected!") diff --git a/connect_core/interface/control_interface.py b/connect_core/interface/control_interface.py index c4bd53f..0763bbe 100644 --- a/connect_core/interface/control_interface.py +++ b/connect_core/interface/control_interface.py @@ -16,15 +16,13 @@ def __init__(self): if self.__mcdr_server: self.config_path = "./config/connect_core/config.json" self._is_server = self.get_config().get("is_server", False) - self.command_core = None else: from connect_core.cli.cli_entry import get_is_server self._is_server = get_is_server() self.config_path = "./config.json" self.language = self.get_config().get("language", "en_us") - self.command_core = CommandLineInterface(self) - self.command_core.start() + self.log_system = LogSystem(self.sid, self.get_config().get("debug", False)) # ============= @@ -168,7 +166,9 @@ def add_command(self, command: str, func: callable): command (str): 命令名称。 func (callable): 命令对应的函数。 """ - self.command_core.add_command(self.sid, command, func) + from connect_core.cli.cli_core import command_core + + command_core.add_command(self.sid, command, func) def remove_command(self, command: str): """ @@ -177,7 +177,9 @@ def remove_command(self, command: str): Args: command (str): 命令名称。 """ - self.command_core.remove_command(self.sid, command) + from connect_core.cli.cli_core import command_core + + command_core.remove_command(self.sid, command) def set_prompt(self, prompt: str): """ @@ -186,7 +188,9 @@ def set_prompt(self, prompt: str): Args: prompt (str): 命令行提示符内容。 """ - self.command_core.set_prompt(prompt) + from connect_core.cli.cli_core import command_core + + command_core.set_prompt(prompt) def set_completer_words(self, words: dict): """ @@ -195,13 +199,17 @@ def set_completer_words(self, words: dict): Args: words (dict): 命令行补全词典内容。 """ - self.command_core.set_completer_words(self.sid, words) + from connect_core.cli.cli_core import command_core + + command_core.set_completer_words(self.sid, words) def flush_cli(self): """ 清空命令行界面。 """ - self.command_core.flush_cli() + from connect_core.cli.cli_core import command_core + + command_core.flush_cli() # ========= # Tools diff --git a/connect_core/plugin/init_plugin.py b/connect_core/plugin/init_plugin.py index 9305b61..0dbeff8 100644 --- a/connect_core/plugin/init_plugin.py +++ b/connect_core/plugin/init_plugin.py @@ -118,10 +118,9 @@ def unload(self, plugin_id: str): def reload(self, plugin_id: str): """重载插件,先卸载再加载""" - if plugin_id in self.plugins: - self.unload(plugin_id) - if "path" in self.plugins[plugin_id].keys(): + if plugin_id in self.plugins and "path" in self.plugins[plugin_id].keys(): plugin_file = self.plugins[plugin_id]["path"].split("/")[-1] + self.unload(plugin_id) self.load_plugin(plugin_file) else: from connect_core.mcdr.mcdr_entry import get_mcdr