287 lines
8.8 KiB
Python
287 lines
8.8 KiB
Python
"""
|
||
插件管理器
|
||
负责插件的加载、卸载和管理
|
||
"""
|
||
import os
|
||
import sys
|
||
import importlib.util
|
||
from typing import Dict, List, Optional, Any
|
||
import traceback
|
||
|
||
class BasePlugin:
|
||
"""
|
||
插件基类
|
||
所有插件必须继承此类并实现相应方法
|
||
"""
|
||
|
||
def __init__(self, plugin_manager, name: str):
|
||
self.plugin_manager = plugin_manager
|
||
self.name = name
|
||
self.enabled = False
|
||
self.config = {}
|
||
|
||
def initialize(self) -> bool:
|
||
"""
|
||
初始化插件
|
||
返回True表示初始化成功,False表示失败
|
||
"""
|
||
return True
|
||
|
||
def enable(self) -> bool:
|
||
"""
|
||
启用插件
|
||
返回True表示启用成功,False表示失败
|
||
"""
|
||
self.enabled = True
|
||
return True
|
||
|
||
def disable(self) -> bool:
|
||
"""
|
||
禁用插件
|
||
返回True表示禁用成功,False表示失败
|
||
"""
|
||
self.enabled = False
|
||
return True
|
||
|
||
def finalize(self):
|
||
"""
|
||
清理插件资源
|
||
"""
|
||
pass
|
||
|
||
def get_info(self) -> Dict[str, Any]:
|
||
"""
|
||
获取插件信息
|
||
"""
|
||
return {
|
||
"name": self.name,
|
||
"enabled": self.enabled,
|
||
"version": "1.0.0",
|
||
"author": "Unknown",
|
||
"description": "Base plugin class"
|
||
}
|
||
|
||
|
||
class PluginManager:
|
||
"""
|
||
插件管理器
|
||
负责插件的加载、卸载和管理
|
||
"""
|
||
|
||
def __init__(self, world):
|
||
self.world = world
|
||
self.plugins: Dict[str, BasePlugin] = {}
|
||
self.plugin_configs: Dict[str, Dict] = {}
|
||
self.plugin_dirs = [
|
||
"plugins/core",
|
||
"plugins/third_party",
|
||
"plugins/user"
|
||
]
|
||
self.enabled = False # 默认不启用插件系统
|
||
|
||
def enable_plugin_system(self):
|
||
"""
|
||
启用插件系统
|
||
"""
|
||
self.enabled = True
|
||
print("✓ 插件系统已启用")
|
||
|
||
def disable_plugin_system(self):
|
||
"""
|
||
禁用插件系统
|
||
"""
|
||
# 禁用所有插件
|
||
for plugin_name in list(self.plugins.keys()):
|
||
self.disable_plugin(plugin_name)
|
||
self.enabled = False
|
||
print("✓ 插件系统已禁用")
|
||
|
||
def is_plugin_system_enabled(self) -> bool:
|
||
"""
|
||
检查插件系统是否已启用
|
||
"""
|
||
return self.enabled
|
||
|
||
def discover_plugins(self) -> List[str]:
|
||
"""
|
||
发现所有可用的插件
|
||
返回插件名称列表
|
||
"""
|
||
if not self.enabled:
|
||
return []
|
||
|
||
plugin_names = []
|
||
|
||
# 获取项目根目录
|
||
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||
|
||
for plugin_dir in self.plugin_dirs:
|
||
full_path = os.path.join(project_root, plugin_dir)
|
||
if os.path.exists(full_path):
|
||
for item in os.listdir(full_path):
|
||
# 查找插件目录(包含plugin.py文件的目录)
|
||
item_path = os.path.join(full_path, item)
|
||
if os.path.isdir(item_path) and os.path.exists(os.path.join(item_path, "plugin.py")):
|
||
plugin_names.append(item)
|
||
|
||
return plugin_names
|
||
|
||
def load_plugin(self, plugin_name: str) -> Optional[BasePlugin]:
|
||
"""
|
||
加载指定插件
|
||
"""
|
||
if not self.enabled:
|
||
print(f"⚠ 插件系统未启用,无法加载插件: {plugin_name}")
|
||
return None
|
||
|
||
if plugin_name in self.plugins:
|
||
print(f"⚠ 插件已加载: {plugin_name}")
|
||
return self.plugins[plugin_name]
|
||
|
||
# 查找插件文件
|
||
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||
plugin_file_path = None
|
||
|
||
for plugin_dir in self.plugin_dirs:
|
||
full_path = os.path.join(project_root, plugin_dir, plugin_name, "plugin.py")
|
||
if os.path.exists(full_path):
|
||
plugin_file_path = full_path
|
||
break
|
||
|
||
if not plugin_file_path:
|
||
print(f"❌ 未找到插件: {plugin_name}")
|
||
return None
|
||
|
||
try:
|
||
# 动态加载插件模块
|
||
spec = importlib.util.spec_from_file_location(f"plugin_{plugin_name}", plugin_file_path)
|
||
module = importlib.util.module_from_spec(spec)
|
||
spec.loader.exec_module(module)
|
||
|
||
# 检查模块中是否有Plugin类
|
||
if not hasattr(module, 'Plugin'):
|
||
print(f"❌ 插件 {plugin_name} 缺少Plugin类")
|
||
return None
|
||
|
||
# 创建插件实例
|
||
plugin_class = getattr(module, 'Plugin')
|
||
plugin_instance = plugin_class(self, plugin_name)
|
||
|
||
# 初始化插件
|
||
if plugin_instance.initialize():
|
||
self.plugins[plugin_name] = plugin_instance
|
||
print(f"✓ 插件加载成功: {plugin_name}")
|
||
return plugin_instance
|
||
else:
|
||
print(f"❌ 插件初始化失败: {plugin_name}")
|
||
return None
|
||
|
||
except Exception as e:
|
||
print(f"❌ 加载插件 {plugin_name} 时出错: {e}")
|
||
traceback.print_exc()
|
||
return None
|
||
|
||
def unload_plugin(self, plugin_name: str) -> bool:
|
||
"""
|
||
卸载指定插件
|
||
"""
|
||
if plugin_name not in self.plugins:
|
||
print(f"⚠ 插件未加载: {plugin_name}")
|
||
return False
|
||
|
||
plugin = self.plugins[plugin_name]
|
||
|
||
# 如果插件已启用,先禁用
|
||
if plugin.enabled:
|
||
plugin.disable()
|
||
|
||
# 清理插件资源
|
||
plugin.finalize()
|
||
|
||
# 从管理器中移除
|
||
del self.plugins[plugin_name]
|
||
|
||
print(f"✓ 插件卸载成功: {plugin_name}")
|
||
return True
|
||
|
||
def enable_plugin(self, plugin_name: str) -> bool:
|
||
"""
|
||
启用指定插件
|
||
"""
|
||
if not self.enabled:
|
||
print(f"⚠ 插件系统未启用,无法启用插件: {plugin_name}")
|
||
return False
|
||
|
||
if plugin_name not in self.plugins:
|
||
# 尝试加载插件
|
||
plugin = self.load_plugin(plugin_name)
|
||
if not plugin:
|
||
return False
|
||
else:
|
||
plugin = self.plugins[plugin_name]
|
||
|
||
if plugin.enabled:
|
||
print(f"⚠ 插件已启用: {plugin_name}")
|
||
return True
|
||
|
||
if plugin.enable():
|
||
print(f"✓ 插件启用成功: {plugin_name}")
|
||
return True
|
||
else:
|
||
print(f"❌ 插件启用失败: {plugin_name}")
|
||
return False
|
||
|
||
def disable_plugin(self, plugin_name: str) -> bool:
|
||
"""
|
||
禁用指定插件
|
||
"""
|
||
if plugin_name not in self.plugins:
|
||
print(f"⚠ 插件未加载: {plugin_name}")
|
||
return False
|
||
|
||
plugin = self.plugins[plugin_name]
|
||
|
||
if not plugin.enabled:
|
||
print(f"⚠ 插件未启用: {plugin_name}")
|
||
return True
|
||
|
||
if plugin.disable():
|
||
print(f"✓ 插件禁用成功: {plugin_name}")
|
||
return True
|
||
else:
|
||
print(f"❌ 插件禁用失败: {plugin_name}")
|
||
return False
|
||
|
||
def get_plugin(self, plugin_name: str) -> Optional[BasePlugin]:
|
||
"""
|
||
获取指定插件实例
|
||
"""
|
||
return self.plugins.get(plugin_name)
|
||
|
||
def list_plugins(self) -> List[Dict[str, Any]]:
|
||
"""
|
||
列出所有插件信息
|
||
"""
|
||
plugin_info_list = []
|
||
for plugin_name, plugin in self.plugins.items():
|
||
plugin_info_list.append(plugin.get_info())
|
||
return plugin_info_list
|
||
|
||
def load_all_plugins(self):
|
||
"""
|
||
加载所有发现的插件
|
||
"""
|
||
if not self.enabled:
|
||
print("⚠ 插件系统未启用,跳过加载所有插件")
|
||
return
|
||
|
||
plugin_names = self.discover_plugins()
|
||
for plugin_name in plugin_names:
|
||
self.load_plugin(plugin_name)
|
||
|
||
def unload_all_plugins(self):
|
||
"""
|
||
卸载所有插件
|
||
"""
|
||
for plugin_name in list(self.plugins.keys()):
|
||
self.unload_plugin(plugin_name) |