EG/plugins/plugin_manager.py
2025-12-12 16:16:15 +08:00

287 lines
8.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
插件管理器
负责插件的加载、卸载和管理
"""
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)