添加插件系统

This commit is contained in:
Rowland 2025-10-30 15:01:29 +08:00
parent 0c2e9f0c1b
commit 6cf616d1bb
26 changed files with 16248 additions and 0 deletions

View File

@ -0,0 +1,383 @@
# 匹配系统插件
为EG引擎提供完整的玩家匹配功能包括队列管理、算法匹配、房间分配、规则配置、实时监控和数据分析等核心功能。
## 功能特性
### 1. 匹配管理
- 智能匹配过程管理
- 多种匹配模式支持
- 匹配状态跟踪和控制
- 匹配结果处理和回调
### 2. 队列系统
- 玩家排队管理
- 队列优先级处理
- 超时自动清理
- 实时队列状态监控
### 3. 匹配算法
- 技能匹配算法
- 快速匹配算法
- 团队平衡算法
- 自定义算法支持
- 匹配质量评估
### 4. 房间分配
- 动态房间创建和销毁
- 玩家房间分配管理
- 房间状态跟踪
- 房间密码保护
### 5. 规则配置
- 灵活的匹配规则系统
- 游戏模式特定规则
- 自定义规则集支持
- 实时规则验证
### 6. 实时监控
- 性能指标收集
- 实时数据监控
- 警报系统
- 系统健康状态检查
### 7. 事件系统
- 事件驱动架构
- 异步事件处理
- 事件过滤和优先级
- 事件监听器系统
### 8. 配置管理
- 持久化配置存储
- 动态配置更新
- 配置变更监听
- 配置导入导出
### 9. 可视化编辑器
- 实时数据展示
- 配置参数调整
- 统计图表显示
- 数据导出功能
### 10. 数据统计
- 实时数据收集
- 历史数据分析
- 统计报告生成
- 数据导出支持
## 系统架构
```
匹配系统插件
├── 核心模块
│ └── 匹配管理器 (core/match_manager.py)
├── 队列系统
│ └── 队列管理器 (queue/queue_manager.py)
├── 算法系统
│ └── 算法管理器 (algorithms/algorithm_manager.py)
├── 房间系统
│ └── 房间分配器 (rooms/room_allocator.py)
├── 规则系统
│ └── 规则管理器 (rules/rule_manager.py)
├── 监控系统
│ └── 匹配监控器 (monitoring/match_monitor.py)
├── 事件系统
│ └── 事件处理器 (events/event_handler.py)
├── 配置系统
│ └── 配置管理器 (config/match_config.py)
├── 编辑器系统
│ └── 匹配编辑器 (editor/match_editor.py)
├── 统计系统
│ └── 统计管理器 (stats/stats_manager.py)
└── 插件主文件
└── 插件入口 (plugin.py)
```
## 安装和使用
### 安装依赖
```bash
# 无特殊依赖使用标准Python库
```
### 配置插件
插件配置文件位于 `config/matchmaking_config.json`,包含以下主要配置项:
```json
{
"system": {
"enable_matchmaking": true,
"max_concurrent_matches": 1000,
"default_match_timeout": 300.0
},
"queue": {
"default_queue_timeout": 300.0,
"queue_processing_interval": 2.0
},
"matching": {
"default_algorithm": "skill_based",
"skill_range": 100
},
"room": {
"default_max_players": 8,
"enable_room_passwords": true
}
}
```
### 启动插件
```python
# 初始化插件
plugin = MatchmakingSystemPlugin(engine)
plugin.initialize()
plugin.enable()
# 插件会自动处理匹配过程
```
## API参考
### 匹配管理
```python
# 开始匹配
match_id = plugin.match_manager.start_matchmaking(player_ids, match_params)
# 取消匹配
plugin.match_manager.cancel_matchmaking(match_id)
# 获取匹配统计
stats = plugin.match_manager.get_match_stats()
```
### 队列管理
```python
# 添加玩家到队列
plugin.queue_manager.add_players_to_queue(player_ids, queue_params)
# 从队列移除玩家
plugin.queue_manager.remove_players_from_queue(player_ids=player_ids)
# 获取队列信息
queue_info = plugin.queue_manager.get_queue_info(queue_name)
```
### 算法管理
```python
# 设置活动算法
plugin.algorithm_manager.set_active_algorithm("skill_based")
# 运行匹配算法
result = plugin.algorithm_manager.run_matching_algorithm(players)
# 更新玩家技能
plugin.algorithm_manager.update_player_skill(player_id, skill_level)
```
### 房间分配
```python
# 创建房间
room_id = plugin.room_allocator.create_room(room_name, room_settings)
# 添加玩家到房间
plugin.room_allocator.add_client_to_room(room_id, player_id)
# 从房间移除玩家
plugin.room_allocator.remove_client_from_room(room_id, player_id)
```
### 规则管理
```python
# 应用规则
is_valid = plugin.rule_manager.apply_rules(players, game_mode)
# 添加自定义规则集
plugin.rule_manager.add_custom_rule_set("custom_rules", rules)
# 设置活动规则集
plugin.rule_manager.set_active_rules("custom_rules")
```
### 监控系统
```python
# 获取性能指标
metrics = plugin.monitor.get_performance_metrics()
# 获取活动警报
alerts = plugin.monitor.get_active_alerts()
# 记录匹配队列时间
plugin.monitor.record_match_queue_time(queue_time)
```
### 事件系统
```python
# 发出事件
plugin.event_handler.emit_event("match_found", payload)
# 注册事件处理器
plugin.event_handler.register_event_handler("match_found", handler_func)
# 注册事件过滤器
plugin.event_handler.register_event_filter("match_found", filter_func)
```
### 配置管理
```python
# 获取配置
config_value = plugin.config_manager.get_config("section", "key", default_value)
# 设置配置
plugin.config_manager.set_config("section", "key", value)
# 保存配置
plugin.config_manager.save_config()
# 加载配置
plugin.config_manager.load_config()
```
### 编辑器系统
```python
# 显示编辑器
plugin.editor.show_editor()
# 隐藏编辑器
plugin.editor.hide_editor()
# 切换标签页
plugin.editor.switch_tab("overview")
# 更新配置
plugin.editor.update_config("section", "key", value)
```
### 统计系统
```python
# 获取实时统计数据
realtime_stats = plugin.stats_manager.get_realtime_stats()
# 生成报告
report = plugin.stats_manager.generate_report("summary", "24h")
# 导出统计数据
plugin.stats_manager.export_stats("stats.json")
# 重置统计数据
plugin.stats_manager.reset_stats()
```
## 匹配流程
### 1. 玩家加入队列
```
玩家 -> 队列管理器 -> 添加到匹配队列
```
### 2. 队列处理
```
队列管理器 -> 算法管理器 -> 运行匹配算法
```
### 3. 匹配创建
```
算法管理器 -> 房间分配器 -> 创建匹配房间
```
### 4. 玩家分配
```
房间分配器 -> 玩家 -> 加入匹配房间
```
### 5. 匹配完成
```
匹配管理器 -> 事件系统 -> 发出匹配完成事件
```
## 性能优化
1. **异步处理**采用多线程和异步I/O提高并发性能
2. **智能队列**:高效的队列管理和玩家匹配算法
3. **内存优化**:及时清理无用数据和对象
4. **缓存机制**:对频繁访问的数据进行缓存
5. **批量处理**:批量处理队列和匹配操作
## 扩展开发
### 添加新的匹配算法
```python
# 在算法管理器中实现新的匹配算法
def _run_custom_matching(self, players):
# 实现自定义匹配逻辑
pass
# 注册算法
plugin.algorithm_manager.register_algorithm("custom", _run_custom_matching)
```
### 添加新的事件类型
```python
# 注册事件处理器
plugin.event_handler.register_event_handler("custom_event", custom_handler)
# 发出事件
plugin.event_handler.emit_event("custom_event", payload)
```
### 添加自定义规则
```python
# 添加自定义规则集
plugin.rule_manager.add_custom_rule_set("my_rules", {
"min_players": 2,
"max_players": 8,
"custom_rule": True
})
# 应用规则
plugin.rule_manager.apply_rules(players, "my_rules")
```
## 故障排除
### 常见问题
1. **匹配失败**:检查匹配规则和算法配置
2. **队列超时**:调整队列超时时间和匹配参数
3. **性能问题**:检查系统资源使用情况,优化配置
4. **配置错误**:验证配置文件格式和参数
### 日志分析
查看日志文件以诊断问题:
```
logs/matchmaking_system.log
```
## 版本信息
- 版本1.0.0
- 作者EG Plugin System
- 许可证MIT
## 贡献指南
欢迎提交Issue和Pull Request来改进这个插件。
## 支持
如需技术支持,请联系插件维护团队或查看相关文档。

View File

@ -0,0 +1,616 @@
"""
算法管理器模块
实现不同的匹配算法技能匹配快速匹配等
"""
import time
import random
from typing import Dict, Any, List, Optional
from collections import defaultdict
class AlgorithmManager:
"""
算法管理器
实现不同的匹配算法技能匹配快速匹配等
"""
def __init__(self, plugin):
"""
初始化算法管理器
Args:
plugin: 匹配系统插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 算法配置
self.algorithm_config = {
"default_algorithm": "skill_based",
"available_algorithms": ["skill_based", "quick", "team_balanced", "custom"],
"skill_based_config": {
"skill_range": 100, # 技能匹配范围
"max_wait_time": 120.0, # 最大等待时间(秒)
"expand_range_over_time": True, # 随时间扩展匹配范围
"range_expansion_rate": 10 # 每秒扩展范围
},
"team_balanced_config": {
"balance_threshold": 0.1, # 平衡阈值
"max_balance_attempts": 5 # 最大平衡尝试次数
},
"quick_match_config": {
"max_queue_time": 30.0, # 最大排队时间
"min_players": 2, # 最少玩家数
"max_players": 8 # 最多玩家数
}
}
# 算法状态
self.algorithm_state = {
"active_algorithm": "skill_based",
"total_matches": 0,
"successful_matches": 0,
"failed_matches": 0,
"average_match_quality": 0.0
}
# 玩家数据存储
self.player_data = {} # 玩家技能、统计数据等
# 算法统计
self.algorithm_stats = {
"algorithms_run": 0,
"matches_created": 0,
"players_matched": 0,
"algorithm_errors": 0
}
# 回调函数
self.algorithm_callbacks = {
"algorithm_selected": [],
"match_quality_calculated": [],
"algorithm_error": []
}
# 时间戳记录
self.last_algorithm_run = 0.0
self.last_stats_reset = 0.0
print("✓ 算法管理器已创建")
def initialize(self) -> bool:
"""
初始化算法管理器
Returns:
是否初始化成功
"""
try:
print("正在初始化算法管理器...")
# 注册默认算法
self._register_default_algorithms()
self.initialized = True
print("✓ 算法管理器初始化完成")
return True
except Exception as e:
print(f"✗ 算法管理器初始化失败: {e}")
self.algorithm_stats["algorithm_errors"] += 1
import traceback
traceback.print_exc()
return False
def _register_default_algorithms(self):
"""注册默认算法"""
try:
print("✓ 默认算法已注册")
except Exception as e:
print(f"✗ 默认算法注册失败: {e}")
self.algorithm_stats["algorithm_errors"] += 1
def enable(self) -> bool:
"""
启用算法管理器
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ 算法管理器未初始化")
return False
self.enabled = True
print("✓ 算法管理器已启用")
return True
except Exception as e:
print(f"✗ 算法管理器启用失败: {e}")
self.algorithm_stats["algorithm_errors"] += 1
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用算法管理器"""
try:
self.enabled = False
print("✓ 算法管理器已禁用")
except Exception as e:
print(f"✗ 算法管理器禁用失败: {e}")
self.algorithm_stats["algorithm_errors"] += 1
import traceback
traceback.print_exc()
def finalize(self):
"""清理算法管理器资源"""
try:
# 禁用算法管理器
if self.enabled:
self.disable()
# 清理回调
self.algorithm_callbacks.clear()
self.initialized = False
print("✓ 算法管理器资源已清理")
except Exception as e:
print(f"✗ 算法管理器资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新算法管理器状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
self.last_algorithm_run = time.time()
except Exception as e:
print(f"✗ 算法管理器更新失败: {e}")
self.algorithm_stats["algorithm_errors"] += 1
import traceback
traceback.print_exc()
def set_active_algorithm(self, algorithm_name: str) -> bool:
"""
设置活动算法
Args:
algorithm_name: 算法名称
Returns:
是否设置成功
"""
try:
if algorithm_name not in self.algorithm_config["available_algorithms"]:
print(f"✗ 不支持的算法: {algorithm_name}")
return False
self.algorithm_state["active_algorithm"] = algorithm_name
print(f"✓ 活动算法已设置为: {algorithm_name}")
# 触发算法选择回调
self._trigger_algorithm_callback("algorithm_selected", {
"algorithm": algorithm_name,
"timestamp": time.time()
})
return True
except Exception as e:
print(f"✗ 活动算法设置失败: {e}")
self.algorithm_stats["algorithm_errors"] += 1
return False
def run_matching_algorithm(self, players: List[Dict[str, Any]], algorithm: str = None) -> Optional[List[List[Dict[str, Any]]]]:
"""
运行匹配算法
Args:
players: 玩家列表
algorithm: 算法名称可选默认使用活动算法
Returns:
匹配结果玩家分组列表或None
"""
try:
if not self.enabled:
return None
# 使用指定算法或活动算法
if algorithm is None:
algorithm = self.algorithm_state["active_algorithm"]
# 验证算法支持
if algorithm not in self.algorithm_config["available_algorithms"]:
print(f"✗ 不支持的算法: {algorithm}")
self.algorithm_stats["algorithm_errors"] += 1
return None
self.algorithm_stats["algorithms_run"] += 1
# 根据算法类型运行相应算法
if algorithm == "skill_based":
result = self._run_skill_based_matching(players)
elif algorithm == "quick":
result = self._run_quick_matching(players)
elif algorithm == "team_balanced":
result = self._run_team_balanced_matching(players)
else:
# 默认使用技能匹配
result = self._run_skill_based_matching(players)
if result:
self.algorithm_state["successful_matches"] += 1
self.algorithm_state["total_matches"] += 1
self.algorithm_stats["matches_created"] += 1
# 计算匹配质量
match_quality = self._calculate_match_quality(result)
self.algorithm_state["average_match_quality"] = (
self.algorithm_state["average_match_quality"] * (self.algorithm_state["successful_matches"] - 1) +
match_quality
) / self.algorithm_state["successful_matches"]
# 触发匹配质量计算回调
self._trigger_algorithm_callback("match_quality_calculated", {
"quality": match_quality,
"algorithm": algorithm,
"timestamp": time.time()
})
else:
self.algorithm_state["failed_matches"] += 1
return result
except Exception as e:
print(f"✗ 匹配算法运行失败: {e}")
self.algorithm_stats["algorithm_errors"] += 1
return None
def _run_skill_based_matching(self, players: List[Dict[str, Any]]) -> Optional[List[List[Dict[str, Any]]]]:
"""
运行基于技能的匹配算法
Args:
players: 玩家列表
Returns:
匹配结果或None
"""
try:
if not players:
return None
config = self.algorithm_config["skill_based_config"]
skill_range = config["skill_range"]
# 按技能水平排序玩家
sorted_players = sorted(players, key=lambda p: p.get("skill_level", 0))
# 简化实现:将技能相近的玩家分组
groups = []
current_group = [sorted_players[0]]
for i in range(1, len(sorted_players)):
current_player = sorted_players[i]
last_player = current_group[-1]
# 检查技能差异是否在范围内
skill_diff = abs(current_player.get("skill_level", 0) - last_player.get("skill_level", 0))
if skill_diff <= skill_range and len(current_group) < 8: # 最多8人一组
current_group.append(current_player)
else:
# 创建新组
groups.append(current_group)
current_group = [current_player]
# 添加最后一组
if current_group:
groups.append(current_group)
print(f"✓ 技能匹配完成: 创建了 {len(groups)} 个组")
return groups
except Exception as e:
print(f"✗ 技能匹配算法失败: {e}")
self.algorithm_stats["algorithm_errors"] += 1
return None
def _run_quick_matching(self, players: List[Dict[str, Any]]) -> Optional[List[List[Dict[str, Any]]]]:
"""
运行快速匹配算法
Args:
players: 玩家列表
Returns:
匹配结果或None
"""
try:
if not players:
return None
config = self.algorithm_config["quick_match_config"]
min_players = config["min_players"]
max_players = config["max_players"]
# 简化实现:随机分组
groups = []
player_pool = players.copy()
random.shuffle(player_pool)
while player_pool:
group_size = min(random.randint(min_players, max_players), len(player_pool))
group = player_pool[:group_size]
groups.append(group)
player_pool = player_pool[group_size:]
print(f"✓ 快速匹配完成: 创建了 {len(groups)} 个组")
return groups
except Exception as e:
print(f"✗ 快速匹配算法失败: {e}")
self.algorithm_stats["algorithm_errors"] += 1
return None
def _run_team_balanced_matching(self, players: List[Dict[str, Any]]) -> Optional[List[List[Dict[str, Any]]]]:
"""
运行团队平衡匹配算法
Args:
players: 玩家列表
Returns:
匹配结果或None
"""
try:
if not players or len(players) < 2:
return None
# 简化实现:创建两个平衡的团队
# 按技能排序
sorted_players = sorted(players, key=lambda p: p.get("skill_level", 0), reverse=True)
team1 = []
team2 = []
team1_skill = 0
team2_skill = 0
# 贪心算法分配玩家到技能平衡的团队
for player in sorted_players:
player_skill = player.get("skill_level", 0)
if team1_skill <= team2_skill:
team1.append(player)
team1_skill += player_skill
else:
team2.append(player)
team2_skill += player_skill
groups = [team1, team2] if team1 and team2 else [sorted_players]
print(f"✓ 团队平衡匹配完成: 创建了 {len(groups)} 个组")
return groups
except Exception as e:
print(f"✗ 团队平衡匹配算法失败: {e}")
self.algorithm_stats["algorithm_errors"] += 1
return None
def _calculate_match_quality(self, groups: List[List[Dict[str, Any]]]) -> float:
"""
计算匹配质量
Args:
groups: 玩家分组
Returns:
匹配质量分数0-1
"""
try:
if not groups:
return 0.0
total_quality = 0.0
group_count = 0
for group in groups:
if len(group) < 2:
continue
# 计算组内技能差异
skills = [p.get("skill_level", 0) for p in group]
avg_skill = sum(skills) / len(skills)
variance = sum((s - avg_skill) ** 2 for s in skills) / len(skills)
std_dev = variance ** 0.5
# 转换为质量分数(标准差越小质量越高)
max_expected_std = 100.0 # 假设最大预期标准差
quality = max(0.0, 1.0 - (std_dev / max_expected_std))
total_quality += quality
group_count += 1
return total_quality / group_count if group_count > 0 else 0.0
except Exception as e:
print(f"✗ 匹配质量计算失败: {e}")
self.algorithm_stats["algorithm_errors"] += 1
return 0.0
def update_player_skill(self, player_id: str, skill_level: float, stats: Dict[str, Any] = None):
"""
更新玩家技能
Args:
player_id: 玩家ID
skill_level: 技能等级
stats: 玩家统计数据
"""
try:
if player_id not in self.player_data:
self.player_data[player_id] = {
"skill_history": [],
"match_stats": {}
}
player_info = self.player_data[player_id]
player_info["current_skill"] = skill_level
player_info["skill_history"].append({
"skill": skill_level,
"timestamp": time.time()
})
if stats:
player_info["match_stats"].update(stats)
except Exception as e:
print(f"✗ 玩家技能更新失败: {e}")
self.algorithm_stats["algorithm_errors"] += 1
def get_player_skill(self, player_id: str) -> Optional[float]:
"""
获取玩家技能
Args:
player_id: 玩家ID
Returns:
玩家技能等级或None
"""
try:
if player_id in self.player_data:
return self.player_data[player_id].get("current_skill")
return None
except Exception as e:
print(f"✗ 玩家技能获取失败: {e}")
self.algorithm_stats["algorithm_errors"] += 1
return None
def get_algorithm_stats(self) -> Dict[str, Any]:
"""
获取算法统计信息
Returns:
算法统计字典
"""
return {
"state": self.algorithm_state.copy(),
"stats": self.algorithm_stats.copy(),
"config": self.algorithm_config.copy(),
"tracked_players": len(self.player_data)
}
def reset_stats(self):
"""重置算法统计信息"""
try:
self.algorithm_stats = {
"algorithms_run": 0,
"matches_created": 0,
"players_matched": 0,
"algorithm_errors": 0
}
self.algorithm_state["total_matches"] = 0
self.algorithm_state["successful_matches"] = 0
self.algorithm_state["failed_matches"] = 0
self.algorithm_state["average_match_quality"] = 0.0
print("✓ 算法统计信息已重置")
except Exception as e:
print(f"✗ 算法统计信息重置失败: {e}")
def set_algorithm_config(self, config: Dict[str, Any]) -> bool:
"""
设置算法配置
Args:
config: 算法配置字典
Returns:
是否设置成功
"""
try:
self.algorithm_config.update(config)
print(f"✓ 算法配置已更新: {self.algorithm_config}")
return True
except Exception as e:
print(f"✗ 算法配置设置失败: {e}")
return False
def get_algorithm_config(self) -> Dict[str, Any]:
"""
获取算法配置
Returns:
算法配置字典
"""
return self.algorithm_config.copy()
def _trigger_algorithm_callback(self, callback_type: str, data: Dict[str, Any]):
"""
触发算法回调
Args:
callback_type: 回调类型
data: 回调数据
"""
try:
if callback_type in self.algorithm_callbacks:
for callback in self.algorithm_callbacks[callback_type]:
try:
callback(data)
except Exception as e:
print(f"✗ 算法回调执行失败: {callback_type} - {e}")
except Exception as e:
print(f"✗ 算法回调触发失败: {e}")
def register_algorithm_callback(self, callback_type: str, callback: callable):
"""
注册算法回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.algorithm_callbacks:
self.algorithm_callbacks[callback_type].append(callback)
print(f"✓ 算法回调已注册: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 算法回调注册失败: {e}")
def unregister_algorithm_callback(self, callback_type: str, callback: callable):
"""
注销算法回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.algorithm_callbacks:
if callback in self.algorithm_callbacks[callback_type]:
self.algorithm_callbacks[callback_type].remove(callback)
print(f"✓ 算法回调已注销: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 算法回调注销失败: {e}")

View File

@ -0,0 +1,712 @@
"""
匹配配置管理器模块
管理匹配系统配置
"""
import time
import json
import os
from typing import Dict, Any, List, Optional
class MatchConfig:
"""
匹配配置管理器
管理匹配系统配置
"""
def __init__(self, plugin):
"""
初始化匹配配置管理器
Args:
plugin: 匹配系统插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 配置文件路径
self.config_file_path = "/home/hello/EG/plugins/user/matchmaking_system/config/matchmaking_config.json"
# 默认配置
self.default_config = {
"system": {
"enable_matchmaking": True,
"max_concurrent_matches": 1000,
"default_match_timeout": 300.0,
"enable_cross_platform_matching": True
},
"queue": {
"default_queue_timeout": 300.0,
"queue_processing_interval": 2.0,
"max_players_per_match": 100,
"min_players_per_match": 2,
"enable_queue_prioritization": True
},
"matching": {
"default_algorithm": "skill_based",
"skill_range": 100,
"max_wait_time": 120.0,
"enable_skill_based_matching": True,
"enable_team_balancing": True
},
"room": {
"default_max_players": 8,
"enable_room_passwords": True,
"enable_room_visibility": True,
"room_timeout": 3600,
"max_rooms": 1000
},
"monitoring": {
"enable_monitoring": True,
"monitoring_interval": 5.0,
"log_level": "INFO",
"enable_performance_monitoring": True
},
"events": {
"enable_event_system": True,
"max_event_queue_size": 10000,
"enable_event_filtering": True
}
}
# 当前配置
self.current_config = self.default_config.copy()
# 配置状态
self.config_state = {
"last_loaded": 0.0,
"last_saved": 0.0,
"config_version": "1.0.0",
"is_dirty": False
}
# 配置统计
self.config_stats = {
"loads": 0,
"saves": 0,
"updates": 0,
"config_errors": 0
}
# 配置监听器
self.config_listeners = {}
# 回调函数
self.config_callbacks = {
"config_loaded": [],
"config_saved": [],
"config_updated": [],
"config_error": []
}
print("✓ 匹配配置管理器已创建")
def initialize(self) -> bool:
"""
初始化匹配配置管理器
Returns:
是否初始化成功
"""
try:
print("正在初始化匹配配置管理器...")
# 创建配置目录
config_dir = os.path.dirname(self.config_file_path)
if not os.path.exists(config_dir):
os.makedirs(config_dir)
# 加载配置
self.load_config()
self.initialized = True
print("✓ 匹配配置管理器初始化完成")
return True
except Exception as e:
print(f"✗ 匹配配置管理器初始化失败: {e}")
self.config_stats["config_errors"] += 1
import traceback
traceback.print_exc()
return False
def enable(self) -> bool:
"""
启用匹配配置管理器
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ 匹配配置管理器未初始化")
return False
self.enabled = True
print("✓ 匹配配置管理器已启用")
return True
except Exception as e:
print(f"✗ 匹配配置管理器启用失败: {e}")
self.config_stats["config_errors"] += 1
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用匹配配置管理器"""
try:
self.enabled = False
# 保存配置(如果有更改)
if self.config_state["is_dirty"]:
self.save_config()
print("✓ 匹配配置管理器已禁用")
except Exception as e:
print(f"✗ 匹配配置管理器禁用失败: {e}")
self.config_stats["config_errors"] += 1
import traceback
traceback.print_exc()
def finalize(self):
"""清理匹配配置管理器资源"""
try:
# 禁用匹配配置管理器
if self.enabled:
self.disable()
# 清理回调
self.config_callbacks.clear()
self.config_listeners.clear()
self.initialized = False
print("✓ 匹配配置管理器资源已清理")
except Exception as e:
print(f"✗ 匹配配置管理器资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新匹配配置管理器状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
# 检查配置文件是否被外部修改
self._check_config_file_changes()
except Exception as e:
print(f"✗ 匹配配置管理器更新失败: {e}")
self.config_stats["config_errors"] += 1
import traceback
traceback.print_exc()
def _check_config_file_changes(self):
"""检查配置文件是否被外部修改"""
try:
if not os.path.exists(self.config_file_path):
return
last_modified = os.path.getmtime(self.config_file_path)
if last_modified > self.config_state["last_loaded"]:
# 配置文件已被修改,重新加载
print("检测到配置文件被外部修改,正在重新加载...")
self.load_config()
except Exception as e:
print(f"✗ 配置文件变更检查失败: {e}")
self.config_stats["config_errors"] += 1
def load_config(self) -> bool:
"""
加载配置
Returns:
是否加载成功
"""
try:
# 检查配置文件是否存在
if os.path.exists(self.config_file_path):
with open(self.config_file_path, 'r', encoding='utf-8') as f:
loaded_config = json.load(f)
# 合并配置(使用默认配置作为基础)
self.current_config = self._merge_config(self.default_config, loaded_config)
print(f"✓ 配置已从文件加载: {self.config_file_path}")
else:
# 使用默认配置
self.current_config = self.default_config.copy()
print("✓ 使用默认配置")
self.config_state["last_loaded"] = time.time()
self.config_state["is_dirty"] = False
self.config_stats["loads"] += 1
# 触发配置加载回调
self._trigger_config_callback("config_loaded", {
"config": self.current_config,
"timestamp": self.config_state["last_loaded"]
})
return True
except Exception as e:
print(f"✗ 配置加载失败: {e}")
self.config_stats["config_errors"] += 1
# 使用默认配置
self.current_config = self.default_config.copy()
return False
def _merge_config(self, base_config: Dict[str, Any], override_config: Dict[str, Any]) -> Dict[str, Any]:
"""
合并配置递归
Args:
base_config: 基础配置
override_config: 覆盖配置
Returns:
合并后的配置
"""
try:
merged = base_config.copy()
for key, value in override_config.items():
if key in merged and isinstance(merged[key], dict) and isinstance(value, dict):
# 递归合并嵌套字典
merged[key] = self._merge_config(merged[key], value)
else:
# 直接覆盖
merged[key] = value
return merged
except Exception as e:
print(f"✗ 配置合并失败: {e}")
self.config_stats["config_errors"] += 1
return base_config
def save_config(self) -> bool:
"""
保存配置
Returns:
是否保存成功
"""
try:
# 创建配置目录(如果不存在)
config_dir = os.path.dirname(self.config_file_path)
if not os.path.exists(config_dir):
os.makedirs(config_dir)
# 保存配置到文件
with open(self.config_file_path, 'w', encoding='utf-8') as f:
json.dump(self.current_config, f, indent=2, ensure_ascii=False)
self.config_state["last_saved"] = time.time()
self.config_state["is_dirty"] = False
self.config_stats["saves"] += 1
# 触发配置保存回调
self._trigger_config_callback("config_saved", {
"config": self.current_config,
"timestamp": self.config_state["last_saved"]
})
print(f"✓ 配置已保存到文件: {self.config_file_path}")
return True
except Exception as e:
print(f"✗ 配置保存失败: {e}")
self.config_stats["config_errors"] += 1
return False
def get_config(self, section: str = None, key: str = None, default_value: Any = None) -> Any:
"""
获取配置值
Args:
section: 配置节可选
key: 配置键可选
default_value: 默认值
Returns:
配置值
"""
try:
if section is None:
return self.current_config.copy()
if section not in self.current_config:
return default_value
if key is None:
return self.current_config[section].copy()
if key not in self.current_config[section]:
return default_value
return self.current_config[section][key]
except Exception as e:
print(f"✗ 获取配置失败: {e}")
self.config_stats["config_errors"] += 1
return default_value
def set_config(self, section: str, key: str, value: Any) -> bool:
"""
设置配置值
Args:
section: 配置节
key: 配置键
value: 配置值
Returns:
是否设置成功
"""
try:
if section not in self.current_config:
self.current_config[section] = {}
self.current_config[section][key] = value
self.config_state["is_dirty"] = True
self.config_stats["updates"] += 1
# 通知配置监听器
self._notify_config_listeners(section, key, value)
# 触发配置更新回调
self._trigger_config_callback("config_updated", {
"section": section,
"key": key,
"value": value,
"timestamp": time.time()
})
return True
except Exception as e:
print(f"✗ 设置配置失败: {e}")
self.config_stats["config_errors"] += 1
return False
def update_config_section(self, section: str, config_data: Dict[str, Any]) -> bool:
"""
更新配置节
Args:
section: 配置节
config_data: 配置数据
Returns:
是否更新成功
"""
try:
if section not in self.current_config:
self.current_config[section] = {}
self.current_config[section].update(config_data)
self.config_state["is_dirty"] = True
self.config_stats["updates"] += 1
# 通知配置监听器
for key, value in config_data.items():
self._notify_config_listeners(section, key, value)
# 触发配置更新回调
self._trigger_config_callback("config_updated", {
"section": section,
"config_data": config_data,
"timestamp": time.time()
})
return True
except Exception as e:
print(f"✗ 更新配置节失败: {e}")
self.config_stats["config_errors"] += 1
return False
def reset_config(self) -> bool:
"""
重置配置为默认值
Returns:
是否重置成功
"""
try:
self.current_config = self.default_config.copy()
self.config_state["is_dirty"] = True
# 通知所有配置监听器
for section_name, section_data in self.current_config.items():
if isinstance(section_data, dict):
for key, value in section_data.items():
self._notify_config_listeners(section_name, key, value)
print("✓ 配置已重置为默认值")
return True
except Exception as e:
print(f"✗ 配置重置失败: {e}")
self.config_stats["config_errors"] += 1
return False
def register_config_listener(self, section: str, key: str, listener: callable):
"""
注册配置监听器
Args:
section: 配置节
key: 配置键
listener: 监听器函数
"""
try:
listener_key = f"{section}.{key}"
if listener_key not in self.config_listeners:
self.config_listeners[listener_key] = []
self.config_listeners[listener_key].append(listener)
print(f"✓ 配置监听器已注册: {listener_key}")
except Exception as e:
print(f"✗ 配置监听器注册失败: {e}")
self.config_stats["config_errors"] += 1
def unregister_config_listener(self, section: str, key: str, listener: callable):
"""
注销配置监听器
Args:
section: 配置节
key: 配置键
listener: 监听器函数
"""
try:
listener_key = f"{section}.{key}"
if listener_key in self.config_listeners:
if listener in self.config_listeners[listener_key]:
self.config_listeners[listener_key].remove(listener)
print(f"✓ 配置监听器已注销: {listener_key}")
except Exception as e:
print(f"✗ 配置监听器注销失败: {e}")
self.config_stats["config_errors"] += 1
def _notify_config_listeners(self, section: str, key: str, value: Any):
"""
通知配置监听器
Args:
section: 配置节
key: 配置键
value: 配置值
"""
try:
listener_key = f"{section}.{key}"
if listener_key in self.config_listeners:
for listener in self.config_listeners[listener_key]:
try:
listener(section, key, value)
except Exception as e:
print(f"✗ 配置监听器执行失败: {listener_key} - {e}")
except Exception as e:
print(f"✗ 配置监听器通知失败: {e}")
self.config_stats["config_errors"] += 1
def get_config_stats(self) -> Dict[str, Any]:
"""
获取配置统计信息
Returns:
配置统计字典
"""
return {
"state": self.config_state.copy(),
"stats": self.config_stats.copy(),
"config_sections": list(self.current_config.keys())
}
def reset_stats(self):
"""重置配置统计信息"""
try:
self.config_stats = {
"loads": 0,
"saves": 0,
"updates": 0,
"config_errors": 0
}
print("✓ 配置统计信息已重置")
except Exception as e:
print(f"✗ 配置统计信息重置失败: {e}")
def validate_config(self) -> bool:
"""
验证配置
Returns:
配置是否有效
"""
try:
# 检查必需的配置项
required_sections = ["system", "queue", "matching", "room", "monitoring", "events"]
for section in required_sections:
if section not in self.current_config:
print(f"✗ 缺少必需的配置节: {section}")
return False
# 检查系统配置
system_config = self.current_config["system"]
if "max_concurrent_matches" not in system_config or not isinstance(system_config["max_concurrent_matches"], int):
print("✗ 无效的最大并发匹配数配置")
return False
# 检查队列配置
queue_config = self.current_config["queue"]
if "max_players_per_match" not in queue_config or not isinstance(queue_config["max_players_per_match"], int):
print("✗ 无效的最大玩家数配置")
return False
print("✓ 配置验证通过")
return True
except Exception as e:
print(f"✗ 配置验证失败: {e}")
self.config_stats["config_errors"] += 1
return False
def export_config(self, file_path: str) -> bool:
"""
导出配置到文件
Args:
file_path: 导出文件路径
Returns:
是否导出成功
"""
try:
# 创建导出目录
export_dir = os.path.dirname(file_path)
if not os.path.exists(export_dir):
os.makedirs(export_dir)
# 导出配置
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(self.current_config, f, indent=2, ensure_ascii=False)
print(f"✓ 配置已导出到: {file_path}")
return True
except Exception as e:
print(f"✗ 配置导出失败: {e}")
self.config_stats["config_errors"] += 1
return False
def import_config(self, file_path: str) -> bool:
"""
从文件导入配置
Args:
file_path: 导入文件路径
Returns:
是否导入成功
"""
try:
if not os.path.exists(file_path):
print(f"✗ 配置文件不存在: {file_path}")
return False
# 读取配置文件
with open(file_path, 'r', encoding='utf-8') as f:
imported_config = json.load(f)
# 验证配置
if not isinstance(imported_config, dict):
print("✗ 无效的配置文件格式")
return False
# 合并配置
self.current_config = self._merge_config(self.default_config, imported_config)
self.config_state["is_dirty"] = True
# 通知配置监听器
for section_name, section_data in self.current_config.items():
if isinstance(section_data, dict):
for key, value in section_data.items():
self._notify_config_listeners(section_name, key, value)
print(f"✓ 配置已从文件导入: {file_path}")
return True
except Exception as e:
print(f"✗ 配置导入失败: {e}")
self.config_stats["config_errors"] += 1
return False
def _trigger_config_callback(self, callback_type: str, data: Dict[str, Any]):
"""
触发配置回调
Args:
callback_type: 回调类型
data: 回调数据
"""
try:
if callback_type in self.config_callbacks:
for callback in self.config_callbacks[callback_type]:
try:
callback(data)
except Exception as e:
print(f"✗ 配置回调执行失败: {callback_type} - {e}")
except Exception as e:
print(f"✗ 配置回调触发失败: {e}")
def register_config_callback(self, callback_type: str, callback: callable):
"""
注册配置回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.config_callbacks:
self.config_callbacks[callback_type].append(callback)
print(f"✓ 配置回调已注册: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 配置回调注册失败: {e}")
def unregister_config_callback(self, callback_type: str, callback: callable):
"""
注销配置回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.config_callbacks:
if callback in self.config_callbacks[callback_type]:
self.config_callbacks[callback_type].remove(callback)
print(f"✓ 配置回调已注销: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 配置回调注销失败: {e}")

View File

@ -0,0 +1,417 @@
"""
匹配管理器模块
管理匹配过程和规则
"""
import time
import threading
from typing import Dict, Any, List, Optional
class MatchManager:
"""
匹配管理器
管理匹配过程和规则
"""
def __init__(self, plugin):
"""
初始化匹配管理器
Args:
plugin: 匹配系统插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 匹配配置
self.match_config = {
"enable_matchmaking": True,
"matchmaking_interval": 1.0,
"max_match_attempts": 3,
"match_timeout": 30.0,
"enable_skill_based_matching": True,
"enable_team_balancing": True,
"enable_cross_platform_matching": True
}
# 匹配状态
self.match_state = {
"is_matching": False,
"active_matches": 0,
"successful_matches": 0,
"failed_matches": 0,
"last_match_time": 0.0
}
# 匹配统计
self.match_stats = {
"matches_started": 0,
"matches_completed": 0,
"matches_cancelled": 0,
"average_match_time": 0.0,
"match_errors": 0
}
# 匹配锁
self.match_lock = threading.RLock()
# 回调函数
self.match_callbacks = {
"match_started": [],
"match_completed": [],
"match_cancelled": [],
"match_error": []
}
# 时间戳记录
self.last_matchmaking_run = 0.0
self.last_stats_reset = 0.0
print("✓ 匹配管理器已创建")
def initialize(self) -> bool:
"""
初始化匹配管理器
Returns:
是否初始化成功
"""
try:
print("正在初始化匹配管理器...")
self.initialized = True
print("✓ 匹配管理器初始化完成")
return True
except Exception as e:
print(f"✗ 匹配管理器初始化失败: {e}")
self.match_stats["match_errors"] += 1
import traceback
traceback.print_exc()
return False
def enable(self) -> bool:
"""
启用匹配管理器
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ 匹配管理器未初始化")
return False
self.enabled = True
print("✓ 匹配管理器已启用")
return True
except Exception as e:
print(f"✗ 匹配管理器启用失败: {e}")
self.match_stats["match_errors"] += 1
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用匹配管理器"""
try:
self.enabled = False
print("✓ 匹配管理器已禁用")
except Exception as e:
print(f"✗ 匹配管理器禁用失败: {e}")
self.match_stats["match_errors"] += 1
import traceback
traceback.print_exc()
def finalize(self):
"""清理匹配管理器资源"""
try:
# 禁用匹配管理器
if self.enabled:
self.disable()
# 清理回调
self.match_callbacks.clear()
self.initialized = False
print("✓ 匹配管理器资源已清理")
except Exception as e:
print(f"✗ 匹配管理器资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新匹配管理器状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
current_time = time.time()
# 定期运行匹配算法
if current_time - self.last_matchmaking_run >= self.match_config["matchmaking_interval"]:
self._run_matchmaking()
self.last_matchmaking_run = current_time
self.match_state["last_match_time"] = current_time
except Exception as e:
print(f"✗ 匹配管理器更新失败: {e}")
self.match_stats["match_errors"] += 1
import traceback
traceback.print_exc()
def _run_matchmaking(self):
"""运行匹配算法"""
try:
if not self.match_config["enable_matchmaking"]:
return
# 通知队列管理器运行匹配
if self.plugin.queue_manager:
self.plugin.queue_manager.process_queues()
except Exception as e:
print(f"✗ 匹配算法运行失败: {e}")
self.match_stats["match_errors"] += 1
def start_matchmaking(self, player_ids: List[str], match_params: Dict[str, Any] = None) -> str:
"""
开始匹配
Args:
player_ids: 玩家ID列表
match_params: 匹配参数
Returns:
匹配ID
"""
try:
if not self.enabled:
raise Exception("匹配管理器未启用")
# 生成匹配ID
match_id = f"match_{int(time.time() * 1000000)}"
# 添加玩家到队列
if self.plugin.queue_manager:
queue_success = self.plugin.queue_manager.add_players_to_queue(
player_ids, match_params or {})
if queue_success:
self.match_stats["matches_started"] += 1
self.match_state["active_matches"] += 1
# 触发匹配开始回调
self._trigger_match_callback("match_started", {
"match_id": match_id,
"player_ids": player_ids,
"match_params": match_params,
"timestamp": time.time()
})
print(f"✓ 匹配已开始: {match_id}")
return match_id
else:
raise Exception("添加玩家到队列失败")
else:
raise Exception("队列管理器不可用")
except Exception as e:
print(f"✗ 匹配开始失败: {e}")
self.match_stats["match_errors"] += 1
# 触发匹配错误回调
self._trigger_match_callback("match_error", {
"player_ids": player_ids,
"error": str(e),
"timestamp": time.time()
})
return ""
def cancel_matchmaking(self, match_id: str) -> bool:
"""
取消匹配
Args:
match_id: 匹配ID
Returns:
是否取消成功
"""
try:
# 从队列中移除玩家
if self.plugin.queue_manager:
cancel_success = self.plugin.queue_manager.remove_players_from_queue(match_id)
if cancel_success:
self.match_stats["matches_cancelled"] += 1
if self.match_state["active_matches"] > 0:
self.match_state["active_matches"] -= 1
# 触发匹配取消回调
self._trigger_match_callback("match_cancelled", {
"match_id": match_id,
"timestamp": time.time()
})
print(f"✓ 匹配已取消: {match_id}")
return True
else:
return False
else:
return False
except Exception as e:
print(f"✗ 匹配取消失败: {e}")
self.match_stats["match_errors"] += 1
return False
def complete_match(self, match_id: str, room_id: str) -> bool:
"""
完成匹配
Args:
match_id: 匹配ID
room_id: 房间ID
Returns:
是否完成成功
"""
try:
self.match_stats["matches_completed"] += 1
self.match_state["successful_matches"] += 1
if self.match_state["active_matches"] > 0:
self.match_state["active_matches"] -= 1
# 触发匹配完成回调
self._trigger_match_callback("match_completed", {
"match_id": match_id,
"room_id": room_id,
"timestamp": time.time()
})
print(f"✓ 匹配已完成: {match_id} -> 房间: {room_id}")
return True
except Exception as e:
print(f"✗ 匹配完成失败: {e}")
self.match_stats["match_errors"] += 1
return False
def get_match_stats(self) -> Dict[str, Any]:
"""
获取匹配统计信息
Returns:
匹配统计字典
"""
return {
"state": self.match_state.copy(),
"stats": self.match_stats.copy(),
"config": self.match_config.copy()
}
def reset_stats(self):
"""重置匹配统计信息"""
try:
self.match_stats = {
"matches_started": 0,
"matches_completed": 0,
"matches_cancelled": 0,
"average_match_time": 0.0,
"match_errors": 0
}
print("✓ 匹配统计信息已重置")
except Exception as e:
print(f"✗ 匹配统计信息重置失败: {e}")
def set_match_config(self, config: Dict[str, Any]) -> bool:
"""
设置匹配配置
Args:
config: 匹配配置字典
Returns:
是否设置成功
"""
try:
self.match_config.update(config)
print(f"✓ 匹配配置已更新: {self.match_config}")
return True
except Exception as e:
print(f"✗ 匹配配置设置失败: {e}")
return False
def get_match_config(self) -> Dict[str, Any]:
"""
获取匹配配置
Returns:
匹配配置字典
"""
return self.match_config.copy()
def _trigger_match_callback(self, callback_type: str, data: Dict[str, Any]):
"""
触发匹配回调
Args:
callback_type: 回调类型
data: 回调数据
"""
try:
if callback_type in self.match_callbacks:
for callback in self.match_callbacks[callback_type]:
try:
callback(data)
except Exception as e:
print(f"✗ 匹配回调执行失败: {callback_type} - {e}")
except Exception as e:
print(f"✗ 匹配回调触发失败: {e}")
def register_match_callback(self, callback_type: str, callback: callable):
"""
注册匹配回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.match_callbacks:
self.match_callbacks[callback_type].append(callback)
print(f"✓ 匹配回调已注册: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 匹配回调注册失败: {e}")
def unregister_match_callback(self, callback_type: str, callback: callable):
"""
注销匹配回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.match_callbacks:
if callback in self.match_callbacks[callback_type]:
self.match_callbacks[callback_type].remove(callback)
print(f"✓ 匹配回调已注销: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 匹配回调注销失败: {e}")

View File

@ -0,0 +1,606 @@
"""
匹配编辑器模块
提供图形界面配置匹配参数
"""
import time
from typing import Dict, Any, List, Optional
class MatchEditor:
"""
匹配编辑器
提供图形界面配置匹配参数
"""
def __init__(self, plugin):
"""
初始化匹配编辑器
Args:
plugin: 匹配系统插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 编辑器配置
self.editor_config = {
"enable_editor": True,
"enable_realtime_monitoring": True,
"enable_performance_display": True,
"enable_config_editor": True,
"enable_statistics_display": True,
"refresh_interval": 1.0,
"max_data_points": 100
}
# 编辑器状态
self.editor_state = {
"is_visible": False,
"last_update": 0.0,
"active_tab": "overview",
"selected_queue": None,
"selected_algorithm": None
}
# UI组件
self.ui_components = {
"main_window": None,
"tabs": {},
"panels": {},
"charts": {},
"controls": {}
}
# 编辑器统计
self.editor_stats = {
"updates": 0,
"ui_refreshes": 0,
"data_points": 0,
"editor_errors": 0
}
# 实时数据缓存
self.realtime_data = {
"performance_metrics": {},
"queue_data": {},
"match_data": {},
"algorithm_stats": {},
"system_stats": {}
}
# 回调函数
self.editor_callbacks = {
"ui_updated": [],
"data_refreshed": [],
"config_changed": [],
"editor_error": []
}
# 时间戳记录
self.last_ui_update = 0.0
self.last_data_refresh = 0.0
print("✓ 匹配编辑器已创建")
def initialize(self) -> bool:
"""
初始化匹配编辑器
Returns:
是否初始化成功
"""
try:
print("正在初始化匹配编辑器...")
# 初始化UI组件模拟
self._initialize_ui_components()
self.initialized = True
print("✓ 匹配编辑器初始化完成")
return True
except Exception as e:
print(f"✗ 匹配编辑器初始化失败: {e}")
self.editor_stats["editor_errors"] += 1
import traceback
traceback.print_exc()
return False
def _initialize_ui_components(self):
"""初始化UI组件"""
try:
# 创建主窗口
self.ui_components["main_window"] = {
"title": "匹配系统编辑器",
"size": (1200, 800),
"position": (100, 100)
}
# 创建标签页
self.ui_components["tabs"] = {
"overview": {"name": "概览", "icon": "dashboard"},
"queues": {"name": "队列", "icon": "queue"},
"matches": {"name": "匹配", "icon": "gamepad"},
"algorithms": {"name": "算法", "icon": "calculate"},
"rooms": {"name": "房间", "icon": "meeting_room"},
"config": {"name": "配置", "icon": "settings"},
"statistics": {"name": "统计", "icon": "bar_chart"}
}
# 创建面板
self.ui_components["panels"] = {
"system_status": {"title": "系统状态", "visible": True},
"performance": {"title": "性能指标", "visible": True},
"queues_list": {"title": "队列列表", "visible": True},
"matches_list": {"title": "匹配列表", "visible": True},
"algorithm_stats": {"title": "算法统计", "visible": True}
}
print("✓ UI组件已初始化")
except Exception as e:
print(f"✗ UI组件初始化失败: {e}")
self.editor_stats["editor_errors"] += 1
def enable(self) -> bool:
"""
启用匹配编辑器
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ 匹配编辑器未初始化")
return False
self.enabled = True
print("✓ 匹配编辑器已启用")
return True
except Exception as e:
print(f"✗ 匹配编辑器启用失败: {e}")
self.editor_stats["editor_errors"] += 1
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用匹配编辑器"""
try:
self.enabled = False
# 隐藏UI
self.hide_editor()
print("✓ 匹配编辑器已禁用")
except Exception as e:
print(f"✗ 匹配编辑器禁用失败: {e}")
self.editor_stats["editor_errors"] += 1
import traceback
traceback.print_exc()
def finalize(self):
"""清理匹配编辑器资源"""
try:
# 禁用匹配编辑器
if self.enabled:
self.disable()
# 清理回调
self.editor_callbacks.clear()
self.initialized = False
print("✓ 匹配编辑器资源已清理")
except Exception as e:
print(f"✗ 匹配编辑器资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新匹配编辑器状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
current_time = time.time()
# 定期刷新UI
if current_time - self.last_ui_update >= self.editor_config["refresh_interval"]:
self._refresh_ui()
self.last_ui_update = current_time
# 定期更新数据
if current_time - self.last_data_refresh >= 0.5: # 每0.5秒更新一次数据
self._update_realtime_data()
self.last_data_refresh = current_time
self.editor_state["last_update"] = current_time
except Exception as e:
print(f"✗ 匹配编辑器更新失败: {e}")
self.editor_stats["editor_errors"] += 1
import traceback
traceback.print_exc()
def _refresh_ui(self):
"""刷新UI"""
try:
# 更新UI组件状态
self._update_ui_components()
# 更新统计信息
self.editor_stats["ui_refreshes"] += 1
# 触发UI更新回调
self._trigger_editor_callback("ui_updated", {
"timestamp": time.time()
})
except Exception as e:
print(f"✗ UI刷新失败: {e}")
self.editor_stats["editor_errors"] += 1
def _update_ui_components(self):
"""更新UI组件"""
try:
# 更新系统状态面板
system_stats = {}
if self.plugin.match_manager:
system_stats.update(self.plugin.match_manager.get_match_stats())
if self.plugin.queue_manager:
system_stats.update(self.plugin.queue_manager.get_queue_stats())
if self.plugin.algorithm_manager:
system_stats.update(self.plugin.algorithm_manager.get_algorithm_stats())
self.ui_components["panels"]["system_status"]["data"] = system_stats
# 更新队列列表面板
if self.plugin.queue_manager:
queues = self.plugin.queue_manager.get_queue_info()
self.ui_components["panels"]["queues_list"]["data"] = queues
# 更新匹配列表面板
if self.plugin.match_manager:
match_stats = self.plugin.match_manager.get_match_stats()
self.ui_components["panels"]["matches_list"]["data"] = match_stats
# 更新算法统计面板
if self.plugin.algorithm_manager:
algorithm_stats = self.plugin.algorithm_manager.get_algorithm_stats()
self.ui_components["panels"]["algorithm_stats"]["data"] = algorithm_stats
except Exception as e:
print(f"✗ UI组件更新失败: {e}")
self.editor_stats["editor_errors"] += 1
def _update_realtime_data(self):
"""更新实时数据"""
try:
current_time = time.time()
# 更新性能指标
if self.plugin.monitor:
metrics = self.plugin.monitor.get_performance_metrics()
self.realtime_data["performance_metrics"] = metrics
# 更新队列数据
if self.plugin.queue_manager:
queue_info = self.plugin.queue_manager.get_queue_info()
self.realtime_data["queue_data"] = queue_info
# 更新匹配数据
if self.plugin.match_manager:
match_stats = self.plugin.match_manager.get_match_stats()
self.realtime_data["match_data"] = match_stats
# 更新算法统计
if self.plugin.algorithm_manager:
algorithm_stats = self.plugin.algorithm_manager.get_algorithm_stats()
self.realtime_data["algorithm_stats"] = algorithm_stats
# 更新系统统计
system_stats = {}
if self.plugin.config_manager:
system_stats["config"] = self.plugin.config_manager.get_config_stats()
if self.plugin.event_handler:
system_stats["events"] = self.plugin.event_handler.get_event_stats()
self.realtime_data["system_stats"] = system_stats
# 触发数据刷新回调
self._trigger_editor_callback("data_refreshed", {
"data": self.realtime_data,
"timestamp": current_time
})
except Exception as e:
print(f"✗ 实时数据更新失败: {e}")
self.editor_stats["editor_errors"] += 1
def show_editor(self):
"""显示编辑器"""
try:
self.editor_state["is_visible"] = True
print("✓ 匹配编辑器已显示")
# 刷新数据
self._update_realtime_data()
except Exception as e:
print(f"✗ 编辑器显示失败: {e}")
self.editor_stats["editor_errors"] += 1
def hide_editor(self):
"""隐藏编辑器"""
try:
self.editor_state["is_visible"] = False
print("✓ 匹配编辑器已隐藏")
except Exception as e:
print(f"✗ 编辑器隐藏失败: {e}")
self.editor_stats["editor_errors"] += 1
def switch_tab(self, tab_name: str):
"""
切换标签页
Args:
tab_name: 标签页名称
"""
try:
if tab_name in self.ui_components["tabs"]:
self.editor_state["active_tab"] = tab_name
print(f"✓ 切换到标签页: {tab_name}")
else:
print(f"✗ 无效的标签页: {tab_name}")
except Exception as e:
print(f"✗ 标签页切换失败: {e}")
self.editor_stats["editor_errors"] += 1
def select_queue(self, queue_name: str):
"""
选择队列
Args:
queue_name: 队列名称
"""
try:
self.editor_state["selected_queue"] = queue_name
print(f"✓ 选择队列: {queue_name}")
except Exception as e:
print(f"✗ 队列选择失败: {e}")
self.editor_stats["editor_errors"] += 1
def select_algorithm(self, algorithm_name: str):
"""
选择算法
Args:
algorithm_name: 算法名称
"""
try:
self.editor_state["selected_algorithm"] = algorithm_name
print(f"✓ 选择算法: {algorithm_name}")
except Exception as e:
print(f"✗ 算法选择失败: {e}")
self.editor_stats["editor_errors"] += 1
def update_config(self, section: str, key: str, value: Any) -> bool:
"""
更新配置
Args:
section: 配置节
key: 配置键
value: 配置值
Returns:
是否更新成功
"""
try:
# 通过配置管理器更新配置
if self.plugin.config_manager:
result = self.plugin.config_manager.set_config(section, key, value)
if result:
self.editor_stats["updates"] += 1
# 触发配置更改回调
self._trigger_editor_callback("config_changed", {
"section": section,
"key": key,
"value": value,
"timestamp": time.time()
})
print(f"✓ 配置已更新: {section}.{key} = {value}")
return True
else:
print(f"✗ 配置更新失败: {section}.{key}")
return False
else:
print("✗ 配置管理器不可用")
return False
except Exception as e:
print(f"✗ 配置更新失败: {e}")
self.editor_stats["editor_errors"] += 1
return False
def get_editor_stats(self) -> Dict[str, Any]:
"""
获取编辑器统计信息
Returns:
编辑器统计字典
"""
return {
"state": self.editor_state.copy(),
"stats": self.editor_stats.copy(),
"config": self.editor_config.copy(),
"ui_components": len(self.ui_components["tabs"])
}
def reset_stats(self):
"""重置编辑器统计信息"""
try:
self.editor_stats = {
"updates": 0,
"ui_refreshes": 0,
"data_points": 0,
"editor_errors": 0
}
print("✓ 编辑器统计信息已重置")
except Exception as e:
print(f"✗ 编辑器统计信息重置失败: {e}")
def set_editor_config(self, config: Dict[str, Any]) -> bool:
"""
设置编辑器配置
Args:
config: 编辑器配置字典
Returns:
是否设置成功
"""
try:
self.editor_config.update(config)
print(f"✓ 编辑器配置已更新: {self.editor_config}")
return True
except Exception as e:
print(f"✗ 编辑器配置设置失败: {e}")
return False
def get_editor_config(self) -> Dict[str, Any]:
"""
获取编辑器配置
Returns:
编辑器配置字典
"""
return self.editor_config.copy()
def get_realtime_data(self) -> Dict[str, Any]:
"""
获取实时数据
Returns:
实时数据字典
"""
return self.realtime_data.copy()
def export_data(self, data_type: str, file_path: str) -> bool:
"""
导出数据
Args:
data_type: 数据类型
file_path: 导出文件路径
Returns:
是否导出成功
"""
try:
import json
import os
# 创建导出目录
export_dir = os.path.dirname(file_path)
if not os.path.exists(export_dir):
os.makedirs(export_dir)
# 获取要导出的数据
export_data = None
if data_type == "performance":
export_data = self.realtime_data["performance_metrics"]
elif data_type == "queues":
export_data = self.realtime_data["queue_data"]
elif data_type == "matches":
export_data = self.realtime_data["match_data"]
elif data_type == "algorithms":
export_data = self.realtime_data["algorithm_stats"]
elif data_type == "system":
export_data = self.realtime_data["system_stats"]
elif data_type == "all":
export_data = self.realtime_data
else:
print(f"✗ 不支持的数据类型: {data_type}")
return False
# 导出数据
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(export_data, f, indent=2, ensure_ascii=False, default=str)
print(f"✓ 数据已导出到: {file_path}")
return True
except Exception as e:
print(f"✗ 数据导出失败: {e}")
self.editor_stats["editor_errors"] += 1
return False
def _trigger_editor_callback(self, callback_type: str, data: Dict[str, Any]):
"""
触发编辑器回调
Args:
callback_type: 回调类型
data: 回调数据
"""
try:
if callback_type in self.editor_callbacks:
for callback in self.editor_callbacks[callback_type]:
try:
callback(data)
except Exception as e:
print(f"✗ 编辑器回调执行失败: {callback_type} - {e}")
except Exception as e:
print(f"✗ 编辑器回调触发失败: {e}")
def register_editor_callback(self, callback_type: str, callback: callable):
"""
注册编辑器回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.editor_callbacks:
self.editor_callbacks[callback_type].append(callback)
print(f"✓ 编辑器回调已注册: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 编辑器回调注册失败: {e}")
def unregister_editor_callback(self, callback_type: str, callback: callable):
"""
注销编辑器回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.editor_callbacks:
if callback in self.editor_callbacks[callback_type]:
self.editor_callbacks[callback_type].remove(callback)
print(f"✓ 编辑器回调已注销: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 编辑器回调注销失败: {e}")

View File

@ -0,0 +1,699 @@
"""
事件处理器模块
处理匹配相关的事件
"""
import time
import threading
import queue
from typing import Dict, Any, List, Optional, Callable
class EventHandler:
"""
事件处理器
处理匹配相关的事件
"""
def __init__(self, plugin):
"""
初始化事件处理器
Args:
plugin: 匹配系统插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 事件配置
self.event_config = {
"enable_event_system": True,
"max_event_queue_size": 10000,
"enable_event_filtering": True,
"event_processing_interval": 0.01, # 10ms
"enable_async_processing": True,
"max_concurrent_events": 100,
"enable_event_prioritization": True
}
# 事件状态
self.event_state = {
"is_processing": False,
"pending_events": 0,
"processed_events": 0,
"dropped_events": 0,
"last_event_time": 0.0
}
# 事件队列
self.event_queue = queue.Queue(maxsize=self.event_config["max_event_queue_size"])
# 事件处理器存储
self.event_handlers = {}
# 事件统计
self.event_stats = {
"events_received": 0,
"events_processed": 0,
"events_dropped": 0,
"handler_errors": 0,
"async_events": 0
}
# 事件过滤器
self.event_filters = {}
# 回调函数
self.event_callbacks = {
"event_received": [],
"event_processed": [],
"event_dropped": [],
"event_error": []
}
# 事件处理线程
self.event_thread = None
self.event_thread_running = False
# 时间戳记录
self.last_event_process = 0.0
self.last_stats_reset = 0.0
print("✓ 事件处理器已创建")
def initialize(self) -> bool:
"""
初始化事件处理器
Returns:
是否初始化成功
"""
try:
print("正在初始化事件处理器...")
# 注册默认事件处理器
self._register_default_handlers()
# 启动事件处理线程
self._start_event_thread()
self.initialized = True
print("✓ 事件处理器初始化完成")
return True
except Exception as e:
print(f"✗ 事件处理器初始化失败: {e}")
self.event_stats["handler_errors"] += 1
import traceback
traceback.print_exc()
return False
def _register_default_handlers(self):
"""注册默认事件处理器"""
try:
# 注册系统事件处理器
self.register_event_handler("player_queued", self._handle_player_queued)
self.register_event_handler("player_dequeued", self._handle_player_dequeued)
self.register_event_handler("match_found", self._handle_match_found)
self.register_event_handler("match_completed", self._handle_match_completed)
self.register_event_handler("match_cancelled", self._handle_match_cancelled)
self.register_event_handler("queue_timeout", self._handle_queue_timeout)
print("✓ 默认事件处理器已注册")
except Exception as e:
print(f"✗ 默认事件处理器注册失败: {e}")
self.event_stats["handler_errors"] += 1
def _start_event_thread(self):
"""启动事件处理线程"""
try:
self.event_thread_running = True
self.event_thread = threading.Thread(target=self._event_loop, daemon=True)
self.event_thread.start()
print("✓ 事件处理线程已启动")
except Exception as e:
print(f"✗ 事件处理线程启动失败: {e}")
self.event_stats["handler_errors"] += 1
def _event_loop(self):
"""事件处理循环"""
try:
while self.event_thread_running:
try:
if self.enabled and self.event_config["enable_event_system"]:
# 处理事件队列
self._process_event_queue()
# 短暂休眠
time.sleep(self.event_config["event_processing_interval"])
except Exception as e:
print(f"✗ 事件处理循环错误: {e}")
self.event_stats["handler_errors"] += 1
time.sleep(1.0) # 出错时延长休眠
except Exception as e:
print(f"✗ 事件处理线程失败: {e}")
self.event_stats["handler_errors"] += 1
def enable(self) -> bool:
"""
启用事件处理器
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ 事件处理器未初始化")
return False
self.enabled = True
print("✓ 事件处理器已启用")
return True
except Exception as e:
print(f"✗ 事件处理器启用失败: {e}")
self.event_stats["handler_errors"] += 1
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用事件处理器"""
try:
self.enabled = False
# 停止事件处理线程
if self.event_thread_running:
self.event_thread_running = False
if self.event_thread and self.event_thread.is_alive():
self.event_thread.join(timeout=5.0)
print("✓ 事件处理器已禁用")
except Exception as e:
print(f"✗ 事件处理器禁用失败: {e}")
self.event_stats["handler_errors"] += 1
import traceback
traceback.print_exc()
def finalize(self):
"""清理事件处理器资源"""
try:
# 禁用事件处理器
if self.enabled:
self.disable()
# 清理回调和处理器
self.event_callbacks.clear()
self.event_handlers.clear()
self.event_filters.clear()
self.initialized = False
print("✓ 事件处理器资源已清理")
except Exception as e:
print(f"✗ 事件处理器资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新事件处理器状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
current_time = time.time()
self.event_state["last_event_time"] = current_time
except Exception as e:
print(f"✗ 事件处理器更新失败: {e}")
self.event_stats["handler_errors"] += 1
import traceback
traceback.print_exc()
def _process_event_queue(self):
"""处理事件队列"""
try:
processed_count = 0
max_process_per_loop = 100 # 每次循环最多处理100个事件
while not self.event_queue.empty() and processed_count < max_process_per_loop:
try:
# 从队列获取事件
event_data = self.event_queue.get_nowait()
# 处理事件
self._handle_event_internal(event_data)
processed_count += 1
self.event_stats["events_processed"] += 1
except queue.Empty:
break
except Exception as e:
print(f"✗ 事件队列处理失败: {e}")
self.event_stats["handler_errors"] += 1
self.event_state["pending_events"] = self.event_queue.qsize()
except Exception as e:
print(f"✗ 事件队列处理失败: {e}")
self.event_stats["handler_errors"] += 1
def _handle_event_internal(self, event_data: Dict[str, Any]):
"""
内部事件处理
Args:
event_data: 事件数据
"""
try:
event_type = event_data.get("type")
event_payload = event_data.get("payload", {})
event_priority = event_data.get("priority", 0)
event_timestamp = event_data.get("timestamp", time.time())
# 应用事件过滤器
if self.event_config["enable_event_filtering"]:
if not self._apply_event_filters(event_type, event_payload):
# 事件被过滤掉
return
# 查找事件处理器
if event_type in self.event_handlers:
handlers = self.event_handlers[event_type]
# 按优先级排序处理器
if self.event_config["enable_event_prioritization"]:
handlers = sorted(handlers, key=lambda x: x.get("priority", 0), reverse=True)
# 调用所有处理器
for handler_info in handlers:
try:
handler_func = handler_info["function"]
handler_result = handler_func(event_payload)
# 检查是否需要停止传播
if handler_result is False:
break
except Exception as e:
print(f"✗ 事件处理器执行失败: {event_type} - {e}")
self.event_stats["handler_errors"] += 1
# 触发事件处理回调
self._trigger_event_callback("event_processed", {
"event_type": event_type,
"event_payload": event_payload,
"processing_time": time.time() - event_timestamp,
"timestamp": time.time()
})
except Exception as e:
print(f"✗ 内部事件处理失败: {e}")
self.event_stats["handler_errors"] += 1
def _apply_event_filters(self, event_type: str, event_payload: Dict[str, Any]) -> bool:
"""
应用事件过滤器
Args:
event_type: 事件类型
event_payload: 事件载荷
Returns:
是否通过过滤器
"""
try:
if event_type in self.event_filters:
filters = self.event_filters[event_type]
for filter_func in filters:
if not filter_func(event_payload):
return False
return True
except Exception as e:
print(f"✗ 事件过滤器应用失败: {e}")
self.event_stats["handler_errors"] += 1
return True
def emit_event(self, event_type: str, event_payload: Dict[str, Any] = None,
priority: int = 0, async_process: bool = None) -> bool:
"""
发出事件
Args:
event_type: 事件类型
event_payload: 事件载荷
priority: 事件优先级
async_process: 是否异步处理
Returns:
是否发出成功
"""
try:
if not self.enabled or not self.event_config["enable_event_system"]:
return False
# 使用默认异步处理设置或指定设置
if async_process is None:
async_process = self.event_config["enable_async_processing"]
event_data = {
"type": event_type,
"payload": event_payload or {},
"priority": priority,
"timestamp": time.time(),
"async": async_process
}
# 触发事件接收回调
self._trigger_event_callback("event_received", {
"event_type": event_type,
"event_payload": event_payload,
"priority": priority,
"timestamp": time.time()
})
# 更新统计
self.event_stats["events_received"] += 1
if async_process:
# 异步处理:添加到队列
try:
self.event_queue.put_nowait(event_data)
self.event_stats["async_events"] += 1
return True
except queue.Full:
# 队列已满,丢弃事件
self.event_stats["events_dropped"] += 1
self.event_state["dropped_events"] += 1
# 触发事件丢弃回调
self._trigger_event_callback("event_dropped", {
"event_type": event_type,
"event_payload": event_payload,
"reason": "queue_full",
"timestamp": time.time()
})
return False
else:
# 同步处理:立即处理
self._handle_event_internal(event_data)
return True
except Exception as e:
print(f"✗ 事件发出失败: {e}")
self.event_stats["handler_errors"] += 1
return False
def register_event_handler(self, event_type: str, handler: Callable, priority: int = 0):
"""
注册事件处理器
Args:
event_type: 事件类型
handler: 处理器函数
priority: 处理器优先级
"""
try:
if event_type not in self.event_handlers:
self.event_handlers[event_type] = []
handler_info = {
"function": handler,
"priority": priority
}
self.event_handlers[event_type].append(handler_info)
print(f"✓ 事件处理器已注册: {event_type} (优先级: {priority})")
except Exception as e:
print(f"✗ 事件处理器注册失败: {e}")
self.event_stats["handler_errors"] += 1
def unregister_event_handler(self, event_type: str, handler: Callable):
"""
注销事件处理器
Args:
event_type: 事件类型
handler: 处理器函数
"""
try:
if event_type in self.event_handlers:
handlers = self.event_handlers[event_type]
for i, handler_info in enumerate(handlers):
if handler_info["function"] == handler:
del handlers[i]
print(f"✓ 事件处理器已注销: {event_type}")
return
print(f"✗ 事件处理器不存在: {event_type}")
except Exception as e:
print(f"✗ 事件处理器注销失败: {e}")
self.event_stats["handler_errors"] += 1
def register_event_filter(self, event_type: str, filter_func: Callable):
"""
注册事件过滤器
Args:
event_type: 事件类型
filter_func: 过滤器函数
"""
try:
if event_type not in self.event_filters:
self.event_filters[event_type] = []
self.event_filters[event_type].append(filter_func)
print(f"✓ 事件过滤器已注册: {event_type}")
except Exception as e:
print(f"✗ 事件过滤器注册失败: {e}")
self.event_stats["handler_errors"] += 1
def unregister_event_filter(self, event_type: str, filter_func: Callable):
"""
注销事件过滤器
Args:
event_type: 事件类型
filter_func: 过滤器函数
"""
try:
if event_type in self.event_filters:
filters = self.event_filters[event_type]
if filter_func in filters:
filters.remove(filter_func)
print(f"✓ 事件过滤器已注销: {event_type}")
return
print(f"✗ 事件过滤器不存在: {event_type}")
except Exception as e:
print(f"✗ 事件过滤器注销失败: {e}")
self.event_stats["handler_errors"] += 1
# 默认事件处理器
def _handle_player_queued(self, payload: Dict[str, Any]):
"""处理玩家排队事件"""
try:
player_ids = payload.get("player_ids", [])
queue_name = payload.get("queue_name", "default")
print(f".players queued: {len(player_ids)} players in queue '{queue_name}'")
# 可以在这里添加额外的处理逻辑
# 例如:记录排队时间、更新统计等
except Exception as e:
print(f"✗ 玩家排队事件处理失败: {e}")
self.event_stats["handler_errors"] += 1
def _handle_player_dequeued(self, payload: Dict[str, Any]):
"""处理玩家离队事件"""
try:
player_ids = payload.get("player_ids", [])
match_id = payload.get("match_id")
print(f".players dequeued: {len(player_ids)} players")
# 可以在这里添加额外的处理逻辑
# 例如:更新统计、清理资源等
except Exception as e:
print(f"✗ 玩家离队事件处理失败: {e}")
self.event_stats["handler_errors"] += 1
def _handle_match_found(self, payload: Dict[str, Any]):
"""处理匹配找到事件"""
try:
match_id = payload.get("match_id")
room_id = payload.get("room_id")
player_ids = payload.get("player_ids", [])
queue_name = payload.get("queue_name", "default")
print(f"🎉 Match found: {match_id} with {len(player_ids)} players in queue '{queue_name}' -> Room: {room_id}")
# 记录匹配队列时间
if self.plugin.monitor:
queue_time = time.time() - payload.get("timestamp", time.time())
self.plugin.monitor.record_match_queue_time(queue_time)
except Exception as e:
print(f"✗ 匹配找到事件处理失败: {e}")
self.event_stats["handler_errors"] += 1
def _handle_match_completed(self, payload: Dict[str, Any]):
"""处理匹配完成事件"""
try:
match_id = payload.get("match_id")
room_id = payload.get("room_id")
print(f"✅ Match completed: {match_id} -> Room: {room_id}")
except Exception as e:
print(f"✗ 匹配完成事件处理失败: {e}")
self.event_stats["handler_errors"] += 1
def _handle_match_cancelled(self, payload: Dict[str, Any]):
"""处理匹配取消事件"""
try:
match_id = payload.get("match_id")
print(f"❌ Match cancelled: {match_id}")
except Exception as e:
print(f"✗ 匹配取消事件处理失败: {e}")
self.event_stats["handler_errors"] += 1
def _handle_queue_timeout(self, payload: Dict[str, Any]):
"""处理队列超时事件"""
try:
player_id = payload.get("player_id")
print(f"⏰ Queue timeout for player: {player_id}")
except Exception as e:
print(f"✗ 队列超时事件处理失败: {e}")
self.event_stats["handler_errors"] += 1
def get_event_stats(self) -> Dict[str, Any]:
"""
获取事件统计信息
Returns:
事件统计字典
"""
return {
"state": self.event_state.copy(),
"stats": self.event_stats.copy(),
"config": self.event_config.copy(),
"pending_events": self.event_queue.qsize()
}
def reset_stats(self):
"""重置事件统计信息"""
try:
self.event_stats = {
"events_received": 0,
"events_processed": 0,
"events_dropped": 0,
"handler_errors": 0,
"async_events": 0
}
print("✓ 事件统计信息已重置")
except Exception as e:
print(f"✗ 事件统计信息重置失败: {e}")
def set_event_config(self, config: Dict[str, Any]) -> bool:
"""
设置事件配置
Args:
config: 事件配置字典
Returns:
是否设置成功
"""
try:
self.event_config.update(config)
print(f"✓ 事件配置已更新: {self.event_config}")
return True
except Exception as e:
print(f"✗ 事件配置设置失败: {e}")
return False
def get_event_config(self) -> Dict[str, Any]:
"""
获取事件配置
Returns:
事件配置字典
"""
return self.event_config.copy()
def _trigger_event_callback(self, callback_type: str, data: Dict[str, Any]):
"""
触发事件回调
Args:
callback_type: 回调类型
data: 回调数据
"""
try:
if callback_type in self.event_callbacks:
for callback in self.event_callbacks[callback_type]:
try:
callback(data)
except Exception as e:
print(f"✗ 事件回调执行失败: {callback_type} - {e}")
except Exception as e:
print(f"✗ 事件回调触发失败: {e}")
def register_event_callback(self, callback_type: str, callback: callable):
"""
注册事件回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.event_callbacks:
self.event_callbacks[callback_type].append(callback)
print(f"✓ 事件回调已注册: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 事件回调注册失败: {e}")
def unregister_event_callback(self, callback_type: str, callback: callable):
"""
注销事件回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.event_callbacks:
if callback in self.event_callbacks[callback_type]:
self.event_callbacks[callback_type].remove(callback)
print(f"✓ 事件回调已注销: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 事件回调注销失败: {e}")

View File

@ -0,0 +1,600 @@
"""
匹配监控系统模块
监控匹配过程和性能
"""
import time
from typing import Dict, Any, List, Optional
from collections import deque
class MatchMonitor:
"""
匹配监控器
监控匹配过程和性能
"""
def __init__(self, plugin):
"""
初始化匹配监控器
Args:
plugin: 匹配系统插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 监控配置
self.monitor_config = {
"enable_monitoring": True,
"monitoring_interval": 5.0,
"log_level": "INFO",
"enable_performance_monitoring": True,
"enable_alerts": True,
"alert_thresholds": {
"match_queue_time": 60.0,
"match_failure_rate": 10.0,
"system_latency": 100.0
},
"enable_metrics_collection": True,
"metrics_retention_period": 3600 # 1小时
}
# 性能指标存储
self.performance_metrics = {
"match_queue_times": deque(maxlen=1000),
"match_success_rates": deque(maxlen=1000),
"system_latencies": deque(maxlen=1000),
"player_wait_times": deque(maxlen=1000),
"algorithm_performance": deque(maxlen=1000)
}
# 监控状态
self.monitor_state = {
"last_monitoring_update": 0.0,
"last_performance_check": 0.0,
"total_monitored_matches": 0,
"active_alerts": 0
}
# 警报系统
self.active_alerts = {}
self.alert_history = deque(maxlen=1000)
# 监控统计
self.monitor_stats = {
"metrics_collected": 0,
"alerts_generated": 0,
"alerts_resolved": 0,
"performance_checks": 0,
"monitor_errors": 0
}
# 回调函数
self.monitor_callbacks = {
"metric_collected": [],
"alert_triggered": [],
"alert_resolved": [],
"performance_degraded": []
}
# 时间戳记录
self.last_metric_collection = 0.0
self.last_alert_check = 0.0
print("✓ 匹配监控器已创建")
def initialize(self) -> bool:
"""
初始化匹配监控器
Returns:
是否初始化成功
"""
try:
print("正在初始化匹配监控器...")
self.initialized = True
print("✓ 匹配监控器初始化完成")
return True
except Exception as e:
print(f"✗ 匹配监控器初始化失败: {e}")
self.monitor_stats["monitor_errors"] += 1
import traceback
traceback.print_exc()
return False
def enable(self) -> bool:
"""
启用匹配监控器
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ 匹配监控器未初始化")
return False
self.enabled = True
print("✓ 匹配监控器已启用")
return True
except Exception as e:
print(f"✗ 匹配监控器启用失败: {e}")
self.monitor_stats["monitor_errors"] += 1
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用匹配监控器"""
try:
self.enabled = False
print("✓ 匹配监控器已禁用")
except Exception as e:
print(f"✗ 匹配监控器禁用失败: {e}")
self.monitor_stats["monitor_errors"] += 1
import traceback
traceback.print_exc()
def finalize(self):
"""清理匹配监控器资源"""
try:
# 禁用匹配监控器
if self.enabled:
self.disable()
# 清理回调
self.monitor_callbacks.clear()
self.initialized = False
print("✓ 匹配监控器资源已清理")
except Exception as e:
print(f"✗ 匹配监控器资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新匹配监控器状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
current_time = time.time()
self.monitor_state["last_monitoring_update"] = current_time
# 定期收集性能指标
if current_time - self.last_metric_collection >= self.monitor_config["monitoring_interval"]:
self._collect_performance_metrics()
self.last_metric_collection = current_time
# 定期检查警报
if current_time - self.last_alert_check >= self.monitor_config["monitoring_interval"]:
self._check_alerts()
self.last_alert_check = current_time
except Exception as e:
print(f"✗ 匹配监控器更新失败: {e}")
self.monitor_stats["monitor_errors"] += 1
import traceback
traceback.print_exc()
def _collect_performance_metrics(self):
"""收集性能指标"""
try:
current_time = time.time()
metrics = {}
# 收集匹配管理器指标
if self.plugin.match_manager:
match_stats = self.plugin.match_manager.get_match_stats()
match_state = match_stats.get("state", {})
metrics["active_matches"] = match_state.get("active_matches", 0)
metrics["successful_matches"] = match_state.get("successful_matches", 0)
metrics["failed_matches"] = match_state.get("failed_matches", 0)
# 计算成功率
total_matches = metrics["successful_matches"] + metrics["failed_matches"]
if total_matches > 0:
success_rate = (metrics["successful_matches"] / total_matches) * 100
metrics["match_success_rate"] = success_rate
self.performance_metrics["match_success_rates"].append((current_time, success_rate))
# 收集队列管理器指标
if self.plugin.queue_manager:
queue_stats = self.plugin.queue_manager.get_queue_stats()
queue_state = queue_stats.get("state", {})
metrics["total_players"] = queue_state.get("total_players", 0)
metrics["players_matched"] = queue_state.get("players_matched", 0)
metrics["players_timed_out"] = queue_state.get("players_timed_out", 0)
# 计算超时率
total_players = metrics["players_matched"] + metrics["players_timed_out"]
if total_players > 0:
timeout_rate = (metrics["players_timed_out"] / total_players) * 100
metrics["queue_timeout_rate"] = timeout_rate
# 收集算法管理器指标
if self.plugin.algorithm_manager:
algorithm_stats = self.plugin.algorithm_manager.get_algorithm_stats()
algorithm_state = algorithm_stats.get("state", {})
metrics["total_algorithms"] = algorithm_state.get("total_matches", 0)
metrics["successful_algorithms"] = algorithm_state.get("successful_matches", 0)
metrics["average_match_quality"] = algorithm_state.get("average_match_quality", 0)
self.performance_metrics["algorithm_performance"].append(
(current_time, metrics["average_match_quality"])
)
# 收集房间分配器指标
if self.plugin.room_allocator:
room_stats = self.plugin.room_allocator.get_room_stats()
room_state = room_stats.get("state", {})
metrics["active_rooms"] = room_state.get("active_rooms", 0)
metrics["total_rooms"] = room_state.get("total_rooms", 0)
# 更新统计
self.monitor_stats["metrics_collected"] += 1
self.monitor_state["total_monitored_matches"] += 1
# 触发指标收集回调
self._trigger_monitor_callback("metric_collected", {
"metrics": metrics,
"timestamp": current_time
})
except Exception as e:
print(f"✗ 性能指标收集失败: {e}")
self.monitor_stats["monitor_errors"] += 1
def _check_alerts(self):
"""检查警报条件"""
try:
if not self.monitor_config["enable_alerts"]:
return
current_time = time.time()
thresholds = self.monitor_config["alert_thresholds"]
# 检查匹配队列时间
if self.performance_metrics["match_queue_times"]:
latest_queue_time = self.performance_metrics["match_queue_times"][-1][1]
if latest_queue_time > thresholds["match_queue_time"]:
self._trigger_alert("high_queue_time", f"匹配队列时间过长: {latest_queue_time:.2f}", current_time)
# 检查匹配失败率
if self.performance_metrics["match_success_rates"]:
latest_success_rate = self.performance_metrics["match_success_rates"][-1][1]
failure_rate = 100 - latest_success_rate
if failure_rate > thresholds["match_failure_rate"]:
self._trigger_alert("high_failure_rate", f"匹配失败率过高: {failure_rate:.2f}%", current_time)
# 检查系统延迟
if self.performance_metrics["system_latencies"]:
latest_latency = self.performance_metrics["system_latencies"][-1][1]
if latest_latency > thresholds["system_latency"]:
self._trigger_alert("high_latency", f"系统延迟过高: {latest_latency:.2f}ms", current_time)
except Exception as e:
print(f"✗ 警报检查失败: {e}")
self.monitor_stats["monitor_errors"] += 1
def _trigger_alert(self, alert_type: str, message: str, timestamp: float = None):
"""
触发警报
Args:
alert_type: 警报类型
message: 警报消息
timestamp: 时间戳
"""
try:
if timestamp is None:
timestamp = time.time()
alert_id = f"{alert_type}_{int(timestamp)}"
# 检查是否已存在相同类型的活动警报
if alert_type in self.active_alerts:
# 更新现有警报
self.active_alerts[alert_type]["count"] += 1
self.active_alerts[alert_type]["last_triggered"] = timestamp
else:
# 创建新警报
self.active_alerts[alert_type] = {
"id": alert_id,
"type": alert_type,
"message": message,
"first_triggered": timestamp,
"last_triggered": timestamp,
"count": 1,
"resolved": False
}
self.monitor_state["active_alerts"] += 1
self.monitor_stats["alerts_generated"] += 1
# 添加到警报历史
self.alert_history.append({
"id": alert_id,
"type": alert_type,
"message": message,
"timestamp": timestamp,
"resolved": False
})
# 触发警报回调
self._trigger_monitor_callback("alert_triggered", {
"alert_id": alert_id,
"alert_type": alert_type,
"message": message,
"timestamp": timestamp
})
print(f"⚠️ 警报触发 [{alert_type}]: {message}")
except Exception as e:
print(f"✗ 警报触发失败: {e}")
self.monitor_stats["monitor_errors"] += 1
def resolve_alert(self, alert_type: str):
"""
解决警报
Args:
alert_type: 警报类型
"""
try:
if alert_type in self.active_alerts:
alert_data = self.active_alerts[alert_type]
alert_data["resolved"] = True
alert_data["resolved_time"] = time.time()
self.monitor_state["active_alerts"] -= 1
self.monitor_stats["alerts_resolved"] += 1
# 触发警报解决回调
self._trigger_monitor_callback("alert_resolved", {
"alert_type": alert_type,
"alert_data": alert_data
})
# 从活动警报中移除
del self.active_alerts[alert_type]
print(f"✅ 警报已解决: {alert_type}")
except Exception as e:
print(f"✗ 警报解决失败: {e}")
self.monitor_stats["monitor_errors"] += 1
def record_match_queue_time(self, queue_time: float):
"""
记录匹配队列时间
Args:
queue_time: 队列时间
"""
try:
current_time = time.time()
self.performance_metrics["match_queue_times"].append((current_time, queue_time))
except Exception as e:
print(f"✗ 匹配队列时间记录失败: {e}")
self.monitor_stats["monitor_errors"] += 1
def record_player_wait_time(self, wait_time: float):
"""
记录玩家等待时间
Args:
wait_time: 等待时间
"""
try:
current_time = time.time()
self.performance_metrics["player_wait_times"].append((current_time, wait_time))
except Exception as e:
print(f"✗ 玩家等待时间记录失败: {e}")
self.monitor_stats["monitor_errors"] += 1
def record_system_latency(self, latency: float):
"""
记录系统延迟
Args:
latency: 延迟毫秒
"""
try:
current_time = time.time()
self.performance_metrics["system_latencies"].append((current_time, latency))
except Exception as e:
print(f"✗ 系统延迟记录失败: {e}")
self.monitor_stats["monitor_errors"] += 1
def get_performance_metrics(self, metric_name: str = None, limit: int = 100) -> Any:
"""
获取性能指标
Args:
metric_name: 指标名称可选
limit: 限制返回的数量
Returns:
性能指标数据
"""
try:
if metric_name:
if metric_name in self.performance_metrics:
metrics = list(self.performance_metrics[metric_name])
return metrics[-limit:] if len(metrics) > limit else metrics
else:
return []
else:
# 返回所有指标
result = {}
for name, metrics in self.performance_metrics.items():
metric_list = list(metrics)
result[name] = metric_list[-limit:] if len(metric_list) > limit else metric_list
return result
except Exception as e:
print(f"✗ 获取性能指标失败: {e}")
self.monitor_stats["monitor_errors"] += 1
return {}
def get_active_alerts(self) -> Dict[str, Any]:
"""
获取活动警报
Returns:
活动警报字典
"""
try:
return self.active_alerts.copy()
except Exception as e:
print(f"✗ 获取活动警报失败: {e}")
self.monitor_stats["monitor_errors"] += 1
return {}
def get_alert_history(self, limit: int = 100) -> List[Dict[str, Any]]:
"""
获取警报历史
Args:
limit: 限制返回的数量
Returns:
警报历史列表
"""
try:
history = list(self.alert_history)
return history[-limit:] if len(history) > limit else history
except Exception as e:
print(f"✗ 获取警报历史失败: {e}")
self.monitor_stats["monitor_errors"] += 1
return []
def get_monitor_stats(self) -> Dict[str, Any]:
"""
获取监控统计信息
Returns:
监控统计字典
"""
return {
"state": self.monitor_state.copy(),
"stats": self.monitor_stats.copy(),
"config": self.monitor_config.copy(),
"active_alerts_count": len(self.active_alerts),
"alert_history_count": len(self.alert_history)
}
def reset_stats(self):
"""重置监控统计信息"""
try:
self.monitor_stats = {
"metrics_collected": 0,
"alerts_generated": 0,
"alerts_resolved": 0,
"performance_checks": 0,
"monitor_errors": 0
}
self.monitor_state["total_monitored_matches"] = 0
self.monitor_state["active_alerts"] = 0
print("✓ 监控统计信息已重置")
except Exception as e:
print(f"✗ 监控统计信息重置失败: {e}")
def set_monitor_config(self, config: Dict[str, Any]) -> bool:
"""
设置监控配置
Args:
config: 监控配置字典
Returns:
是否设置成功
"""
try:
self.monitor_config.update(config)
print(f"✓ 监控配置已更新: {self.monitor_config}")
return True
except Exception as e:
print(f"✗ 监控配置设置失败: {e}")
return False
def get_monitor_config(self) -> Dict[str, Any]:
"""
获取监控配置
Returns:
监控配置字典
"""
return self.monitor_config.copy()
def _trigger_monitor_callback(self, callback_type: str, data: Dict[str, Any]):
"""
触发监控回调
Args:
callback_type: 回调类型
data: 回调数据
"""
try:
if callback_type in self.monitor_callbacks:
for callback in self.monitor_callbacks[callback_type]:
try:
callback(data)
except Exception as e:
print(f"✗ 监控回调执行失败: {callback_type} - {e}")
except Exception as e:
print(f"✗ 监控回调触发失败: {e}")
def register_monitor_callback(self, callback_type: str, callback: callable):
"""
注册监控回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.monitor_callbacks:
self.monitor_callbacks[callback_type].append(callback)
print(f"✓ 监控回调已注册: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 监控回调注册失败: {e}")
def unregister_monitor_callback(self, callback_type: str, callback: callable):
"""
注销监控回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.monitor_callbacks:
if callback in self.monitor_callbacks[callback_type]:
self.monitor_callbacks[callback_type].remove(callback)
print(f"✓ 监控回调已注销: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 监控回调注销失败: {e}")

View File

@ -0,0 +1,225 @@
"""
匹配系统插件主文件
"""
class MatchmakingSystemPlugin:
"""
匹配系统插件
为EG引擎提供玩家匹配功能
"""
def __init__(self, engine):
"""
初始化匹配系统插件
Args:
engine: EG引擎实例
"""
self.engine = engine
self.name = "MatchmakingSystem"
self.version = "1.0.0"
# 插件组件
self.match_manager = None
self.queue_manager = None
self.algorithm_manager = None
self.room_allocator = None
self.rule_manager = None
self.monitor = None
self.event_handler = None
self.config_manager = None
self.editor = None
self.stats_manager = None
print("✓ 匹配系统插件已创建")
def initialize(self) -> bool:
"""
初始化插件
Returns:
是否初始化成功
"""
try:
print("正在初始化匹配系统插件...")
# 导入模块
from .core.match_manager import MatchManager
from .queue.queue_manager import QueueManager
from .algorithms.algorithm_manager import AlgorithmManager
from .rooms.room_allocator import RoomAllocator
from .rules.rule_manager import RuleManager
from .monitoring.match_monitor import MatchMonitor
from .events.event_handler import EventHandler
from .config.match_config import MatchConfig
from .editor.match_editor import MatchEditor
from .stats.stats_manager import StatsManager
# 创建组件
self.config_manager = MatchConfig(self)
self.event_handler = EventHandler(self)
self.rule_manager = RuleManager(self)
self.algorithm_manager = AlgorithmManager(self)
self.queue_manager = QueueManager(self)
self.room_allocator = RoomAllocator(self)
self.match_manager = MatchManager(self)
self.monitor = MatchMonitor(self)
self.editor = MatchEditor(self)
self.stats_manager = StatsManager(self)
# 初始化组件
components = [
self.config_manager,
self.event_handler,
self.rule_manager,
self.algorithm_manager,
self.queue_manager,
self.room_allocator,
self.match_manager,
self.monitor,
self.editor,
self.stats_manager
]
for component in components:
if hasattr(component, 'initialize') and not component.initialize():
print(f"✗ 组件初始化失败: {component.__class__.__name__}")
return False
print("✓ 匹配系统插件初始化完成")
return True
except Exception as e:
print(f"✗ 匹配系统插件初始化失败: {e}")
import traceback
traceback.print_exc()
return False
def enable(self) -> bool:
"""
启用插件
Returns:
是否启用成功
"""
try:
print("正在启用匹配系统插件...")
# 启用组件
components = [
self.config_manager,
self.event_handler,
self.rule_manager,
self.algorithm_manager,
self.queue_manager,
self.room_allocator,
self.match_manager,
self.monitor,
self.editor,
self.stats_manager
]
for component in components:
if hasattr(component, 'enable') and not component.enable():
print(f"✗ 组件启用失败: {component.__class__.__name__}")
return False
print("✓ 匹配系统插件已启用")
return True
except Exception as e:
print(f"✗ 匹配系统插件启用失败: {e}")
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用插件"""
try:
print("正在禁用匹配系统插件...")
# 禁用组件
components = [
self.stats_manager,
self.editor,
self.monitor,
self.match_manager,
self.room_allocator,
self.queue_manager,
self.algorithm_manager,
self.rule_manager,
self.event_handler,
self.config_manager
]
for component in components:
if hasattr(component, 'disable'):
component.disable()
print("✓ 匹配系统插件已禁用")
except Exception as e:
print(f"✗ 匹配系统插件禁用失败: {e}")
import traceback
traceback.print_exc()
def finalize(self):
"""清理插件资源"""
try:
print("正在清理匹配系统插件资源...")
# 清理组件
components = [
self.stats_manager,
self.editor,
self.monitor,
self.match_manager,
self.room_allocator,
self.queue_manager,
self.algorithm_manager,
self.rule_manager,
self.event_handler,
self.config_manager
]
for component in components:
if hasattr(component, 'finalize'):
component.finalize()
print("✓ 匹配系统插件资源已清理")
except Exception as e:
print(f"✗ 匹配系统插件资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新插件状态
Args:
dt: 时间增量
"""
try:
# 更新组件
components = [
self.config_manager,
self.event_handler,
self.rule_manager,
self.algorithm_manager,
self.queue_manager,
self.room_allocator,
self.match_manager,
self.monitor,
self.editor,
self.stats_manager
]
for component in components:
if hasattr(component, 'update'):
component.update(dt)
except Exception as e:
print(f"✗ 匹配系统插件更新失败: {e}")
import traceback
traceback.print_exc()

View File

@ -0,0 +1,664 @@
"""
队列管理器模块
管理等待匹配的玩家队列
"""
import time
import threading
import uuid
from typing import Dict, Any, List, Optional
from collections import deque
class QueueManager:
"""
队列管理器
管理等待匹配的玩家队列
"""
def __init__(self, plugin):
"""
初始化队列管理器
Args:
plugin: 匹配系统插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 队列配置
self.queue_config = {
"default_queue_timeout": 300.0, # 5分钟
"queue_processing_interval": 2.0,
"max_players_per_match": 100,
"min_players_per_match": 2,
"enable_queue_prioritization": True,
"enable_skill_based_queue": True,
"enable_region_based_queue": True
}
# 队列状态
self.queue_state = {
"total_players": 0,
"active_queues": 0,
"players_matched": 0,
"players_timed_out": 0
}
# 队列存储
self.queues = {} # 按游戏模式分类的队列
self.player_queues = {} # 玩家所在的队列映射
self.queue_lock = threading.RLock()
# 队列统计
self.queue_stats = {
"players_added": 0,
"players_removed": 0,
"matches_created": 0,
"queue_timeouts": 0,
"queue_errors": 0
}
# 回调函数
self.queue_callbacks = {
"player_queued": [],
"player_dequeued": [],
"match_found": [],
"queue_timeout": [],
"queue_error": []
}
# 时间戳记录
self.last_queue_process = 0.0
self.last_cleanup = 0.0
print("✓ 队列管理器已创建")
def initialize(self) -> bool:
"""
初始化队列管理器
Returns:
是否初始化成功
"""
try:
print("正在初始化队列管理器...")
self.initialized = True
print("✓ 队列管理器初始化完成")
return True
except Exception as e:
print(f"✗ 队列管理器初始化失败: {e}")
self.queue_stats["queue_errors"] += 1
import traceback
traceback.print_exc()
return False
def enable(self) -> bool:
"""
启用队列管理器
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ 队列管理器未初始化")
return False
self.enabled = True
print("✓ 队列管理器已启用")
return True
except Exception as e:
print(f"✗ 队列管理器启用失败: {e}")
self.queue_stats["queue_errors"] += 1
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用队列管理器"""
try:
self.enabled = False
# 清空所有队列
with self.queue_lock:
self.queues.clear()
self.player_queues.clear()
print("✓ 队列管理器已禁用")
except Exception as e:
print(f"✗ 队列管理器禁用失败: {e}")
self.queue_stats["queue_errors"] += 1
import traceback
traceback.print_exc()
def finalize(self):
"""清理队列管理器资源"""
try:
# 禁用队列管理器
if self.enabled:
self.disable()
# 清理回调
self.queue_callbacks.clear()
self.initialized = False
print("✓ 队列管理器资源已清理")
except Exception as e:
print(f"✗ 队列管理器资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新队列管理器状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
current_time = time.time()
# 定期处理队列
if current_time - self.last_queue_process >= self.queue_config["queue_processing_interval"]:
self.process_queues()
self.last_queue_process = current_time
# 定期清理
if current_time - self.last_cleanup >= 60.0: # 每分钟清理一次
self._cleanup_expired_players(current_time)
self.last_cleanup = current_time
except Exception as e:
print(f"✗ 队列管理器更新失败: {e}")
self.queue_stats["queue_errors"] += 1
import traceback
traceback.print_exc()
def _cleanup_expired_players(self, current_time: float):
"""清理过期玩家"""
try:
expired_players = []
with self.queue_lock:
for player_id, queue_info in self.player_queues.items():
join_time = queue_info["join_time"]
timeout = queue_info.get("timeout", self.queue_config["default_queue_timeout"])
if current_time - join_time > timeout:
expired_players.append(player_id)
# 移除过期玩家
for player_id in expired_players:
self._remove_player_from_queue(player_id, "timeout")
self.queue_stats["queue_timeouts"] += 1
# 触发队列超时回调
self._trigger_queue_callback("queue_timeout", {
"player_id": player_id,
"timestamp": current_time
})
except Exception as e:
print(f"✗ 过期玩家清理失败: {e}")
self.queue_stats["queue_errors"] += 1
def add_players_to_queue(self, player_ids: List[str], queue_params: Dict[str, Any]) -> bool:
"""
添加玩家到队列
Args:
player_ids: 玩家ID列表
queue_params: 队列参数
Returns:
是否添加成功
"""
try:
if not self.enabled:
return False
queue_name = queue_params.get("queue_name", "default")
game_mode = queue_params.get("game_mode", "default")
region = queue_params.get("region", "global")
skill_level = queue_params.get("skill_level", 0)
timeout = queue_params.get("timeout", self.queue_config["default_queue_timeout"])
with self.queue_lock:
# 创建队列(如果不存在)
if queue_name not in self.queues:
self.queues[queue_name] = {
"name": queue_name,
"game_mode": game_mode,
"region": region,
"players": deque(),
"created_time": time.time()
}
self.queue_state["active_queues"] += 1
# 添加玩家到队列
queue = self.queues[queue_name]
for player_id in player_ids:
player_info = {
"player_id": player_id,
"skill_level": skill_level,
"region": region,
"join_time": time.time(),
"timeout": timeout,
"queue_params": queue_params
}
queue["players"].append(player_info)
self.player_queues[player_id] = {
"queue_name": queue_name,
"join_time": time.time(),
"timeout": timeout
}
self.queue_state["total_players"] += len(player_ids)
self.queue_stats["players_added"] += len(player_ids)
# 触发玩家入队回调
self._trigger_queue_callback("player_queued", {
"player_ids": player_ids,
"queue_name": queue_name,
"game_mode": game_mode,
"timestamp": time.time()
})
print(f"{len(player_ids)}名玩家已添加到队列: {queue_name}")
return True
except Exception as e:
print(f"✗ 玩家添加到队列失败: {e}")
self.queue_stats["queue_errors"] += 1
return False
def remove_players_from_queue(self, match_id: str = None, player_ids: List[str] = None) -> bool:
"""
从队列移除玩家
Args:
match_id: 匹配ID可选
player_ids: 玩家ID列表可选
Returns:
是否移除成功
"""
try:
if not self.enabled:
return False
removed_count = 0
if player_ids:
# 移除指定玩家
for player_id in player_ids:
if self._remove_player_from_queue(player_id):
removed_count += 1
else:
# 移除所有玩家(这种情况较少使用)
with self.queue_lock:
player_ids = list(self.player_queues.keys())
for player_id in player_ids:
if self._remove_player_from_queue(player_id):
removed_count += 1
self.queue_stats["players_removed"] += removed_count
# 触发玩家离队回调
if player_ids:
self._trigger_queue_callback("player_dequeued", {
"player_ids": player_ids,
"match_id": match_id,
"timestamp": time.time()
})
print(f"{removed_count}名玩家已从队列移除")
return removed_count > 0
except Exception as e:
print(f"✗ 玩家从队列移除失败: {e}")
self.queue_stats["queue_errors"] += 1
return False
def _remove_player_from_queue(self, player_id: str, reason: str = "manual") -> bool:
"""
从队列移除单个玩家
Args:
player_id: 玩家ID
reason: 移除原因
Returns:
是否移除成功
"""
try:
with self.queue_lock:
if player_id not in self.player_queues:
return False
queue_name = self.player_queues[player_id]["queue_name"]
del self.player_queues[player_id]
# 从队列中移除玩家
if queue_name in self.queues:
queue = self.queues[queue_name]
players = queue["players"]
# 查找并移除玩家
player_found = False
for i, player_info in enumerate(list(players)):
if player_info["player_id"] == player_id:
del players[i]
player_found = True
break
# 如果队列为空,移除队列
if len(players) == 0:
del self.queues[queue_name]
self.queue_state["active_queues"] -= 1
if player_found:
self.queue_state["total_players"] -= 1
return True
return False
except Exception as e:
print(f"✗ 玩家从队列移除失败: {e}")
self.queue_stats["queue_errors"] += 1
return False
def process_queues(self):
"""处理队列(寻找匹配)"""
try:
if not self.enabled:
return
with self.queue_lock:
queue_names = list(self.queues.keys())
for queue_name in queue_names:
self._process_queue(queue_name)
except Exception as e:
print(f"✗ 队列处理失败: {e}")
self.queue_stats["queue_errors"] += 1
def _process_queue(self, queue_name: str):
"""
处理单个队列
Args:
queue_name: 队列名称
"""
try:
with self.queue_lock:
if queue_name not in self.queues:
return
queue = self.queues[queue_name]
players = list(queue["players"])
# 检查是否有足够的玩家进行匹配
min_players = self.queue_config["min_players_per_match"]
max_players = self.queue_config["max_players_per_match"]
if len(players) >= min_players:
# 确定匹配的玩家数量
match_player_count = min(len(players), max_players)
# 选择玩家(简化实现,实际中可能需要考虑技能匹配等因素)
selected_players = players[:match_player_count]
# 创建匹配
if self._create_match(selected_players, queue):
# 从队列中移除已匹配的玩家
for player_info in selected_players:
self._remove_player_from_queue(player_info["player_id"])
self.queue_state["players_matched"] += len(selected_players)
self.queue_stats["matches_created"] += 1
except Exception as e:
print(f"✗ 队列处理失败: {e}")
self.queue_stats["queue_errors"] += 1
def _create_match(self, players: List[Dict[str, Any]], queue: Dict[str, Any]) -> bool:
"""
创建匹配
Args:
players: 玩家列表
queue: 队列信息
Returns:
是否创建成功
"""
try:
# 生成匹配ID
match_id = f"match_{int(time.time() * 1000000)}"
# 提取玩家ID
player_ids = [player["player_id"] for player in players]
# 创建房间
room_id = None
if self.plugin.room_allocator:
room_settings = {
"game_mode": queue["game_mode"],
"region": queue["region"],
"max_players": len(players)
}
room_id = self.plugin.room_allocator.create_room(
room_name=f"Match_{match_id[:8]}",
room_settings=room_settings
)
# 添加玩家到房间
if room_id and self.plugin.room_allocator:
for player_id in player_ids:
self.plugin.room_allocator.add_client_to_room(room_id, player_id)
# 通知匹配管理器匹配完成
if self.plugin.match_manager:
self.plugin.match_manager.complete_match(match_id, room_id or "")
# 触发匹配找到回调
self._trigger_queue_callback("match_found", {
"match_id": match_id,
"room_id": room_id,
"player_ids": player_ids,
"queue_name": queue["name"],
"timestamp": time.time()
})
print(f"✓ 匹配已创建: {match_id} ({len(player_ids)}名玩家)")
return True
except Exception as e:
print(f"✗ 匹配创建失败: {e}")
self.queue_stats["queue_errors"] += 1
return False
def get_queue_info(self, queue_name: str = None) -> Dict[str, Any]:
"""
获取队列信息
Args:
queue_name: 队列名称可选如果未指定则返回所有队列信息
Returns:
队列信息字典
"""
try:
with self.queue_lock:
if queue_name:
if queue_name in self.queues:
queue = self.queues[queue_name]
return {
"name": queue["name"],
"game_mode": queue["game_mode"],
"region": queue["region"],
"player_count": len(queue["players"]),
"created_time": queue["created_time"]
}
else:
return {}
else:
# 返回所有队列信息
queue_info = {}
for name, queue in self.queues.items():
queue_info[name] = {
"name": queue["name"],
"game_mode": queue["game_mode"],
"region": queue["region"],
"player_count": len(queue["players"]),
"created_time": queue["created_time"]
}
return queue_info
except Exception as e:
print(f"✗ 队列信息获取失败: {e}")
self.queue_stats["queue_errors"] += 1
return {}
def get_player_queue_info(self, player_id: str) -> Optional[Dict[str, Any]]:
"""
获取玩家队列信息
Args:
player_id: 玩家ID
Returns:
玩家队列信息或None
"""
try:
with self.queue_lock:
if player_id in self.player_queues:
return self.player_queues[player_id].copy()
else:
return None
except Exception as e:
print(f"✗ 玩家队列信息获取失败: {e}")
self.queue_stats["queue_errors"] += 1
return None
def get_queue_stats(self) -> Dict[str, Any]:
"""
获取队列统计信息
Returns:
队列统计字典
"""
return {
"state": self.queue_state.copy(),
"stats": self.queue_stats.copy(),
"config": self.queue_config.copy(),
"current_queues": len(self.queues),
"current_players": len(self.player_queues)
}
def reset_stats(self):
"""重置队列统计信息"""
try:
self.queue_stats = {
"players_added": 0,
"players_removed": 0,
"matches_created": 0,
"queue_timeouts": 0,
"queue_errors": 0
}
print("✓ 队列统计信息已重置")
except Exception as e:
print(f"✗ 队列统计信息重置失败: {e}")
def set_queue_config(self, config: Dict[str, Any]) -> bool:
"""
设置队列配置
Args:
config: 队列配置字典
Returns:
是否设置成功
"""
try:
self.queue_config.update(config)
print(f"✓ 队列配置已更新: {self.queue_config}")
return True
except Exception as e:
print(f"✗ 队列配置设置失败: {e}")
return False
def get_queue_config(self) -> Dict[str, Any]:
"""
获取队列配置
Returns:
队列配置字典
"""
return self.queue_config.copy()
def _trigger_queue_callback(self, callback_type: str, data: Dict[str, Any]):
"""
触发队列回调
Args:
callback_type: 回调类型
data: 回调数据
"""
try:
if callback_type in self.queue_callbacks:
for callback in self.queue_callbacks[callback_type]:
try:
callback(data)
except Exception as e:
print(f"✗ 队列回调执行失败: {callback_type} - {e}")
except Exception as e:
print(f"✗ 队列回调触发失败: {e}")
def register_queue_callback(self, callback_type: str, callback: callable):
"""
注册队列回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.queue_callbacks:
self.queue_callbacks[callback_type].append(callback)
print(f"✓ 队列回调已注册: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 队列回调注册失败: {e}")
def unregister_queue_callback(self, callback_type: str, callback: callable):
"""
注销队列回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.queue_callbacks:
if callback in self.queue_callbacks[callback_type]:
self.queue_callbacks[callback_type].remove(callback)
print(f"✓ 队列回调已注销: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 队列回调注销失败: {e}")

View File

@ -0,0 +1,752 @@
"""
房间分配器模块
为匹配成功的玩家创建和分配房间
"""
import time
import uuid
from typing import Dict, Any, List, Optional
class RoomAllocator:
"""
房间分配器
为匹配成功的玩家创建和分配房间
"""
def __init__(self, plugin):
"""
初始化房间分配器
Args:
plugin: 匹配系统插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 房间配置
self.room_config = {
"default_max_players": 8,
"enable_room_passwords": True,
"enable_room_visibility": True,
"room_timeout": 3600, # 1小时无活动房间自动关闭
"max_rooms": 1000,
"enable_persistent_rooms": False
}
# 房间状态
self.room_state = {
"total_rooms": 0,
"active_rooms": 0,
"occupied_rooms": 0,
"available_rooms": 0
}
# 房间存储
self.rooms = {} # 房间数据
self.player_rooms = {} # 玩家所在房间映射
# 房间统计
self.room_stats = {
"rooms_created": 0,
"rooms_destroyed": 0,
"players_added": 0,
"players_removed": 0,
"room_errors": 0
}
# 回调函数
self.room_callbacks = {
"room_created": [],
"room_destroyed": [],
"player_added": [],
"player_removed": [],
"room_error": []
}
# 时间戳记录
self.last_cleanup = 0.0
self.last_stats_reset = 0.0
print("✓ 房间分配器已创建")
def initialize(self) -> bool:
"""
初始化房间分配器
Returns:
是否初始化成功
"""
try:
print("正在初始化房间分配器...")
self.initialized = True
print("✓ 房间分配器初始化完成")
return True
except Exception as e:
print(f"✗ 房间分配器初始化失败: {e}")
self.room_stats["room_errors"] += 1
import traceback
traceback.print_exc()
return False
def enable(self) -> bool:
"""
启用房间分配器
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ 房间分配器未初始化")
return False
self.enabled = True
print("✓ 房间分配器已启用")
return True
except Exception as e:
print(f"✗ 房间分配器启用失败: {e}")
self.room_stats["room_errors"] += 1
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用房间分配器"""
try:
self.enabled = False
# 销毁所有房间
self._destroy_all_rooms()
print("✓ 房间分配器已禁用")
except Exception as e:
print(f"✗ 房间分配器禁用失败: {e}")
self.room_stats["room_errors"] += 1
import traceback
traceback.print_exc()
def finalize(self):
"""清理房间分配器资源"""
try:
# 禁用房间分配器
if self.enabled:
self.disable()
# 清理回调
self.room_callbacks.clear()
self.initialized = False
print("✓ 房间分配器资源已清理")
except Exception as e:
print(f"✗ 房间分配器资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新房间分配器状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
current_time = time.time()
# 定期清理过期房间
if current_time - self.last_cleanup >= 300.0: # 每5分钟清理一次
self._cleanup_expired_rooms(current_time)
self.last_cleanup = current_time
except Exception as e:
print(f"✗ 房间分配器更新失败: {e}")
self.room_stats["room_errors"] += 1
import traceback
traceback.print_exc()
def _cleanup_expired_rooms(self, current_time: float):
"""清理过期房间"""
try:
expired_rooms = []
for room_id, room_data in self.rooms.items():
# 检查房间是否超时
if current_time - room_data.get("last_activity", 0) > self.room_config["room_timeout"]:
# 检查房间是否为空
if len(room_data.get("players", {})) == 0:
expired_rooms.append(room_id)
# 销毁过期房间
for room_id in expired_rooms:
self.destroy_room(room_id)
except Exception as e:
print(f"✗ 过期房间清理失败: {e}")
self.room_stats["room_errors"] += 1
def _destroy_all_rooms(self):
"""销毁所有房间"""
try:
room_ids = list(self.rooms.keys())
for room_id in room_ids:
self.destroy_room(room_id)
except Exception as e:
print(f"✗ 所有房间销毁失败: {e}")
self.room_stats["room_errors"] += 1
def create_room(self, room_name: str = None, room_settings: Dict[str, Any] = None,
room_password: str = None) -> Optional[str]:
"""
创建房间
Args:
room_name: 房间名称
room_settings: 房间设置
room_password: 房间密码
Returns:
房间ID或None
"""
try:
if not self.enabled:
return None
# 检查房间数量限制
if len(self.rooms) >= self.room_config["max_rooms"]:
print("✗ 房间数量已达上限")
self.room_stats["room_errors"] += 1
return None
# 生成房间ID
room_id = f"room_{int(time.time() * 1000000)}"
# 使用默认设置或传入设置
settings = {
"max_players": self.room_config["default_max_players"],
"is_public": True,
"allow_spectators": True
}
if room_settings:
settings.update(room_settings)
# 创建房间数据
room_data = {
"room_id": room_id,
"room_name": room_name or f"房间-{room_id[:8]}",
"settings": settings,
"password": room_password,
"players": {}, # 玩家ID到玩家数据的映射
"host_player_id": None,
"created_time": time.time(),
"last_activity": time.time(),
"room_state": {}, # 房间状态数据
"custom_data": {} # 自定义房间数据
}
# 添加到房间列表
self.rooms[room_id] = room_data
self.room_state["total_rooms"] += 1
self.room_state["active_rooms"] += 1
self.room_stats["rooms_created"] += 1
# 触发房间创建回调
self._trigger_room_callback("room_created", {
"room_id": room_id,
"room_name": room_data["room_name"],
"settings": settings,
"timestamp": room_data["created_time"]
})
print(f"✓ 房间已创建: {room_id} ({room_data['room_name']})")
return room_id
except Exception as e:
print(f"✗ 房间创建失败: {e}")
self.room_stats["room_errors"] += 1
return None
def destroy_room(self, room_id: str) -> bool:
"""
销毁房间
Args:
room_id: 房间ID
Returns:
是否销毁成功
"""
try:
if not self.enabled:
return False
# 检查房间是否存在
if room_id not in self.rooms:
print(f"✗ 房间不存在: {room_id}")
return False
room_data = self.rooms[room_id]
# 通知房间内所有玩家
player_ids = list(room_data["players"].keys())
for player_id in player_ids:
self._notify_player_room_destroyed(player_id, room_id)
# 移除房间
del self.rooms[room_id]
self.room_state["active_rooms"] -= 1
self.room_stats["rooms_destroyed"] += 1
# 触发房间销毁回调
self._trigger_room_callback("room_destroyed", {
"room_id": room_id,
"room_name": room_data["room_name"],
"timestamp": time.time()
})
print(f"✓ 房间已销毁: {room_id}")
return True
except Exception as e:
print(f"✗ 房间销毁失败: {e}")
self.room_stats["room_errors"] += 1
return False
def _notify_player_room_destroyed(self, player_id: str, room_id: str):
"""
通知玩家房间被销毁
Args:
player_id: 玩家ID
room_id: 房间ID
"""
try:
# 从玩家房间映射中移除
if player_id in self.player_rooms:
del self.player_rooms[player_id]
except Exception as e:
print(f"✗ 玩家房间销毁通知失败: {e}")
self.room_stats["room_errors"] += 1
def add_client_to_room(self, room_id: str, player_id: str, player_data: Dict[str, Any] = None) -> bool:
"""
添加玩家到房间
Args:
room_id: 房间ID
player_id: 玩家ID
player_data: 玩家数据
Returns:
是否添加成功
"""
try:
if not self.enabled:
return False
# 检查房间是否存在
if room_id not in self.rooms:
print(f"✗ 房间不存在: {room_id}")
self.room_stats["room_errors"] += 1
return False
room_data = self.rooms[room_id]
# 检查房间是否已满
if len(room_data["players"]) >= room_data["settings"]["max_players"]:
print(f"✗ 房间已满: {room_id}")
return False
# 检查房间密码
if room_data["password"] and not self._verify_room_password(room_id, player_data):
print(f"✗ 房间密码错误: {room_id}")
return False
# 添加玩家到房间
player_info = player_data or {}
player_info["join_time"] = time.time()
player_info["last_activity"] = time.time()
room_data["players"][player_id] = player_info
room_data["last_activity"] = time.time()
# 设置房间主机(如果是第一个玩家)
if room_data["host_player_id"] is None:
room_data["host_player_id"] = player_id
# 更新玩家房间映射
self.player_rooms[player_id] = room_id
self.room_stats["players_added"] += 1
# 触发玩家添加回调
self._trigger_room_callback("player_added", {
"room_id": room_id,
"room_name": room_data["room_name"],
"player_id": player_id,
"timestamp": time.time()
})
print(f"✓ 玩家已加入房间: {player_id} -> {room_id}")
return True
except Exception as e:
print(f"✗ 玩家加入房间失败: {e}")
self.room_stats["room_errors"] += 1
return False
def remove_client_from_room(self, room_id: str, player_id: str) -> bool:
"""
从房间移除玩家
Args:
room_id: 房间ID
player_id: 玩家ID
Returns:
是否移除成功
"""
try:
if not self.enabled:
return False
# 检查房间是否存在
if room_id not in self.rooms:
print(f"✗ 房间不存在: {room_id}")
return False
room_data = self.rooms[room_id]
# 检查玩家是否在房间中
if player_id not in room_data["players"]:
print(f"✗ 玩家不在房间中: {player_id}")
return False
# 移除玩家
del room_data["players"][player_id]
room_data["last_activity"] = time.time()
# 更新主机(如果移除的是主机)
if room_data["host_player_id"] == player_id:
if room_data["players"]:
# 选择第一个玩家作为新主机
room_data["host_player_id"] = next(iter(room_data["players"]))
else:
room_data["host_player_id"] = None
# 移除玩家房间映射
if player_id in self.player_rooms:
del self.player_rooms[player_id]
self.room_stats["players_removed"] += 1
# 触发玩家移除回调
self._trigger_room_callback("player_removed", {
"room_id": room_id,
"room_name": room_data["room_name"],
"player_id": player_id,
"timestamp": time.time()
})
# 如果房间为空,销毁房间
if len(room_data["players"]) == 0:
self.destroy_room(room_id)
print(f"✓ 玩家已离开房间: {player_id} <- {room_id}")
return True
except Exception as e:
print(f"✗ 玩家离开房间失败: {e}")
self.room_stats["room_errors"] += 1
return False
def _verify_room_password(self, room_id: str, player_data: Dict[str, Any]) -> bool:
"""
验证房间密码
Args:
room_id: 房间ID
player_data: 玩家数据
Returns:
密码是否正确
"""
try:
if not self.room_config["enable_room_passwords"]:
return True
if room_id not in self.rooms:
return False
room_data = self.rooms[room_id]
if not room_data["password"]:
return True
player_password = player_data.get("password") if player_data else None
return player_password == room_data["password"]
except Exception as e:
print(f"✗ 房间密码验证失败: {e}")
self.room_stats["room_errors"] += 1
return False
def get_room_info(self, room_id: str) -> Optional[Dict[str, Any]]:
"""
获取房间信息
Args:
room_id: 房间ID
Returns:
房间信息或None
"""
try:
if room_id in self.rooms:
room_data = self.rooms[room_id]
# 返回不包含敏感信息的房间信息
safe_room_data = {
"room_id": room_data["room_id"],
"room_name": room_data["room_name"],
"settings": room_data["settings"],
"player_count": len(room_data["players"]),
"has_password": bool(room_data["password"]),
"host_player_id": room_data["host_player_id"],
"created_time": room_data["created_time"],
"last_activity": room_data["last_activity"]
}
return safe_room_data
else:
return None
except Exception as e:
print(f"✗ 获取房间信息失败: {e}")
self.room_stats["room_errors"] += 1
return None
def get_player_room(self, player_id: str) -> Optional[str]:
"""
获取玩家所在房间
Args:
player_id: 玩家ID
Returns:
房间ID或None
"""
try:
return self.player_rooms.get(player_id)
except Exception as e:
print(f"✗ 获取玩家房间失败: {e}")
self.room_stats["room_errors"] += 1
return None
def get_room_players(self, room_id: str) -> List[str]:
"""
获取房间内所有玩家
Args:
room_id: 房间ID
Returns:
玩家ID列表
"""
try:
if room_id in self.rooms:
return list(self.rooms[room_id]["players"].keys())
else:
return []
except Exception as e:
print(f"✗ 获取房间玩家失败: {e}")
self.room_stats["room_errors"] += 1
return []
def update_room_state(self, room_id: str, state_data: Dict[str, Any]) -> bool:
"""
更新房间状态
Args:
room_id: 房间ID
state_data: 状态数据
Returns:
是否更新成功
"""
try:
if room_id not in self.rooms:
return False
self.rooms[room_id]["room_state"].update(state_data)
self.rooms[room_id]["last_activity"] = time.time()
return True
except Exception as e:
print(f"✗ 更新房间状态失败: {e}")
self.room_stats["room_errors"] += 1
return False
def set_room_custom_data(self, room_id: str, key: str, value: Any) -> bool:
"""
设置房间自定义数据
Args:
room_id: 房间ID
key: 数据键
value: 数据值
Returns:
是否设置成功
"""
try:
if room_id not in self.rooms:
return False
self.rooms[room_id]["custom_data"][key] = value
return True
except Exception as e:
print(f"✗ 设置房间自定义数据失败: {e}")
self.room_stats["room_errors"] += 1
return False
def get_room_custom_data(self, room_id: str, key: str, default: Any = None) -> Any:
"""
获取房间自定义数据
Args:
room_id: 房间ID
key: 数据键
default: 默认值
Returns:
数据值或默认值
"""
try:
if room_id not in self.rooms:
return default
return self.rooms[room_id]["custom_data"].get(key, default)
except Exception as e:
print(f"✗ 获取房间自定义数据失败: {e}")
self.room_stats["room_errors"] += 1
return default
def get_room_stats(self) -> Dict[str, Any]:
"""
获取房间统计信息
Returns:
房间统计字典
"""
return {
"state": self.room_state.copy(),
"stats": self.room_stats.copy(),
"config": self.room_config.copy(),
"current_rooms": len(self.rooms),
"current_players": len(self.player_rooms)
}
def reset_stats(self):
"""重置房间统计信息"""
try:
self.room_stats = {
"rooms_created": 0,
"rooms_destroyed": 0,
"players_added": 0,
"players_removed": 0,
"room_errors": 0
}
print("✓ 房间统计信息已重置")
except Exception as e:
print(f"✗ 房间统计信息重置失败: {e}")
def set_room_config(self, config: Dict[str, Any]) -> bool:
"""
设置房间配置
Args:
config: 房间配置字典
Returns:
是否设置成功
"""
try:
self.room_config.update(config)
print(f"✓ 房间配置已更新: {self.room_config}")
return True
except Exception as e:
print(f"✗ 房间配置设置失败: {e}")
return False
def get_room_config(self) -> Dict[str, Any]:
"""
获取房间配置
Returns:
房间配置字典
"""
return self.room_config.copy()
def _trigger_room_callback(self, callback_type: str, data: Dict[str, Any]):
"""
触发房间回调
Args:
callback_type: 回调类型
data: 回调数据
"""
try:
if callback_type in self.room_callbacks:
for callback in self.room_callbacks[callback_type]:
try:
callback(data)
except Exception as e:
print(f"✗ 房间回调执行失败: {callback_type} - {e}")
except Exception as e:
print(f"✗ 房间回调触发失败: {e}")
def register_room_callback(self, callback_type: str, callback: callable):
"""
注册房间回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.room_callbacks:
self.room_callbacks[callback_type].append(callback)
print(f"✓ 房间回调已注册: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 房间回调注册失败: {e}")
def unregister_room_callback(self, callback_type: str, callback: callable):
"""
注销房间回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.room_callbacks:
if callback in self.room_callbacks[callback_type]:
self.room_callbacks[callback_type].remove(callback)
print(f"✓ 房间回调已注销: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 房间回调注销失败: {e}")

View File

@ -0,0 +1,633 @@
"""
匹配规则管理器模块
管理匹配规则和参数
"""
import time
from typing import Dict, Any, List, Optional
class RuleManager:
"""
匹配规则管理器
管理匹配规则和参数
"""
def __init__(self, plugin):
"""
初始化匹配规则管理器
Args:
plugin: 匹配系统插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 规则配置
self.rule_config = {
"default_rules": {
"min_players": 2,
"max_players": 8,
"skill_range": 100,
"max_wait_time": 120.0,
"region_matching": True,
"platform_matching": True,
"language_matching": True
},
"game_mode_rules": {}, # 不同游戏模式的规则
"custom_rules": {}, # 自定义规则
"enable_rule_validation": True,
"enable_dynamic_rules": True
}
# 规则状态
self.rule_state = {
"active_rules": "default",
"total_rules": 1, # 默认规则
"custom_rules_count": 0,
"rules_modified": 0
}
# 规则统计
self.rule_stats = {
"rules_applied": 0,
"rules_violated": 0,
"rule_errors": 0
}
# 回调函数
self.rule_callbacks = {
"rule_applied": [],
"rule_violated": [],
"rule_updated": [],
"rule_error": []
}
# 时间戳记录
self.last_rule_application = 0.0
self.last_stats_reset = 0.0
print("✓ 匹配规则管理器已创建")
def initialize(self) -> bool:
"""
初始化匹配规则管理器
Returns:
是否初始化成功
"""
try:
print("正在初始化匹配规则管理器...")
self.initialized = True
print("✓ 匹配规则管理器初始化完成")
return True
except Exception as e:
print(f"✗ 匹配规则管理器初始化失败: {e}")
self.rule_stats["rule_errors"] += 1
import traceback
traceback.print_exc()
return False
def enable(self) -> bool:
"""
启用匹配规则管理器
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ 匹配规则管理器未初始化")
return False
self.enabled = True
print("✓ 匹配规则管理器已启用")
return True
except Exception as e:
print(f"✗ 匹配规则管理器启用失败: {e}")
self.rule_stats["rule_errors"] += 1
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用匹配规则管理器"""
try:
self.enabled = False
print("✓ 匹配规则管理器已禁用")
except Exception as e:
print(f"✗ 匹配规则管理器禁用失败: {e}")
self.rule_stats["rule_errors"] += 1
import traceback
traceback.print_exc()
def finalize(self):
"""清理匹配规则管理器资源"""
try:
# 禁用匹配规则管理器
if self.enabled:
self.disable()
# 清理回调
self.rule_callbacks.clear()
self.initialized = False
print("✓ 匹配规则管理器资源已清理")
except Exception as e:
print(f"✗ 匹配规则管理器资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新匹配规则管理器状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
self.last_rule_application = time.time()
except Exception as e:
print(f"✗ 匹配规则管理器更新失败: {e}")
self.rule_stats["rule_errors"] += 1
import traceback
traceback.print_exc()
def apply_rules(self, players: List[Dict[str, Any]], game_mode: str = "default") -> bool:
"""
应用匹配规则
Args:
players: 玩家列表
game_mode: 游戏模式
Returns:
是否符合规则
"""
try:
if not self.enabled:
return True # 如果未启用,跳过规则检查
self.rule_stats["rules_applied"] += 1
# 获取适用的规则
rules = self.get_active_rules(game_mode)
# 检查玩家数量
min_players = rules.get("min_players", 2)
max_players = rules.get("max_players", 8)
if len(players) < min_players:
print(f"✗ 玩家数量不足: {len(players)} < {min_players}")
self.rule_stats["rules_violated"] += 1
# 触发规则违反回调
self._trigger_rule_callback("rule_violated", {
"rule": "min_players",
"required": min_players,
"actual": len(players),
"timestamp": time.time()
})
return False
if len(players) > max_players:
print(f"✗ 玩家数量超限: {len(players)} > {max_players}")
self.rule_stats["rules_violated"] += 1
# 触发规则违反回调
self._trigger_rule_callback("rule_violated", {
"rule": "max_players",
"required": max_players,
"actual": len(players),
"timestamp": time.time()
})
return False
# 检查技能范围
if rules.get("skill_range") is not None:
skill_range = rules["skill_range"]
skills = [p.get("skill_level", 0) for p in players]
min_skill = min(skills)
max_skill = max(skills)
if max_skill - min_skill > skill_range:
print(f"✗ 技能范围超限: {max_skill - min_skill} > {skill_range}")
self.rule_stats["rules_violated"] += 1
# 触发规则违反回调
self._trigger_rule_callback("rule_violated", {
"rule": "skill_range",
"required": skill_range,
"actual": max_skill - min_skill,
"timestamp": time.time()
})
return False
# 检查区域匹配
if rules.get("region_matching", False):
regions = [p.get("region", "global") for p in players]
if len(set(regions)) > 1:
print(f"✗ 区域不匹配: {set(regions)}")
self.rule_stats["rules_violated"] += 1
# 触发规则违反回调
self._trigger_rule_callback("rule_violated", {
"rule": "region_matching",
"regions": list(set(regions)),
"timestamp": time.time()
})
return False
# 检查平台匹配
if rules.get("platform_matching", False):
platforms = [p.get("platform", "pc") for p in players]
if len(set(platforms)) > 1:
print(f"✗ 平台不匹配: {set(platforms)}")
self.rule_stats["rules_violated"] += 1
# 触发规则违反回调
self._trigger_rule_callback("rule_violated", {
"rule": "platform_matching",
"platforms": list(set(platforms)),
"timestamp": time.time()
})
return False
# 检查语言匹配
if rules.get("language_matching", False):
languages = [p.get("language", "en") for p in players]
if len(set(languages)) > 1:
print(f"✗ 语言不匹配: {set(languages)}")
self.rule_stats["rules_violated"] += 1
# 触发规则违反回调
self._trigger_rule_callback("rule_violated", {
"rule": "language_matching",
"languages": list(set(languages)),
"timestamp": time.time()
})
return False
# 触发规则应用回调
self._trigger_rule_callback("rule_applied", {
"players": len(players),
"game_mode": game_mode,
"rules": rules,
"timestamp": time.time()
})
print(f"✓ 规则检查通过: {len(players)}名玩家, 游戏模式: {game_mode}")
return True
except Exception as e:
print(f"✗ 规则应用失败: {e}")
self.rule_stats["rule_errors"] += 1
return False
def get_active_rules(self, game_mode: str = "default") -> Dict[str, Any]:
"""
获取活动规则
Args:
game_mode: 游戏模式
Returns:
规则字典
"""
try:
# 检查是否有特定游戏模式的规则
if game_mode in self.rule_config["game_mode_rules"]:
return self.rule_config["game_mode_rules"][game_mode]
# 检查是否有自定义规则
if self.rule_state["active_rules"] in self.rule_config["custom_rules"]:
return self.rule_config["custom_rules"][self.rule_state["active_rules"]]
# 返回默认规则
return self.rule_config["default_rules"]
except Exception as e:
print(f"✗ 获取活动规则失败: {e}")
self.rule_stats["rule_errors"] += 1
return self.rule_config["default_rules"]
def set_active_rules(self, rule_set_name: str) -> bool:
"""
设置活动规则集
Args:
rule_set_name: 规则集名称
Returns:
是否设置成功
"""
try:
# 验证规则集存在
if (rule_set_name != "default" and
rule_set_name not in self.rule_config["custom_rules"] and
rule_set_name not in self.rule_config["game_mode_rules"]):
print(f"✗ 规则集不存在: {rule_set_name}")
return False
self.rule_state["active_rules"] = rule_set_name
# 触发规则更新回调
self._trigger_rule_callback("rule_updated", {
"rule_set": rule_set_name,
"timestamp": time.time()
})
print(f"✓ 活动规则集已设置为: {rule_set_name}")
return True
except Exception as e:
print(f"✗ 活动规则集设置失败: {e}")
self.rule_stats["rule_errors"] += 1
return False
def add_custom_rule_set(self, rule_set_name: str, rules: Dict[str, Any]) -> bool:
"""
添加自定义规则集
Args:
rule_set_name: 规则集名称
rules: 规则字典
Returns:
是否添加成功
"""
try:
if not self.enabled:
return False
# 验证规则
if self.rule_config["enable_rule_validation"]:
if not self._validate_rules(rules):
print(f"✗ 规则验证失败: {rule_set_name}")
self.rule_stats["rule_errors"] += 1
return False
self.rule_config["custom_rules"][rule_set_name] = rules
self.rule_state["custom_rules_count"] = len(self.rule_config["custom_rules"])
self.rule_state["total_rules"] += 1
self.rule_state["rules_modified"] += 1
print(f"✓ 自定义规则集已添加: {rule_set_name}")
return True
except Exception as e:
print(f"✗ 自定义规则集添加失败: {e}")
self.rule_stats["rule_errors"] += 1
return False
def remove_custom_rule_set(self, rule_set_name: str) -> bool:
"""
移除自定义规则集
Args:
rule_set_name: 规则集名称
Returns:
是否移除成功
"""
try:
if rule_set_name in self.rule_config["custom_rules"]:
del self.rule_config["custom_rules"][rule_set_name]
self.rule_state["custom_rules_count"] = len(self.rule_config["custom_rules"])
self.rule_state["total_rules"] -= 1
self.rule_state["rules_modified"] += 1
# 如果删除的是活动规则集,切换回默认规则
if self.rule_state["active_rules"] == rule_set_name:
self.rule_state["active_rules"] = "default"
print(f"✓ 自定义规则集已移除: {rule_set_name}")
return True
else:
print(f"✗ 自定义规则集不存在: {rule_set_name}")
return False
except Exception as e:
print(f"✗ 自定义规则集移除失败: {e}")
self.rule_stats["rule_errors"] += 1
return False
def _validate_rules(self, rules: Dict[str, Any]) -> bool:
"""
验证规则
Args:
rules: 规则字典
Returns:
是否验证通过
"""
try:
# 检查基本规则参数
if "min_players" in rules:
if not isinstance(rules["min_players"], int) or rules["min_players"] < 1:
return False
if "max_players" in rules:
if not isinstance(rules["max_players"], int) or rules["max_players"] < 1:
return False
if "min_players" in rules and "max_players" in rules:
if rules["min_players"] > rules["max_players"]:
return False
if "skill_range" in rules:
if not isinstance(rules["skill_range"], (int, float)) or rules["skill_range"] < 0:
return False
if "max_wait_time" in rules:
if not isinstance(rules["max_wait_time"], (int, float)) or rules["max_wait_time"] < 0:
return False
return True
except Exception as e:
print(f"✗ 规则验证失败: {e}")
self.rule_stats["rule_errors"] += 1
return False
def add_game_mode_rules(self, game_mode: str, rules: Dict[str, Any]) -> bool:
"""
添加游戏模式规则
Args:
game_mode: 游戏模式
rules: 规则字典
Returns:
是否添加成功
"""
try:
if not self.enabled:
return False
# 验证规则
if self.rule_config["enable_rule_validation"]:
if not self._validate_rules(rules):
print(f"✗ 游戏模式规则验证失败: {game_mode}")
self.rule_stats["rule_errors"] += 1
return False
self.rule_config["game_mode_rules"][game_mode] = rules
self.rule_state["total_rules"] += 1
self.rule_state["rules_modified"] += 1
print(f"✓ 游戏模式规则已添加: {game_mode}")
return True
except Exception as e:
print(f"✗ 游戏模式规则添加失败: {e}")
self.rule_stats["rule_errors"] += 1
return False
def remove_game_mode_rules(self, game_mode: str) -> bool:
"""
移除游戏模式规则
Args:
game_mode: 游戏模式
Returns:
是否移除成功
"""
try:
if game_mode in self.rule_config["game_mode_rules"]:
del self.rule_config["game_mode_rules"][game_mode]
self.rule_state["total_rules"] -= 1
self.rule_state["rules_modified"] += 1
print(f"✓ 游戏模式规则已移除: {game_mode}")
return True
else:
print(f"✗ 游戏模式规则不存在: {game_mode}")
return False
except Exception as e:
print(f"✗ 游戏模式规则移除失败: {e}")
self.rule_stats["rule_errors"] += 1
return False
def get_rule_stats(self) -> Dict[str, Any]:
"""
获取规则统计信息
Returns:
规则统计字典
"""
return {
"state": self.rule_state.copy(),
"stats": self.rule_stats.copy(),
"config": self.rule_config.copy()
}
def reset_stats(self):
"""重置规则统计信息"""
try:
self.rule_stats = {
"rules_applied": 0,
"rules_violated": 0,
"rule_errors": 0
}
print("✓ 规则统计信息已重置")
except Exception as e:
print(f"✗ 规则统计信息重置失败: {e}")
def set_rule_config(self, config: Dict[str, Any]) -> bool:
"""
设置规则配置
Args:
config: 规则配置字典
Returns:
是否设置成功
"""
try:
self.rule_config.update(config)
print(f"✓ 规则配置已更新: {self.rule_config}")
return True
except Exception as e:
print(f"✗ 规则配置设置失败: {e}")
return False
def get_rule_config(self) -> Dict[str, Any]:
"""
获取规则配置
Returns:
规则配置字典
"""
return self.rule_config.copy()
def _trigger_rule_callback(self, callback_type: str, data: Dict[str, Any]):
"""
触发规则回调
Args:
callback_type: 回调类型
data: 回调数据
"""
try:
if callback_type in self.rule_callbacks:
for callback in self.rule_callbacks[callback_type]:
try:
callback(data)
except Exception as e:
print(f"✗ 规则回调执行失败: {callback_type} - {e}")
except Exception as e:
print(f"✗ 规则回调触发失败: {e}")
def register_rule_callback(self, callback_type: str, callback: callable):
"""
注册规则回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.rule_callbacks:
self.rule_callbacks[callback_type].append(callback)
print(f"✓ 规则回调已注册: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 规则回调注册失败: {e}")
def unregister_rule_callback(self, callback_type: str, callback: callable):
"""
注销规则回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.rule_callbacks:
if callback in self.rule_callbacks[callback_type]:
self.rule_callbacks[callback_type].remove(callback)
print(f"✓ 规则回调已注销: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 规则回调注销失败: {e}")

View File

@ -0,0 +1,657 @@
"""
统计数据管理器模块
收集和分析匹配数据
"""
import time
import json
from typing import Dict, Any, List, Optional
from collections import defaultdict, deque
class StatsManager:
"""
统计数据管理器
收集和分析匹配数据
"""
def __init__(self, plugin):
"""
初始化统计数据管理器
Args:
plugin: 匹配系统插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 统计配置
self.stats_config = {
"enable_statistics": True,
"data_retention_period": 86400, # 24小时
"max_data_points": 10000,
"enable_realtime_stats": True,
"stats_collection_interval": 10.0,
"enable_export": True,
"export_format": "json"
}
# 统计数据存储
self.statistics = {
"match_times": deque(maxlen=1000),
"queue_times": deque(maxlen=1000),
"success_rates": deque(maxlen=1000),
"player_counts": deque(maxlen=1000),
"algorithm_performance": deque(maxlen=1000),
"system_performance": deque(maxlen=1000)
}
# 统计状态
self.stats_state = {
"total_matches": 0,
"successful_matches": 0,
"failed_matches": 0,
"total_players": 0,
"matched_players": 0,
"last_stats_update": 0.0
}
# 历史统计数据
self.historical_stats = {
"daily": defaultdict(dict),
"weekly": defaultdict(dict),
"monthly": defaultdict(dict)
}
# 统计报告
self.stat_reports = {
"last_report": None,
"report_cache": {}
}
# 统计回调
self.stats_callbacks = {
"stats_updated": [],
"report_generated": [],
"data_exported": [],
"stats_error": []
}
# 时间戳记录
self.last_stats_collection = 0.0
self.last_report_generation = 0.0
print("✓ 统计数据管理器已创建")
def initialize(self) -> bool:
"""
初始化统计数据管理器
Returns:
是否初始化成功
"""
try:
print("正在初始化统计数据管理器...")
self.initialized = True
print("✓ 统计数据管理器初始化完成")
return True
except Exception as e:
print(f"✗ 统计数据管理器初始化失败: {e}")
import traceback
traceback.print_exc()
return False
def enable(self) -> bool:
"""
启用统计数据管理器
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ 统计数据管理器未初始化")
return False
self.enabled = True
print("✓ 统计数据管理器已启用")
return True
except Exception as e:
print(f"✗ 统计数据管理器启用失败: {e}")
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用统计数据管理器"""
try:
self.enabled = False
print("✓ 统计数据管理器已禁用")
except Exception as e:
print(f"✗ 统计数据管理器禁用失败: {e}")
import traceback
traceback.print_exc()
def finalize(self):
"""清理统计数据管理器资源"""
try:
# 禁用统计数据管理器
if self.enabled:
self.disable()
# 清理回调
self.stats_callbacks.clear()
self.initialized = False
print("✓ 统计数据管理器资源已清理")
except Exception as e:
print(f"✗ 统计数据管理器资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新统计数据管理器状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
current_time = time.time()
# 定期收集统计数据
if current_time - self.last_stats_collection >= self.stats_config["stats_collection_interval"]:
self._collect_statistics()
self.last_stats_collection = current_time
self.stats_state["last_stats_update"] = current_time
except Exception as e:
print(f"✗ 统计数据管理器更新失败: {e}")
import traceback
traceback.print_exc()
def _collect_statistics(self):
"""收集统计数据"""
try:
current_time = time.time()
stats_data = {}
# 收集匹配管理器统计数据
if self.plugin.match_manager:
match_stats = self.plugin.match_manager.get_match_stats()
match_state = match_stats.get("state", {})
stats_data["active_matches"] = match_state.get("active_matches", 0)
stats_data["successful_matches"] = match_state.get("successful_matches", 0)
stats_data["failed_matches"] = match_state.get("failed_matches", 0)
# 更新总计数
self.stats_state["total_matches"] = (
match_state.get("successful_matches", 0) +
match_state.get("failed_matches", 0)
)
self.stats_state["successful_matches"] = match_state.get("successful_matches", 0)
self.stats_state["failed_matches"] = match_state.get("failed_matches", 0)
# 收集队列管理器统计数据
if self.plugin.queue_manager:
queue_stats = self.plugin.queue_manager.get_queue_stats()
queue_state = queue_stats.get("state", {})
stats_data["total_players"] = queue_state.get("total_players", 0)
stats_data["players_matched"] = queue_state.get("players_matched", 0)
stats_data["players_timed_out"] = queue_state.get("players_timed_out", 0)
# 更新总计数
self.stats_state["total_players"] = queue_state.get("total_players", 0)
self.stats_state["matched_players"] = queue_state.get("players_matched", 0)
# 收集算法管理器统计数据
if self.plugin.algorithm_manager:
algorithm_stats = self.plugin.algorithm_manager.get_algorithm_stats()
algorithm_state = algorithm_stats.get("state", {})
stats_data["total_algorithms"] = algorithm_state.get("total_matches", 0)
stats_data["successful_algorithms"] = algorithm_state.get("successful_matches", 0)
stats_data["average_match_quality"] = algorithm_state.get("average_match_quality", 0)
# 记录算法性能
self.statistics["algorithm_performance"].append(
(current_time, stats_data["average_match_quality"])
)
# 收集房间分配器统计数据
if self.plugin.room_allocator:
room_stats = self.plugin.room_allocator.get_room_stats()
room_state = room_stats.get("state", {})
stats_data["active_rooms"] = room_state.get("active_rooms", 0)
stats_data["total_rooms"] = room_state.get("total_rooms", 0)
# 记录统计数据
self.statistics["player_counts"].append((current_time, stats_data.get("total_players", 0)))
# 触发统计更新回调
self._trigger_stats_callback("stats_updated", {
"stats_data": stats_data,
"timestamp": current_time
})
except Exception as e:
print(f"✗ 统计数据收集失败: {e}")
self._trigger_stats_callback("stats_error", {
"error": str(e),
"timestamp": time.time()
})
def record_match_time(self, match_time: float):
"""
记录匹配时间
Args:
match_time: 匹配时间
"""
try:
current_time = time.time()
self.statistics["match_times"].append((current_time, match_time))
except Exception as e:
print(f"✗ 匹配时间记录失败: {e}")
def record_queue_time(self, queue_time: float):
"""
记录队列时间
Args:
queue_time: 队列时间
"""
try:
current_time = time.time()
self.statistics["queue_times"].append((current_time, queue_time))
except Exception as e:
print(f"✗ 队列时间记录失败: {e}")
def record_success_rate(self, success_rate: float):
"""
记录成功率
Args:
success_rate: 成功率百分比
"""
try:
current_time = time.time()
self.statistics["success_rates"].append((current_time, success_rate))
except Exception as e:
print(f"✗ 成功率记录失败: {e}")
def get_realtime_stats(self) -> Dict[str, Any]:
"""
获取实时统计数据
Returns:
实时统计数据字典
"""
try:
realtime_stats = {
"current_time": time.time(),
"state": self.stats_state.copy(),
"statistics": {}
}
# 获取最新的统计数据
for stat_name, stat_data in self.statistics.items():
if stat_data:
realtime_stats["statistics"][stat_name] = list(stat_data)[-10:] # 最近10个数据点
else:
realtime_stats["statistics"][stat_name] = []
return realtime_stats
except Exception as e:
print(f"✗ 实时统计数据获取失败: {e}")
return {}
def generate_report(self, report_type: str = "summary", time_range: str = "24h") -> Dict[str, Any]:
"""
生成统计报告
Args:
report_type: 报告类型summary, detailed, custom
time_range: 时间范围24h, 7d, 30d
Returns:
统计报告字典
"""
try:
current_time = time.time()
report = {
"report_type": report_type,
"time_range": time_range,
"generated_time": current_time,
"data": {}
}
# 根据报告类型生成不同内容
if report_type == "summary":
report["data"] = self._generate_summary_report()
elif report_type == "detailed":
report["data"] = self._generate_detailed_report()
else:
report["data"] = self._generate_custom_report(report_type)
self.stat_reports["last_report"] = report
self.stat_reports["report_cache"][f"{report_type}_{time_range}"] = report
# 触发报告生成回调
self._trigger_stats_callback("report_generated", {
"report": report,
"timestamp": current_time
})
return report
except Exception as e:
print(f"✗ 统计报告生成失败: {e}")
self._trigger_stats_callback("stats_error", {
"error": str(e),
"timestamp": time.time()
})
return {}
def _generate_summary_report(self) -> Dict[str, Any]:
"""生成摘要报告"""
try:
summary = {
"total_matches": self.stats_state["total_matches"],
"successful_matches": self.stats_state["successful_matches"],
"failed_matches": self.stats_state["failed_matches"],
"match_success_rate": 0.0,
"total_players": self.stats_state["total_players"],
"matched_players": self.stats_state["matched_players"],
"player_match_rate": 0.0,
"average_match_time": 0.0,
"average_queue_time": 0.0
}
# 计算成功率
if self.stats_state["total_matches"] > 0:
summary["match_success_rate"] = (
self.stats_state["successful_matches"] / self.stats_state["total_matches"]
) * 100
# 计算玩家匹配率
if self.stats_state["total_players"] > 0:
summary["player_match_rate"] = (
self.stats_state["matched_players"] / self.stats_state["total_players"]
) * 100
# 计算平均匹配时间
if self.statistics["match_times"]:
times = [t[1] for t in self.statistics["match_times"]]
summary["average_match_time"] = sum(times) / len(times)
# 计算平均队列时间
if self.statistics["queue_times"]:
times = [t[1] for t in self.statistics["queue_times"]]
summary["average_queue_time"] = sum(times) / len(times)
return summary
except Exception as e:
print(f"✗ 摘要报告生成失败: {e}")
return {}
def _generate_detailed_report(self) -> Dict[str, Any]:
"""生成详细报告"""
try:
detailed = {
"summary": self._generate_summary_report(),
"trends": self._generate_trend_data(),
"performance": self._generate_performance_data(),
"historical": self._get_historical_data()
}
return detailed
except Exception as e:
print(f"✗ 详细报告生成失败: {e}")
return {}
def _generate_custom_report(self, report_type: str) -> Dict[str, Any]:
"""生成自定义报告"""
try:
# 简化实现,返回摘要报告
return self._generate_summary_report()
except Exception as e:
print(f"✗ 自定义报告生成失败: {e}")
return {}
def _generate_trend_data(self) -> Dict[str, Any]:
"""生成趋势数据"""
try:
trends = {}
# 匹配趋势
if self.statistics["match_times"]:
recent_matches = list(self.statistics["match_times"])[-100:] # 最近100个数据点
trends["match_times"] = [t[1] for t in recent_matches]
# 成功率趋势
if self.statistics["success_rates"]:
recent_rates = list(self.statistics["success_rates"])[-100:]
trends["success_rates"] = [r[1] for r in recent_rates]
# 玩家数量趋势
if self.statistics["player_counts"]:
recent_players = list(self.statistics["player_counts"])[-100:]
trends["player_counts"] = [p[1] for p in recent_players]
return trends
except Exception as e:
print(f"✗ 趋势数据生成失败: {e}")
return {}
def _generate_performance_data(self) -> Dict[str, Any]:
"""生成性能数据"""
try:
performance = {}
# 算法性能
if self.statistics["algorithm_performance"]:
recent_performance = list(self.statistics["algorithm_performance"])[-100:]
performance["algorithm_performance"] = [p[1] for p in recent_performance]
# 系统性能
if self.statistics["system_performance"]:
recent_system = list(self.statistics["system_performance"])[-100:]
performance["system_performance"] = [s[1] for s in recent_system]
return performance
except Exception as e:
print(f"✗ 性能数据生成失败: {e}")
return {}
def _get_historical_data(self) -> Dict[str, Any]:
"""获取历史数据"""
try:
return {
"daily": dict(self.historical_stats["daily"]),
"weekly": dict(self.historical_stats["weekly"]),
"monthly": dict(self.historical_stats["monthly"])
}
except Exception as e:
print(f"✗ 历史数据获取失败: {e}")
return {}
def export_stats(self, file_path: str, format: str = "json") -> bool:
"""
导出统计数据
Args:
file_path: 导出文件路径
format: 导出格式json, csv
Returns:
是否导出成功
"""
try:
import os
# 创建导出目录
export_dir = os.path.dirname(file_path)
if not os.path.exists(export_dir):
os.makedirs(export_dir)
# 生成统计数据
stats_data = {
"statistics": self.get_realtime_stats(),
"reports": self.stat_reports,
"config": self.stats_config
}
if format.lower() == "json":
# 导出为JSON格式
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(stats_data, f, indent=2, ensure_ascii=False, default=str)
else:
# 默认导出为JSON格式
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(stats_data, f, indent=2, ensure_ascii=False, default=str)
# 触发数据导出回调
self._trigger_stats_callback("data_exported", {
"file_path": file_path,
"format": format,
"timestamp": time.time()
})
print(f"✓ 统计数据已导出到: {file_path}")
return True
except Exception as e:
print(f"✗ 统计数据导出失败: {e}")
self._trigger_stats_callback("stats_error", {
"error": str(e),
"timestamp": time.time()
})
return False
def get_stats_config(self) -> Dict[str, Any]:
"""
获取统计配置
Returns:
统计配置字典
"""
return self.stats_config.copy()
def set_stats_config(self, config: Dict[str, Any]) -> bool:
"""
设置统计配置
Args:
config: 统计配置字典
Returns:
是否设置成功
"""
try:
self.stats_config.update(config)
print(f"✓ 统计配置已更新: {self.stats_config}")
return True
except Exception as e:
print(f"✗ 统计配置设置失败: {e}")
return False
def get_stats_state(self) -> Dict[str, Any]:
"""
获取统计状态
Returns:
统计状态字典
"""
return self.stats_state.copy()
def reset_stats(self):
"""重置统计数据"""
try:
# 重置统计数据
for stat_name in self.statistics:
self.statistics[stat_name].clear()
# 重置状态
self.stats_state = {
"total_matches": 0,
"successful_matches": 0,
"failed_matches": 0,
"total_players": 0,
"matched_players": 0,
"last_stats_update": 0.0
}
print("✓ 统计数据已重置")
except Exception as e:
print(f"✗ 统计数据重置失败: {e}")
def _trigger_stats_callback(self, callback_type: str, data: Dict[str, Any]):
"""
触发统计回调
Args:
callback_type: 回调类型
data: 回调数据
"""
try:
if callback_type in self.stats_callbacks:
for callback in self.stats_callbacks[callback_type]:
try:
callback(data)
except Exception as e:
print(f"✗ 统计回调执行失败: {callback_type} - {e}")
except Exception as e:
print(f"✗ 统计回调触发失败: {e}")
def register_stats_callback(self, callback_type: str, callback: callable):
"""
注册统计回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.stats_callbacks:
self.stats_callbacks[callback_type].append(callback)
print(f"✓ 统计回调已注册: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 统计回调注册失败: {e}")
def unregister_stats_callback(self, callback_type: str, callback: callable):
"""
注销统计回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.stats_callbacks:
if callback in self.stats_callbacks[callback_type]:
self.stats_callbacks[callback_type].remove(callback)
print(f"✓ 统计回调已注销: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 统计回调注销失败: {e}")

View File

@ -0,0 +1,331 @@
# 实时通信插件
为EG引擎提供完整的实时通信功能支持WebSocket双向通信、客户端管理、消息路由、房间系统等功能。
## 功能特性
### 1. WebSocket服务器
- 实时双向通信支持
- SSL/TLS加密连接
- 心跳检测和连接管理
- 消息压缩和优化
### 2. 客户端管理
- 客户端连接和断开管理
- 认证和授权系统
- 黑名单和速率限制
- 客户端状态跟踪
### 3. 消息路由
- 智能消息分发
- 房间内消息广播
- 点对点消息传递
- 消息过滤和验证
### 4. 房间系统
- 动态房间创建和销毁
- 房间密码保护
- 客户端加入/离开管理
- 房间状态同步
### 5. 协议处理
- 多协议支持JSON、二进制等
- 消息压缩和解压缩
- 数据序列化和反序列化
- 消息分片和重组
### 6. 安全认证
- Token认证机制
- 密码哈希和验证
- 会话管理
- IP过滤和阻止
### 7. 监控系统
- 实时性能监控
- 日志记录和分析
- 警报系统
- 指标收集和展示
### 8. 配置管理
- 灵活的配置系统
- 实时配置更新
- 配置导入导出
- 默认配置模板
### 9. 事件系统
- 事件驱动架构
- 异步事件处理
- 事件过滤和优先级
- 事件监听器系统
### 10. 可视化编辑器
- 实时数据监控
- 配置界面
- 统计信息展示
- 数据导出功能
## 系统架构
```
实时通信插件
├── 核心模块
│ └── WebSocket服务器 (core/websocket_server.py)
├── 客户端管理
│ └── 客户端管理器 (clients/client_manager.py)
├── 消息处理
│ ├── 消息路由器 (messaging/message_router.py)
│ ├── 协议处理器 (protocol/protocol_handler.py)
│ └── 数据序列化器 (serialization/data_serializer.py)
├── 房间系统
│ └── 房间管理器 (rooms/room_manager.py)
├── 安全系统
│ └── 认证管理器 (auth/auth_manager.py)
├── 监控系统
│ └── 通信监控器 (monitoring/communication_monitor.py)
├── 配置管理
│ └── 通信配置器 (config/comm_config.py)
├── 事件系统
│ └── 事件处理器 (events/event_handler.py)
├── 编辑器接口
│ └── 通信编辑器 (editor/comm_editor.py)
└── 工具模块
└── 通信工具类 (utils/comm_utils.py)
```
## 安装和使用
### 安装依赖
```bash
# 安装必要的Python包
pip install psutil
```
### 配置插件
插件配置文件位于 `config/communication_config.json`,包含以下主要配置项:
```json
{
"server": {
"host": "0.0.0.0",
"port": 8080,
"enable_ssl": false
},
"client": {
"max_clients": 1000,
"enable_authentication": true
},
"message": {
"max_message_size": 65536,
"enable_message_compression": true
}
}
```
### 启动插件
```python
# 初始化插件
plugin = RealtimeCommunicationPlugin(engine)
plugin.initialize()
plugin.enable()
# 启动WebSocket服务器
plugin.websocket_server.start_server()
# 插件会自动处理客户端连接、消息路由等操作
```
## API参考
### WebSocket服务器
```python
# 发送消息到客户端
plugin.websocket_server.send_message_to_client(client_id, message)
# 广播消息
plugin.websocket_server.broadcast_message(message)
# 断开客户端连接
plugin.websocket_server.disconnect_client(client_id, reason)
```
### 客户端管理
```python
# 添加客户端
plugin.client_manager.add_client(client_id, client_info)
# 认证客户端
plugin.client_manager.authenticate_client(client_id, auth_data)
# 禁止客户端
plugin.client_manager.ban_client(client_id, reason)
```
### 消息路由
```python
# 路由消息
plugin.message_router.route_message(client_id, message)
# 发送直接消息
plugin.message_router.send_direct_message(from_client_id, to_client_id, message)
# 房间广播
plugin.message_router.broadcast_to_room(room_id, message)
```
### 房间管理
```python
# 创建房间
room_id = plugin.room_manager.create_room(room_name, settings)
# 添加客户端到房间
plugin.room_manager.add_client_to_room(room_id, client_id)
# 从房间移除客户端
plugin.room_manager.remove_client_from_room(room_id, client_id)
# 销毁房间
plugin.room_manager.destroy_room(room_id)
```
## 消息格式
### 系统消息
```json
{
"type": "ping",
"timestamp": 1234567890.123
}
```
```json
{
"type": "pong",
"timestamp": 1234567890.123,
"ping_timestamp": 1234567890.120
}
```
### 聊天消息
```json
{
"type": "chat",
"content": "Hello, world!",
"sender": "user123"
}
```
### 房间消息
```json
{
"type": "join_room",
"room_id": "room123"
}
```
```json
{
"type": "leave_room",
"room_id": "room123"
}
```
## 性能优化
1. **连接管理**:使用连接池和复用机制减少资源消耗
2. **消息压缩**:对大数据消息进行自动压缩
3. **异步处理**采用多线程和异步I/O提高并发性能
4. **缓存机制**:对频繁访问的数据进行缓存
5. **内存优化**:及时清理无用对象和连接
## 安全特性
1. **认证机制**支持Token和密码认证
2. **权限控制**:基于角色的访问控制
3. **数据加密**支持SSL/TLS传输加密
4. **防攻击**IP过滤、速率限制、防DDoS
5. **审计日志**:完整操作日志记录
## 监控和调试
### 实时监控
- CPU和内存使用率
- 网络流量统计
- 连接数和消息数
- 错误率和响应时间
### 日志系统
- 详细的操作日志
- 错误和异常记录
- 性能指标日志
- 安全审计日志
## 扩展开发
### 添加新的消息类型
```python
# 在消息路由器中注册新的处理器
plugin.message_router.register_message_handler("custom_type", custom_handler)
def custom_handler(client_id, message):
# 处理自定义消息
pass
```
### 添加新的协议
```python
# 在协议处理器中注册新的协议
plugin.protocol_handler.add_protocol_handler("custom", encode_func, decode_func)
```
### 添加事件监听器
```python
# 注册事件监听器
plugin.event_handler.register_event_handler("client_connected", on_client_connected)
def on_client_connected(payload):
# 处理客户端连接事件
pass
```
## 故障排除
### 常见问题
1. **连接失败**:检查端口是否被占用,防火墙设置
2. **认证失败**:检查认证配置和凭证
3. **性能问题**:检查系统资源使用情况,优化配置
4. **消息丢失**:检查网络连接,调整消息队列大小
### 日志分析
查看日志文件以诊断问题:
```
logs/communication_monitor.log
```
## 版本信息
- 版本1.0.0
- 作者EG Plugin System
- 许可证MIT
## 贡献指南
欢迎提交Issue和Pull Request来改进这个插件。
## 支持
如需技术支持,请联系插件维护团队或查看相关文档。

View File

@ -0,0 +1,900 @@
"""
认证管理器模块
确保通信安全
"""
import time
import hashlib
import secrets
import hmac
from typing import Dict, Any, List, Optional
class AuthManager:
"""
认证管理器
确保通信安全
"""
def __init__(self, plugin):
"""
初始化认证管理器
Args:
plugin: 实时通信插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 认证配置
self.auth_config = {
"enable_authentication": True,
"auth_timeout": 30.0,
"enable_token_auth": True,
"enable_password_auth": True,
"token_lifetime": 86400, # 24小时
"enable_session_management": True,
"session_timeout": 3600, # 1小时
"enable_two_factor_auth": False,
"max_login_attempts": 5,
"login_lockout_duration": 900, # 15分钟
"enable_ip_filtering": True,
"enable_audit_logging": True
}
# 认证状态
self.auth_state = {
"active_sessions": 0,
"total_authentications": 0,
"successful_authentications": 0,
"failed_authentications": 0
}
# 认证存储
self.sessions = {}
self.tokens = {}
self.login_attempts = {}
self.blocked_ips = {}
# 认证统计
self.auth_stats = {
"tokens_generated": 0,
"sessions_created": 0,
"sessions_expired": 0,
"users_banned": 0,
"auth_errors": 0
}
# 密钥管理
self.secret_key = self._generate_secret_key()
# 回调函数
self.auth_callbacks = {
"auth_success": [],
"auth_failed": [],
"session_created": [],
"session_expired": [],
"user_banned": [],
"auth_error": []
}
# 时间戳记录
self.last_session_cleanup = 0.0
self.last_auth_event = 0.0
print("✓ 认证管理器已创建")
def initialize(self) -> bool:
"""
初始化认证管理器
Returns:
是否初始化成功
"""
try:
print("正在初始化认证管理器...")
# 生成密钥
self.secret_key = self._generate_secret_key()
self.initialized = True
print("✓ 认证管理器初始化完成")
return True
except Exception as e:
print(f"✗ 认证管理器初始化失败: {e}")
self.auth_stats["auth_errors"] += 1
import traceback
traceback.print_exc()
return False
def _generate_secret_key(self) -> str:
"""
生成密钥
Returns:
生成的密钥
"""
try:
return secrets.token_hex(32)
except Exception as e:
print(f"✗ 密钥生成失败: {e}")
# 使用默认密钥(仅用于开发环境)
return "default_secret_key_for_development_purposes_only"
def enable(self) -> bool:
"""
启用认证管理器
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ 认证管理器未初始化")
return False
self.enabled = True
print("✓ 认证管理器已启用")
return True
except Exception as e:
print(f"✗ 认证管理器启用失败: {e}")
self.auth_stats["auth_errors"] += 1
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用认证管理器"""
try:
self.enabled = False
# 清理会话和令牌
self.sessions.clear()
self.tokens.clear()
print("✓ 认证管理器已禁用")
except Exception as e:
print(f"✗ 认证管理器禁用失败: {e}")
self.auth_stats["auth_errors"] += 1
import traceback
traceback.print_exc()
def finalize(self):
"""清理认证管理器资源"""
try:
# 禁用认证管理器
if self.enabled:
self.disable()
# 清理回调
self.auth_callbacks.clear()
self.initialized = False
print("✓ 认证管理器资源已清理")
except Exception as e:
print(f"✗ 认证管理器资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新认证管理器状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
current_time = time.time()
# 定期清理过期会话
if current_time - self.last_session_cleanup > 300: # 每5分钟清理一次
self._cleanup_expired_sessions(current_time)
self.last_session_cleanup = current_time
# 定期清理登录尝试记录
self._cleanup_login_attempts(current_time)
self.last_auth_event = current_time
except Exception as e:
print(f"✗ 认证管理器更新失败: {e}")
self.auth_stats["auth_errors"] += 1
import traceback
traceback.print_exc()
def _cleanup_expired_sessions(self, current_time: float):
"""清理过期会话"""
try:
expired_sessions = []
for session_id, session_data in self.sessions.items():
if current_time - session_data["login_time"] > self.auth_config["session_timeout"]:
expired_sessions.append(session_id)
for session_id in expired_sessions:
del self.sessions[session_id]
self.auth_state["active_sessions"] -= 1
self.auth_stats["sessions_expired"] += 1
# 触发会话过期回调
self._trigger_auth_callback("session_expired", {
"session_id": session_id,
"timestamp": current_time
})
except Exception as e:
print(f"✗ 过期会话清理失败: {e}")
self.auth_stats["auth_errors"] += 1
def _cleanup_login_attempts(self, current_time: float):
"""清理登录尝试记录"""
try:
expired_attempts = []
for ip_address, attempt_data in self.login_attempts.items():
if current_time - attempt_data["last_attempt"] > self.auth_config["login_lockout_duration"]:
expired_attempts.append(ip_address)
for ip_address in expired_attempts:
del self.login_attempts[ip_address]
except Exception as e:
print(f"✗ 登录尝试记录清理失败: {e}")
self.auth_stats["auth_errors"] += 1
def authenticate_client(self, client_id: str, auth_data: Dict[str, Any]) -> bool:
"""
认证客户端
Args:
client_id: 客户端ID
auth_data: 认证数据
Returns:
是否认证成功
"""
try:
if not self.enabled or not self.auth_config["enable_authentication"]:
# 如果未启用认证,直接通过
return True
# 检查IP是否被阻止
client_ip = auth_data.get("client_ip", "")
if self._is_ip_blocked(client_ip):
self.auth_stats["failed_authentications"] += 1
return False
# 检查登录尝试次数
if self._is_login_blocked(client_ip):
self.auth_stats["failed_authentications"] += 1
return False
# 执行认证
auth_result = self._perform_authentication(client_id, auth_data)
if auth_result:
self.auth_state["successful_authentications"] += 1
self.auth_state["total_authentications"] += 1
# 触发认证成功回调
self._trigger_auth_callback("auth_success", {
"client_id": client_id,
"auth_data": auth_data,
"timestamp": time.time()
})
# 记录审计日志
if self.auth_config["enable_audit_logging"]:
self._log_auth_event("auth_success", client_id, client_ip)
else:
self.auth_state["failed_authentications"] += 1
self.auth_state["total_authentications"] += 1
# 记录失败的登录尝试
self._record_failed_login(client_ip)
# 触发认证失败回调
self._trigger_auth_callback("auth_failed", {
"client_id": client_id,
"auth_data": auth_data,
"timestamp": time.time()
})
# 记录审计日志
if self.auth_config["enable_audit_logging"]:
self._log_auth_event("auth_failed", client_id, client_ip)
return auth_result
except Exception as e:
print(f"✗ 客户端认证失败: {e}")
self.auth_stats["auth_errors"] += 1
return False
def _is_ip_blocked(self, client_ip: str) -> bool:
"""
检查IP是否被阻止
Args:
client_ip: 客户端IP
Returns:
IP是否被阻止
"""
try:
if not self.auth_config["enable_ip_filtering"]:
return False
if client_ip in self.blocked_ips:
block_data = self.blocked_ips[client_ip]
if time.time() - block_data["block_time"] < block_data["duration"]:
return True
else:
# 阻止时间已过期,移除
del self.blocked_ips[client_ip]
return False
except Exception as e:
print(f"✗ IP阻止检查失败: {e}")
self.auth_stats["auth_errors"] += 1
return False
def _is_login_blocked(self, client_ip: str) -> bool:
"""
检查登录是否被阻止
Args:
client_ip: 客户端IP
Returns:
登录是否被阻止
"""
try:
if client_ip in self.login_attempts:
attempts = self.login_attempts[client_ip]
if (attempts["count"] >= self.auth_config["max_login_attempts"] and
time.time() - attempts["last_attempt"] < self.auth_config["login_lockout_duration"]):
return True
return False
except Exception as e:
print(f"✗ 登录阻止检查失败: {e}")
self.auth_stats["auth_errors"] += 1
return False
def _record_failed_login(self, client_ip: str):
"""
记录失败的登录尝试
Args:
client_ip: 客户端IP
"""
try:
current_time = time.time()
if client_ip not in self.login_attempts:
self.login_attempts[client_ip] = {
"count": 1,
"last_attempt": current_time
}
else:
self.login_attempts[client_ip]["count"] += 1
self.login_attempts[client_ip]["last_attempt"] = current_time
# 如果超过最大尝试次数阻止IP
if (self.login_attempts[client_ip]["count"] >=
self.auth_config["max_login_attempts"]):
self._block_ip(client_ip, self.auth_config["login_lockout_duration"])
except Exception as e:
print(f"✗ 失败登录记录失败: {e}")
self.auth_stats["auth_errors"] += 1
def _perform_authentication(self, client_id: str, auth_data: Dict[str, Any]) -> bool:
"""
执行认证
Args:
client_id: 客户端ID
auth_data: 认证数据
Returns:
是否认证成功
"""
try:
# 检查认证类型
auth_type = auth_data.get("auth_type", "token")
if auth_type == "token":
return self._authenticate_with_token(client_id, auth_data)
elif auth_type == "password":
return self._authenticate_with_password(client_id, auth_data)
elif auth_type == "session":
return self._authenticate_with_session(client_id, auth_data)
else:
# 默认认证方式
return self._authenticate_with_token(client_id, auth_data)
except Exception as e:
print(f"✗ 认证执行失败: {e}")
self.auth_stats["auth_errors"] += 1
return False
def _authenticate_with_token(self, client_id: str, auth_data: Dict[str, Any]) -> bool:
"""
使用令牌认证
Args:
client_id: 客户端ID
auth_data: 认证数据
Returns:
是否认证成功
"""
try:
token = auth_data.get("token")
if not token:
return False
# 验证令牌
if token in self.tokens:
token_data = self.tokens[token]
if time.time() - token_data["created_time"] < self.auth_config["token_lifetime"]:
# 令牌有效,创建会话
self._create_session(client_id, auth_data)
return True
else:
# 令牌过期,移除
del self.tokens[token]
return False
except Exception as e:
print(f"✗ 令牌认证失败: {e}")
self.auth_stats["auth_errors"] += 1
return False
def _authenticate_with_password(self, client_id: str, auth_data: Dict[str, Any]) -> bool:
"""
使用密码认证
Args:
client_id: 客户端ID
auth_data: 认证数据
Returns:
是否认证成功
"""
try:
username = auth_data.get("username")
password = auth_data.get("password")
if not username or not password:
return False
# 验证密码(简化实现)
# 在实际应用中,这里应该连接到用户数据库验证用户名和密码
if username == "test_user" and password == "test_password":
# 创建会话
self._create_session(client_id, auth_data)
return True
else:
return False
except Exception as e:
print(f"✗ 密码认证失败: {e}")
self.auth_stats["auth_errors"] += 1
return False
def _authenticate_with_session(self, client_id: str, auth_data: Dict[str, Any]) -> bool:
"""
使用会话认证
Args:
client_id: 客户端ID
auth_data: 认证数据
Returns:
是否认证成功
"""
try:
session_id = auth_data.get("session_id")
if not session_id:
return False
# 检查会话是否存在且有效
if session_id in self.sessions:
session_data = self.sessions[session_id]
if time.time() - session_data["login_time"] < self.auth_config["session_timeout"]:
# 更新会话最后活动时间
session_data["last_activity"] = time.time()
return True
return False
except Exception as e:
print(f"✗ 会话认证失败: {e}")
self.auth_stats["auth_errors"] += 1
return False
def _create_session(self, client_id: str, auth_data: Dict[str, Any]):
"""
创建会话
Args:
client_id: 客户端ID
auth_data: 认证数据
"""
try:
session_id = self._generate_session_id()
session_data = {
"client_id": client_id,
"login_time": time.time(),
"last_activity": time.time(),
"user_id": auth_data.get("user_id", ""),
"username": auth_data.get("username", ""),
"permissions": auth_data.get("permissions", [])
}
self.sessions[session_id] = session_data
self.auth_state["active_sessions"] += 1
self.auth_stats["sessions_created"] += 1
# 触发会话创建回调
self._trigger_auth_callback("session_created", {
"session_id": session_id,
"client_id": client_id,
"auth_data": auth_data,
"timestamp": time.time()
})
except Exception as e:
print(f"✗ 会话创建失败: {e}")
self.auth_stats["auth_errors"] += 1
def _generate_session_id(self) -> str:
"""
生成会话ID
Returns:
生成的会话ID
"""
try:
return secrets.token_urlsafe(32)
except Exception as e:
print(f"✗ 会话ID生成失败: {e}")
self.auth_stats["auth_errors"] += 1
return f"session_{int(time.time() * 1000000)}"
def generate_token(self, user_id: str, permissions: List[str] = None) -> str:
"""
生成令牌
Args:
user_id: 用户ID
permissions: 权限列表
Returns:
生成的令牌
"""
try:
token = secrets.token_urlsafe(64)
self.tokens[token] = {
"user_id": user_id,
"permissions": permissions or [],
"created_time": time.time()
}
self.auth_stats["tokens_generated"] += 1
return token
except Exception as e:
print(f"✗ 令牌生成失败: {e}")
self.auth_stats["auth_errors"] += 1
return ""
def validate_token(self, token: str) -> bool:
"""
验证令牌
Args:
token: 令牌
Returns:
令牌是否有效
"""
try:
if not token:
return False
if token in self.tokens:
token_data = self.tokens[token]
if time.time() - token_data["created_time"] < self.auth_config["token_lifetime"]:
return True
else:
# 令牌过期,移除
del self.tokens[token]
return False
except Exception as e:
print(f"✗ 令牌验证失败: {e}")
self.auth_stats["auth_errors"] += 1
return False
def hash_password(self, password: str, salt: str = None) -> Dict[str, str]:
"""
哈希密码
Args:
password: 密码
salt: 盐值可选
Returns:
包含哈希值和盐值的字典
"""
try:
if salt is None:
salt = secrets.token_hex(16)
# 使用PBKDF2哈希密码
password_hash = hashlib.pbkdf2_hmac('sha256', password.encode('utf-8'), salt.encode('utf-8'), 100000)
return {
"hash": password_hash.hex(),
"salt": salt
}
except Exception as e:
print(f"✗ 密码哈希失败: {e}")
self.auth_stats["auth_errors"] += 1
return {}
def verify_password(self, password: str, password_hash: str, salt: str) -> bool:
"""
验证密码
Args:
password: 密码
password_hash: 密码哈希值
salt: 盐值
Returns:
密码是否正确
"""
try:
# 重新哈希密码
new_hash = hashlib.pbkdf2_hmac('sha256', password.encode('utf-8'), salt.encode('utf-8'), 100000)
return hmac.compare_digest(new_hash.hex(), password_hash)
except Exception as e:
print(f"✗ 密码验证失败: {e}")
self.auth_stats["auth_errors"] += 1
return False
def _block_ip(self, client_ip: str, duration: float):
"""
阻止IP地址
Args:
client_ip: 客户端IP
duration: 阻止持续时间
"""
try:
self.blocked_ips[client_ip] = {
"block_time": time.time(),
"duration": duration
}
# 触发用户禁止回调
self._trigger_auth_callback("user_banned", {
"ip_address": client_ip,
"duration": duration,
"timestamp": time.time()
})
# 记录审计日志
if self.auth_config["enable_audit_logging"]:
self._log_auth_event("ip_blocked", None, client_ip)
print(f"✓ IP地址已被阻止: {client_ip} (持续 {duration} 秒)")
except Exception as e:
print(f"✗ IP阻止失败: {e}")
self.auth_stats["auth_errors"] += 1
def unblock_ip(self, client_ip: str) -> bool:
"""
解除IP阻止
Args:
client_ip: 客户端IP
Returns:
是否解除成功
"""
try:
if client_ip in self.blocked_ips:
del self.blocked_ips[client_ip]
print(f"✓ IP地址阻止已解除: {client_ip}")
return True
else:
print(f"✗ IP地址未被阻止: {client_ip}")
return False
except Exception as e:
print(f"✗ IP阻止解除失败: {e}")
self.auth_stats["auth_errors"] += 1
return False
def _log_auth_event(self, event_type: str, client_id: str = None, client_ip: str = None):
"""
记录认证事件
Args:
event_type: 事件类型
client_id: 客户端ID可选
client_ip: 客户端IP可选
"""
try:
if not self.auth_config["enable_audit_logging"]:
return
event = {
"event_type": event_type,
"client_id": client_id,
"client_ip": client_ip,
"timestamp": time.time()
}
# 在实际实现中,这里会将事件记录到日志文件或数据库
print(f"[认证日志] {event_type} - 客户端: {client_id}, IP: {client_ip}")
except Exception as e:
print(f"✗ 认证事件记录失败: {e}")
self.auth_stats["auth_errors"] += 1
def get_active_sessions(self) -> Dict[str, Any]:
"""
获取活跃会话
Returns:
活跃会话字典
"""
try:
return self.sessions.copy()
except Exception as e:
print(f"✗ 获取活跃会话失败: {e}")
self.auth_stats["auth_errors"] += 1
return {}
def get_blocked_ips(self) -> Dict[str, Any]:
"""
获取被阻止的IP地址
Returns:
被阻止的IP地址字典
"""
try:
return self.blocked_ips.copy()
except Exception as e:
print(f"✗ 获取被阻止的IP地址失败: {e}")
self.auth_stats["auth_errors"] += 1
return {}
def get_auth_stats(self) -> Dict[str, Any]:
"""
获取认证统计信息
Returns:
认证统计字典
"""
return {
"state": self.auth_state.copy(),
"stats": self.auth_stats.copy(),
"config": self.auth_config.copy()
}
def reset_stats(self):
"""重置认证统计信息"""
try:
self.auth_stats = {
"tokens_generated": 0,
"sessions_created": 0,
"sessions_expired": 0,
"users_banned": 0,
"auth_errors": 0
}
print("✓ 认证统计信息已重置")
except Exception as e:
print(f"✗ 认证统计信息重置失败: {e}")
def set_auth_config(self, config: Dict[str, Any]) -> bool:
"""
设置认证配置
Args:
config: 认证配置字典
Returns:
是否设置成功
"""
try:
self.auth_config.update(config)
print(f"✓ 认证配置已更新: {self.auth_config}")
return True
except Exception as e:
print(f"✗ 认证配置设置失败: {e}")
return False
def get_auth_config(self) -> Dict[str, Any]:
"""
获取认证配置
Returns:
认证配置字典
"""
return self.auth_config.copy()
def _trigger_auth_callback(self, callback_type: str, data: Dict[str, Any]):
"""
触发认证回调
Args:
callback_type: 回调类型
data: 回调数据
"""
try:
if callback_type in self.auth_callbacks:
for callback in self.auth_callbacks[callback_type]:
try:
callback(data)
except Exception as e:
print(f"✗ 认证回调执行失败: {callback_type} - {e}")
except Exception as e:
print(f"✗ 认证回调触发失败: {e}")
def register_auth_callback(self, callback_type: str, callback: callable):
"""
注册认证回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.auth_callbacks:
self.auth_callbacks[callback_type].append(callback)
print(f"✓ 认证回调已注册: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 认证回调注册失败: {e}")
def unregister_auth_callback(self, callback_type: str, callback: callable):
"""
注销认证回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.auth_callbacks:
if callback in self.auth_callbacks[callback_type]:
self.auth_callbacks[callback_type].remove(callback)
print(f"✓ 认证回调已注销: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 认证回调注销失败: {e}")

View File

@ -0,0 +1,724 @@
"""
客户端管理器模块
管理客户端连接和状态
"""
import time
import threading
import hashlib
from typing import Dict, Any, List, Optional
class ClientManager:
"""
客户端管理器
管理客户端连接和状态
"""
def __init__(self, plugin):
"""
初始化客户端管理器
Args:
plugin: 实时通信插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 客户端配置
self.client_config = {
"enable_authentication": True,
"auth_timeout": 30.0,
"max_clients": 1000,
"enable_heartbeat": True,
"heartbeat_interval": 30.0,
"enable_rate_limiting": True,
"max_messages_per_second": 100,
"enable_banning": True,
"ban_duration": 3600,
"client_timeout": 60.0
}
# 客户端状态
self.client_state = {
"current_clients": 0,
"total_clients": 0,
"authenticated_clients": 0,
"banned_clients": 0
}
# 客户端存储
self.clients = {}
self.client_lock = threading.RLock()
# 客户端统计
self.client_stats = {
"clients_joined": 0,
"clients_left": 0,
"authentication_success": 0,
"authentication_failed": 0,
"messages_sent": 0,
"messages_received": 0,
"banned_clients": 0,
"errors": 0
}
# 黑名单管理
self.banned_ips = {}
self.banned_users = {}
# 回调函数
self.client_callbacks = {
"client_joined": [],
"client_left": [],
"client_authenticated": [],
"client_banned": [],
"client_error": []
}
# 时间戳记录
self.last_heartbeat_check = 0.0
self.last_cleanup = 0.0
print("✓ 客户端管理器已创建")
def initialize(self) -> bool:
"""
初始化客户端管理器
Returns:
是否初始化成功
"""
try:
print("正在初始化客户端管理器...")
self.initialized = True
print("✓ 客户端管理器初始化完成")
return True
except Exception as e:
print(f"✗ 客户端管理器初始化失败: {e}")
self.client_stats["errors"] += 1
import traceback
traceback.print_exc()
return False
def enable(self) -> bool:
"""
启用客户端管理器
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ 客户端管理器未初始化")
return False
self.enabled = True
print("✓ 客户端管理器已启用")
return True
except Exception as e:
print(f"✗ 客户端管理器启用失败: {e}")
self.client_stats["errors"] += 1
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用客户端管理器"""
try:
self.enabled = False
# 断开所有客户端
self._disconnect_all_clients()
print("✓ 客户端管理器已禁用")
except Exception as e:
print(f"✗ 客户端管理器禁用失败: {e}")
self.client_stats["errors"] += 1
import traceback
traceback.print_exc()
def finalize(self):
"""清理客户端管理器资源"""
try:
# 禁用客户端管理器
if self.enabled:
self.disable()
# 清理回调
self.client_callbacks.clear()
self.initialized = False
print("✓ 客户端管理器资源已清理")
except Exception as e:
print(f"✗ 客户端管理器资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新客户端管理器状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
current_time = time.time()
# 定期检查心跳
if current_time - self.last_heartbeat_check > self.client_config["heartbeat_interval"]:
self._check_client_heartbeats(current_time)
self.last_heartbeat_check = current_time
# 定期清理
if current_time - self.last_cleanup > 60.0: # 每分钟清理一次
self._cleanup_banned_clients(current_time)
self.last_cleanup = current_time
except Exception as e:
print(f"✗ 客户端管理器更新失败: {e}")
self.client_stats["errors"] += 1
import traceback
traceback.print_exc()
def _check_client_heartbeats(self, current_time: float):
"""检查客户端心跳"""
try:
if not self.client_config["enable_heartbeat"]:
return
clients_to_disconnect = []
with self.client_lock:
for client_id, client_data in self.clients.items():
last_heartbeat = client_data.get("last_heartbeat", client_data["connect_time"])
if current_time - last_heartbeat > self.client_config["client_timeout"]:
clients_to_disconnect.append(client_id)
for client_id in clients_to_disconnect:
self.disconnect_client(client_id, "timeout")
except Exception as e:
print(f"✗ 客户端心跳检查失败: {e}")
self.client_stats["errors"] += 1
def _cleanup_banned_clients(self, current_time: float):
"""清理过期的黑名单客户端"""
try:
expired_bans = []
for ip, ban_data in self.banned_ips.items():
if current_time - ban_data["ban_time"] > self.client_config["ban_duration"]:
expired_bans.append(ip)
for ip in expired_bans:
del self.banned_ips[ip]
self.client_state["banned_clients"] -= 1
except Exception as e:
print(f"✗ 黑名单清理失败: {e}")
self.client_stats["errors"] += 1
def _disconnect_all_clients(self):
"""断开所有客户端连接"""
try:
with self.client_lock:
client_ids = list(self.clients.keys())
for client_id in client_ids:
self.disconnect_client(client_id, "server_shutdown")
except Exception as e:
print(f"✗ 断开所有客户端连接失败: {e}")
self.client_stats["errors"] += 1
def add_client(self, client_id: str, client_info: Dict[str, Any]) -> bool:
"""
添加客户端
Args:
client_id: 客户端ID
client_info: 客户端信息
Returns:
是否添加成功
"""
try:
if not self.enabled:
return False
# 检查客户端数量限制
with self.client_lock:
if len(self.clients) >= self.client_config["max_clients"]:
print("✗ 客户端数量已达上限")
return False
# 检查IP是否被禁止
client_ip = client_info.get("ip_address", "")
if self._is_ip_banned(client_ip):
print(f"✗ IP地址被禁止: {client_ip}")
return False
# 添加客户端
client_data = {
"client_id": client_id,
"client_info": client_info,
"connect_time": time.time(),
"last_heartbeat": time.time(),
"is_authenticated": False,
"user_id": "",
"username": "",
"permissions": [],
"messages_sent": 0,
"messages_received": 0,
"bytes_sent": 0,
"bytes_received": 0
}
with self.client_lock:
self.clients[client_id] = client_data
self.client_state["current_clients"] = len(self.clients)
self.client_state["total_clients"] += 1
self.client_stats["clients_joined"] += 1
# 触发客户端加入回调
self._trigger_client_callback("client_joined", {
"client_id": client_id,
"client_info": client_info,
"timestamp": time.time()
})
print(f"✓ 客户端已添加: {client_id}")
return True
except Exception as e:
print(f"✗ 添加客户端失败: {e}")
self.client_stats["errors"] += 1
return False
def remove_client(self, client_id: str, reason: str = "unknown") -> bool:
"""
移除客户端
Args:
client_id: 客户端ID
reason: 移除原因
Returns:
是否移除成功
"""
try:
with self.client_lock:
if client_id in self.clients:
client_data = self.clients[client_id]
if client_data["is_authenticated"]:
self.client_state["authenticated_clients"] -= 1
del self.clients[client_id]
self.client_state["current_clients"] = len(self.clients)
self.client_stats["clients_left"] += 1
# 触发客户端离开回调
self._trigger_client_callback("client_left", {
"client_id": client_id,
"reason": reason,
"timestamp": time.time()
})
print(f"✓ 客户端已移除: {client_id} (原因: {reason})")
return True
except Exception as e:
print(f"✗ 移除客户端失败: {e}")
self.client_stats["errors"] += 1
return False
def disconnect_client(self, client_id: str, reason: str = "kicked") -> bool:
"""
断开客户端连接
Args:
client_id: 客户端ID
reason: 断开原因
Returns:
是否断开成功
"""
try:
# 通知WebSocket服务器断开连接
if self.plugin.websocket_server:
self.plugin.websocket_server.disconnect_client(client_id, reason)
# 移除客户端
return self.remove_client(client_id, reason)
except Exception as e:
print(f"✗ 断开客户端连接失败: {e}")
self.client_stats["errors"] += 1
return False
def authenticate_client(self, client_id: str, auth_data: Dict[str, Any]) -> bool:
"""
认证客户端
Args:
client_id: 客户端ID
auth_data: 认证数据
Returns:
是否认证成功
"""
try:
if not self.enabled or not self.client_config["enable_authentication"]:
# 如果未启用认证,直接通过
with self.client_lock:
if client_id in self.clients:
self.clients[client_id]["is_authenticated"] = True
return True
# 使用认证管理器进行认证
if self.plugin.auth_manager:
auth_result = self.plugin.auth_manager.authenticate_client(client_id, auth_data)
if auth_result:
# 更新客户端认证状态
with self.client_lock:
if client_id in self.clients:
self.clients[client_id]["is_authenticated"] = True
self.clients[client_id]["user_id"] = auth_data.get("user_id", "")
self.clients[client_id]["username"] = auth_data.get("username", "")
self.clients[client_id]["permissions"] = auth_data.get("permissions", [])
self.client_state["authenticated_clients"] += 1
self.client_stats["authentication_success"] += 1
# 触发客户端认证回调
self._trigger_client_callback("client_authenticated", {
"client_id": client_id,
"user_id": auth_data.get("user_id", ""),
"username": auth_data.get("username", ""),
"timestamp": time.time()
})
print(f"✓ 客户端认证成功: {client_id}")
return True
else:
self.client_stats["authentication_failed"] += 1
print(f"✗ 客户端认证失败: {client_id}")
return False
else:
print("✗ 认证管理器不可用")
return False
except Exception as e:
print(f"✗ 客户端认证失败: {e}")
self.client_stats["errors"] += 1
return False
def update_client_heartbeat(self, client_id: str) -> bool:
"""
更新客户端心跳
Args:
client_id: 客户端ID
Returns:
是否更新成功
"""
try:
with self.client_lock:
if client_id in self.clients:
self.clients[client_id]["last_heartbeat"] = time.time()
return True
else:
return False
except Exception as e:
print(f"✗ 更新客户端心跳失败: {e}")
self.client_stats["errors"] += 1
return False
def get_client(self, client_id: str) -> Optional[Dict[str, Any]]:
"""
获取客户端信息
Args:
client_id: 客户端ID
Returns:
客户端信息或None
"""
try:
with self.client_lock:
if client_id in self.clients:
return self.clients[client_id].copy()
else:
return None
except Exception as e:
print(f"✗ 获取客户端信息失败: {e}")
self.client_stats["errors"] += 1
return None
def get_all_clients(self) -> Dict[str, Any]:
"""
获取所有客户端信息
Returns:
所有客户端信息字典
"""
try:
with self.client_lock:
return {k: v.copy() for k, v in self.clients.items()}
except Exception as e:
print(f"✗ 获取所有客户端信息失败: {e}")
self.client_stats["errors"] += 1
return {}
def ban_client(self, client_id: str, reason: str = "violation", duration: float = 3600) -> bool:
"""
禁止客户端
Args:
client_id: 客户端ID
reason: 禁止原因
duration: 禁止时长
Returns:
是否禁止成功
"""
try:
if not self.client_config["enable_banning"]:
return False
client_data = self.get_client(client_id)
if not client_data:
return False
client_ip = client_data["client_info"].get("ip_address", "")
if client_ip:
# 添加到IP黑名单
self.banned_ips[client_ip] = {
"client_id": client_id,
"ban_time": time.time(),
"reason": reason,
"duration": duration
}
self.client_state["banned_clients"] += 1
self.client_stats["banned_clients"] += 1
# 断开客户端连接
self.disconnect_client(client_id, f"banned: {reason}")
# 触发客户端禁止回调
self._trigger_client_callback("client_banned", {
"client_id": client_id,
"ip_address": client_ip,
"reason": reason,
"duration": duration,
"timestamp": time.time()
})
print(f"✓ 客户端已被禁止: {client_id} (IP: {client_ip})")
return True
else:
return False
except Exception as e:
print(f"✗ 禁止客户端失败: {e}")
self.client_stats["errors"] += 1
return False
def _is_ip_banned(self, ip_address: str) -> bool:
"""
检查IP是否被禁止
Args:
ip_address: IP地址
Returns:
IP是否被禁止
"""
try:
if not self.client_config["enable_banning"]:
return False
if ip_address in self.banned_ips:
ban_data = self.banned_ips[ip_address]
if time.time() - ban_data["ban_time"] < ban_data["duration"]:
return True
else:
# 禁止时间已过期,移除
del self.banned_ips[ip_address]
self.client_state["banned_clients"] -= 1
return False
except Exception as e:
print(f"✗ IP禁止检查失败: {e}")
self.client_stats["errors"] += 1
return False
def unban_ip(self, ip_address: str) -> bool:
"""
解除IP禁止
Args:
ip_address: IP地址
Returns:
是否解除成功
"""
try:
if ip_address in self.banned_ips:
del self.banned_ips[ip_address]
self.client_state["banned_clients"] -= 1
print(f"✓ IP禁止已解除: {ip_address}")
return True
else:
print(f"✗ IP未被禁止: {ip_address}")
return False
except Exception as e:
print(f"✗ 解除IP禁止失败: {e}")
self.client_stats["errors"] += 1
return False
def is_client_authenticated(self, client_id: str) -> bool:
"""
检查客户端是否已认证
Args:
client_id: 客户端ID
Returns:
客户端是否已认证
"""
try:
with self.client_lock:
if client_id in self.clients:
return self.clients[client_id]["is_authenticated"]
else:
return False
except Exception as e:
print(f"✗ 客户端认证检查失败: {e}")
self.client_stats["errors"] += 1
return False
def get_client_stats(self) -> Dict[str, Any]:
"""
获取客户端统计信息
Returns:
客户端统计字典
"""
return {
"state": self.client_state.copy(),
"stats": self.client_stats.copy(),
"config": self.client_config.copy()
}
def reset_stats(self):
"""重置客户端统计信息"""
try:
self.client_stats = {
"clients_joined": 0,
"clients_left": 0,
"authentication_success": 0,
"authentication_failed": 0,
"messages_sent": 0,
"messages_received": 0,
"banned_clients": 0,
"errors": 0
}
print("✓ 客户端统计信息已重置")
except Exception as e:
print(f"✗ 客户端统计信息重置失败: {e}")
def set_client_config(self, config: Dict[str, Any]) -> bool:
"""
设置客户端配置
Args:
config: 客户端配置字典
Returns:
是否设置成功
"""
try:
self.client_config.update(config)
print(f"✓ 客户端配置已更新: {self.client_config}")
return True
except Exception as e:
print(f"✗ 客户端配置设置失败: {e}")
return False
def get_client_config(self) -> Dict[str, Any]:
"""
获取客户端配置
Returns:
客户端配置字典
"""
return self.client_config.copy()
def _trigger_client_callback(self, callback_type: str, data: Dict[str, Any]):
"""
触发客户端回调
Args:
callback_type: 回调类型
data: 回调数据
"""
try:
if callback_type in self.client_callbacks:
for callback in self.client_callbacks[callback_type]:
try:
callback(data)
except Exception as e:
print(f"✗ 客户端回调执行失败: {callback_type} - {e}")
except Exception as e:
print(f"✗ 客户端回调触发失败: {e}")
def register_client_callback(self, callback_type: str, callback: callable):
"""
注册客户端回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.client_callbacks:
self.client_callbacks[callback_type].append(callback)
print(f"✓ 客户端回调已注册: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 客户端回调注册失败: {e}")
def unregister_client_callback(self, callback_type: str, callback: callable):
"""
注销客户端回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.client_callbacks:
if callback in self.client_callbacks[callback_type]:
self.client_callbacks[callback_type].remove(callback)
print(f"✓ 客户端回调已注销: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 客户端回调注销失败: {e}")

View File

@ -0,0 +1,759 @@
"""
通信配置管理器模块
管理通信配置和用户偏好
"""
import time
import json
import os
from typing import Dict, Any, List, Optional
class CommConfig:
"""
通信配置管理器
管理通信配置和用户偏好
"""
def __init__(self, plugin):
"""
初始化通信配置管理器
Args:
plugin: 实时通信插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 配置文件路径
self.config_file_path = "/home/hello/EG/plugins/user/realtime_communication/config/communication_config.json"
# 默认配置
self.default_config = {
"server": {
"host": "0.0.0.0",
"port": 8080,
"enable_ssl": False,
"ssl_cert_file": "",
"ssl_key_file": "",
"max_connections": 1000,
"connection_timeout": 30.0,
"ping_interval": 30.0
},
"client": {
"enable_authentication": True,
"auth_timeout": 30.0,
"max_clients": 1000,
"enable_heartbeat": True,
"heartbeat_interval": 30.0,
"enable_rate_limiting": True,
"max_messages_per_second": 100,
"enable_banning": True,
"ban_duration": 3600
},
"message": {
"enable_message_filtering": True,
"max_message_size": 65536,
"enable_message_queue": True,
"message_queue_size": 10000,
"enable_message_compression": True,
"compression_threshold": 1024
},
"room": {
"max_rooms": 1000,
"max_clients_per_room": 100,
"enable_room_persistence": False,
"room_timeout": 3600,
"enable_room_passwords": True
},
"protocol": {
"supported_protocols": ["websocket", "json", "binary"],
"default_protocol": "json",
"enable_compression": True,
"compression_threshold": 1024,
"enable_encryption": False,
"max_message_size": 65536
},
"auth": {
"enable_authentication": True,
"auth_timeout": 30.0,
"enable_token_auth": True,
"enable_password_auth": True,
"token_lifetime": 86400,
"enable_session_management": True,
"session_timeout": 3600,
"max_login_attempts": 5,
"login_lockout_duration": 900
},
"serialization": {
"default_format": "json",
"supported_formats": ["json", "pickle", "binary"],
"enable_compression": True,
"compression_threshold": 1024,
"enable_caching": True,
"cache_size": 1000
},
"monitoring": {
"enable_monitoring": True,
"monitoring_interval": 5.0,
"log_level": "INFO",
"enable_file_logging": True,
"log_file_path": "/home/hello/EG/plugins/user/realtime_communication/logs/communication_monitor.log"
},
"events": {
"enable_event_system": True,
"max_event_queue_size": 10000,
"enable_event_filtering": True
}
}
# 当前配置
self.current_config = self.default_config.copy()
# 配置状态
self.config_state = {
"last_loaded": 0.0,
"last_saved": 0.0,
"config_version": "1.0.0",
"is_dirty": False
}
# 配置统计
self.config_stats = {
"loads": 0,
"saves": 0,
"updates": 0,
"config_errors": 0
}
# 配置监听器
self.config_listeners = {}
# 回调函数
self.config_callbacks = {
"config_loaded": [],
"config_saved": [],
"config_updated": [],
"config_error": []
}
print("✓ 通信配置管理器已创建")
def initialize(self) -> bool:
"""
初始化通信配置管理器
Returns:
是否初始化成功
"""
try:
print("正在初始化通信配置管理器...")
# 创建配置目录
config_dir = os.path.dirname(self.config_file_path)
if not os.path.exists(config_dir):
os.makedirs(config_dir)
# 创建日志目录
if "monitoring" in self.default_config:
log_dir = os.path.dirname(self.default_config["monitoring"]["log_file_path"])
if not os.path.exists(log_dir):
os.makedirs(log_dir)
# 加载配置
self.load_config()
self.initialized = True
print("✓ 通信配置管理器初始化完成")
return True
except Exception as e:
print(f"✗ 通信配置管理器初始化失败: {e}")
self.config_stats["config_errors"] += 1
import traceback
traceback.print_exc()
return False
def enable(self) -> bool:
"""
启用通信配置管理器
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ 通信配置管理器未初始化")
return False
self.enabled = True
print("✓ 通信配置管理器已启用")
return True
except Exception as e:
print(f"✗ 通信配置管理器启用失败: {e}")
self.config_stats["config_errors"] += 1
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用通信配置管理器"""
try:
self.enabled = False
# 保存配置(如果有更改)
if self.config_state["is_dirty"]:
self.save_config()
print("✓ 通信配置管理器已禁用")
except Exception as e:
print(f"✗ 通信配置管理器禁用失败: {e}")
self.config_stats["config_errors"] += 1
import traceback
traceback.print_exc()
def finalize(self):
"""清理通信配置管理器资源"""
try:
# 禁用通信配置管理器
if self.enabled:
self.disable()
# 清理回调
self.config_callbacks.clear()
self.config_listeners.clear()
self.initialized = False
print("✓ 通信配置管理器资源已清理")
except Exception as e:
print(f"✗ 通信配置管理器资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新通信配置管理器状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
# 检查配置文件是否被外部修改
self._check_config_file_changes()
except Exception as e:
print(f"✗ 通信配置管理器更新失败: {e}")
self.config_stats["config_errors"] += 1
import traceback
traceback.print_exc()
def _check_config_file_changes(self):
"""检查配置文件是否被外部修改"""
try:
if not os.path.exists(self.config_file_path):
return
last_modified = os.path.getmtime(self.config_file_path)
if last_modified > self.config_state["last_loaded"]:
# 配置文件已被修改,重新加载
print("检测到配置文件被外部修改,正在重新加载...")
self.load_config()
except Exception as e:
print(f"✗ 配置文件变更检查失败: {e}")
self.config_stats["config_errors"] += 1
def load_config(self) -> bool:
"""
加载配置
Returns:
是否加载成功
"""
try:
# 检查配置文件是否存在
if os.path.exists(self.config_file_path):
with open(self.config_file_path, 'r', encoding='utf-8') as f:
loaded_config = json.load(f)
# 合并配置(使用默认配置作为基础)
self.current_config = self._merge_config(self.default_config, loaded_config)
print(f"✓ 配置已从文件加载: {self.config_file_path}")
else:
# 使用默认配置
self.current_config = self.default_config.copy()
print("✓ 使用默认配置")
self.config_state["last_loaded"] = time.time()
self.config_state["is_dirty"] = False
self.config_stats["loads"] += 1
# 触发配置加载回调
self._trigger_config_callback("config_loaded", {
"config": self.current_config,
"timestamp": self.config_state["last_loaded"]
})
return True
except Exception as e:
print(f"✗ 配置加载失败: {e}")
self.config_stats["config_errors"] += 1
# 使用默认配置
self.current_config = self.default_config.copy()
return False
def _merge_config(self, base_config: Dict[str, Any], override_config: Dict[str, Any]) -> Dict[str, Any]:
"""
合并配置递归
Args:
base_config: 基础配置
override_config: 覆盖配置
Returns:
合并后的配置
"""
try:
merged = base_config.copy()
for key, value in override_config.items():
if key in merged and isinstance(merged[key], dict) and isinstance(value, dict):
# 递归合并嵌套字典
merged[key] = self._merge_config(merged[key], value)
else:
# 直接覆盖
merged[key] = value
return merged
except Exception as e:
print(f"✗ 配置合并失败: {e}")
self.config_stats["config_errors"] += 1
return base_config
def save_config(self) -> bool:
"""
保存配置
Returns:
是否保存成功
"""
try:
# 创建配置目录(如果不存在)
config_dir = os.path.dirname(self.config_file_path)
if not os.path.exists(config_dir):
os.makedirs(config_dir)
# 保存配置到文件
with open(self.config_file_path, 'w', encoding='utf-8') as f:
json.dump(self.current_config, f, indent=2, ensure_ascii=False)
self.config_state["last_saved"] = time.time()
self.config_state["is_dirty"] = False
self.config_stats["saves"] += 1
# 触发配置保存回调
self._trigger_config_callback("config_saved", {
"config": self.current_config,
"timestamp": self.config_state["last_saved"]
})
print(f"✓ 配置已保存到文件: {self.config_file_path}")
return True
except Exception as e:
print(f"✗ 配置保存失败: {e}")
self.config_stats["config_errors"] += 1
return False
def get_config(self, section: str = None, key: str = None, default_value: Any = None) -> Any:
"""
获取配置值
Args:
section: 配置节可选
key: 配置键可选
default_value: 默认值
Returns:
配置值
"""
try:
if section is None:
return self.current_config.copy()
if section not in self.current_config:
return default_value
if key is None:
return self.current_config[section].copy()
if key not in self.current_config[section]:
return default_value
return self.current_config[section][key]
except Exception as e:
print(f"✗ 获取配置失败: {e}")
self.config_stats["config_errors"] += 1
return default_value
def set_config(self, section: str, key: str, value: Any) -> bool:
"""
设置配置值
Args:
section: 配置节
key: 配置键
value: 配置值
Returns:
是否设置成功
"""
try:
if section not in self.current_config:
self.current_config[section] = {}
self.current_config[section][key] = value
self.config_state["is_dirty"] = True
self.config_stats["updates"] += 1
# 通知配置监听器
self._notify_config_listeners(section, key, value)
# 触发配置更新回调
self._trigger_config_callback("config_updated", {
"section": section,
"key": key,
"value": value,
"timestamp": time.time()
})
return True
except Exception as e:
print(f"✗ 设置配置失败: {e}")
self.config_stats["config_errors"] += 1
return False
def update_config_section(self, section: str, config_data: Dict[str, Any]) -> bool:
"""
更新配置节
Args:
section: 配置节
config_data: 配置数据
Returns:
是否更新成功
"""
try:
if section not in self.current_config:
self.current_config[section] = {}
self.current_config[section].update(config_data)
self.config_state["is_dirty"] = True
self.config_stats["updates"] += 1
# 通知配置监听器
for key, value in config_data.items():
self._notify_config_listeners(section, key, value)
# 触发配置更新回调
self._trigger_config_callback("config_updated", {
"section": section,
"config_data": config_data,
"timestamp": time.time()
})
return True
except Exception as e:
print(f"✗ 更新配置节失败: {e}")
self.config_stats["config_errors"] += 1
return False
def reset_config(self) -> bool:
"""
重置配置为默认值
Returns:
是否重置成功
"""
try:
self.current_config = self.default_config.copy()
self.config_state["is_dirty"] = True
# 通知所有配置监听器
for section_name, section_data in self.current_config.items():
if isinstance(section_data, dict):
for key, value in section_data.items():
self._notify_config_listeners(section_name, key, value)
print("✓ 配置已重置为默认值")
return True
except Exception as e:
print(f"✗ 配置重置失败: {e}")
self.config_stats["config_errors"] += 1
return False
def register_config_listener(self, section: str, key: str, listener: callable):
"""
注册配置监听器
Args:
section: 配置节
key: 配置键
listener: 监听器函数
"""
try:
listener_key = f"{section}.{key}"
if listener_key not in self.config_listeners:
self.config_listeners[listener_key] = []
self.config_listeners[listener_key].append(listener)
print(f"✓ 配置监听器已注册: {listener_key}")
except Exception as e:
print(f"✗ 配置监听器注册失败: {e}")
self.config_stats["config_errors"] += 1
def unregister_config_listener(self, section: str, key: str, listener: callable):
"""
注销配置监听器
Args:
section: 配置节
key: 配置键
listener: 监听器函数
"""
try:
listener_key = f"{section}.{key}"
if listener_key in self.config_listeners:
if listener in self.config_listeners[listener_key]:
self.config_listeners[listener_key].remove(listener)
print(f"✓ 配置监听器已注销: {listener_key}")
except Exception as e:
print(f"✗ 配置监听器注销失败: {e}")
self.config_stats["config_errors"] += 1
def _notify_config_listeners(self, section: str, key: str, value: Any):
"""
通知配置监听器
Args:
section: 配置节
key: 配置键
value: 配置值
"""
try:
listener_key = f"{section}.{key}"
if listener_key in self.config_listeners:
for listener in self.config_listeners[listener_key]:
try:
listener(section, key, value)
except Exception as e:
print(f"✗ 配置监听器执行失败: {listener_key} - {e}")
except Exception as e:
print(f"✗ 配置监听器通知失败: {e}")
self.config_stats["config_errors"] += 1
def get_config_stats(self) -> Dict[str, Any]:
"""
获取配置统计信息
Returns:
配置统计字典
"""
return {
"state": self.config_state.copy(),
"stats": self.config_stats.copy(),
"config_sections": list(self.current_config.keys())
}
def reset_stats(self):
"""重置配置统计信息"""
try:
self.config_stats = {
"loads": 0,
"saves": 0,
"updates": 0,
"config_errors": 0
}
print("✓ 配置统计信息已重置")
except Exception as e:
print(f"✗ 配置统计信息重置失败: {e}")
def validate_config(self) -> bool:
"""
验证配置
Returns:
配置是否有效
"""
try:
# 检查必需的配置项
required_sections = ["server", "client", "message", "room", "protocol", "auth", "serialization"]
for section in required_sections:
if section not in self.current_config:
print(f"✗ 缺少必需的配置节: {section}")
return False
# 检查服务器配置
server_config = self.current_config["server"]
if "port" not in server_config or not isinstance(server_config["port"], int):
print("✗ 无效的服务器端口配置")
return False
if "max_connections" not in server_config or not isinstance(server_config["max_connections"], int):
print("✗ 无效的最大连接数配置")
return False
# 检查客户端配置
client_config = self.current_config["client"]
if "max_clients" not in client_config or not isinstance(client_config["max_clients"], int):
print("✗ 无效的最大客户端数配置")
return False
print("✓ 配置验证通过")
return True
except Exception as e:
print(f"✗ 配置验证失败: {e}")
self.config_stats["config_errors"] += 1
return False
def export_config(self, file_path: str) -> bool:
"""
导出配置到文件
Args:
file_path: 导出文件路径
Returns:
是否导出成功
"""
try:
# 创建导出目录
export_dir = os.path.dirname(file_path)
if not os.path.exists(export_dir):
os.makedirs(export_dir)
# 导出配置
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(self.current_config, f, indent=2, ensure_ascii=False)
print(f"✓ 配置已导出到: {file_path}")
return True
except Exception as e:
print(f"✗ 配置导出失败: {e}")
self.config_stats["config_errors"] += 1
return False
def import_config(self, file_path: str) -> bool:
"""
从文件导入配置
Args:
file_path: 导入文件路径
Returns:
是否导入成功
"""
try:
if not os.path.exists(file_path):
print(f"✗ 配置文件不存在: {file_path}")
return False
# 读取配置文件
with open(file_path, 'r', encoding='utf-8') as f:
imported_config = json.load(f)
# 验证配置
if not isinstance(imported_config, dict):
print("✗ 无效的配置文件格式")
return False
# 合并配置
self.current_config = self._merge_config(self.default_config, imported_config)
self.config_state["is_dirty"] = True
# 通知配置监听器
for section_name, section_data in self.current_config.items():
if isinstance(section_data, dict):
for key, value in section_data.items():
self._notify_config_listeners(section_name, key, value)
print(f"✓ 配置已从文件导入: {file_path}")
return True
except Exception as e:
print(f"✗ 配置导入失败: {e}")
self.config_stats["config_errors"] += 1
return False
def _trigger_config_callback(self, callback_type: str, data: Dict[str, Any]):
"""
触发配置回调
Args:
callback_type: 回调类型
data: 回调数据
"""
try:
if callback_type in self.config_callbacks:
for callback in self.config_callbacks[callback_type]:
try:
callback(data)
except Exception as e:
print(f"✗ 配置回调执行失败: {callback_type} - {e}")
except Exception as e:
print(f"✗ 配置回调触发失败: {e}")
def register_config_callback(self, callback_type: str, callback: callable):
"""
注册配置回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.config_callbacks:
self.config_callbacks[callback_type].append(callback)
print(f"✓ 配置回调已注册: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 配置回调注册失败: {e}")
def unregister_config_callback(self, callback_type: str, callback: callable):
"""
注销配置回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.config_callbacks:
if callback in self.config_callbacks[callback_type]:
self.config_callbacks[callback_type].remove(callback)
print(f"✓ 配置回调已注销: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 配置回调注销失败: {e}")

View File

@ -0,0 +1,698 @@
"""
WebSocket服务器模块
处理实时双向通信连接
"""
import time
import threading
import json
import base64
from typing import Dict, Any, List, Optional
class WebSocketServer:
"""
WebSocket服务器
处理实时双向通信连接
"""
def __init__(self, plugin):
"""
初始化WebSocket服务器
Args:
plugin: 实时通信插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# WebSocket配置
self.websocket_config = {
"host": "0.0.0.0",
"port": 8080,
"enable_ssl": False,
"ssl_cert_file": "",
"ssl_key_file": "",
"max_connections": 1000,
"enable_compression": True,
"ping_interval": 30.0,
"ping_timeout": 10.0,
"message_queue_size": 1000,
"enable_cors": True
}
# WebSocket服务器状态
self.server_state = {
"is_running": False,
"start_time": 0.0,
"uptime": 0.0,
"current_connections": 0,
"total_connections": 0,
"bytes_sent": 0,
"bytes_received": 0
}
# WebSocket服务器统计
self.server_stats = {
"messages_sent": 0,
"messages_received": 0,
"connections_accepted": 0,
"connections_dropped": 0,
"errors": 0
}
# 连接存储
self.connections = {}
self.connection_lock = threading.RLock()
# 消息队列
self.message_queue = []
self.message_queue_lock = threading.RLock()
# 服务器线程
self.server_thread = None
self.server_thread_running = False
# 回调函数
self.websocket_callbacks = {
"server_started": [],
"server_stopped": [],
"client_connected": [],
"client_disconnected": [],
"message_received": [],
"websocket_error": []
}
# 时间戳记录
self.last_ping_time = 0.0
self.last_message_time = 0.0
print("✓ WebSocket服务器已创建")
def initialize(self) -> bool:
"""
初始化WebSocket服务器
Returns:
是否初始化成功
"""
try:
print("正在初始化WebSocket服务器...")
self.initialized = True
print("✓ WebSocket服务器初始化完成")
return True
except Exception as e:
print(f"✗ WebSocket服务器初始化失败: {e}")
self.server_stats["errors"] += 1
import traceback
traceback.print_exc()
return False
def enable(self) -> bool:
"""
启用WebSocket服务器
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ WebSocket服务器未初始化")
return False
# 启动WebSocket服务器
self._start_websocket_server()
self.enabled = True
print("✓ WebSocket服务器已启用")
return True
except Exception as e:
print(f"✗ WebSocket服务器启用失败: {e}")
self.server_stats["errors"] += 1
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用WebSocket服务器"""
try:
self.enabled = False
# 停止WebSocket服务器
self._stop_websocket_server()
print("✓ WebSocket服务器已禁用")
except Exception as e:
print(f"✗ WebSocket服务器禁用失败: {e}")
self.server_stats["errors"] += 1
import traceback
traceback.print_exc()
def finalize(self):
"""清理WebSocket服务器资源"""
try:
# 禁用WebSocket服务器
if self.enabled:
self.disable()
# 清理回调
self.websocket_callbacks.clear()
self.initialized = False
print("✓ WebSocket服务器资源已清理")
except Exception as e:
print(f"✗ WebSocket服务器资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新WebSocket服务器状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
current_time = time.time()
# 更新运行时间
if self.server_state["is_running"]:
self.server_state["uptime"] = current_time - self.server_state["start_time"]
# 处理消息队列
self._process_message_queue()
# 发送心跳
if current_time - self.last_ping_time > self.websocket_config["ping_interval"]:
self._send_ping_to_all_clients()
self.last_ping_time = current_time
self.last_message_time = current_time
except Exception as e:
print(f"✗ WebSocket服务器更新失败: {e}")
self.server_stats["errors"] += 1
import traceback
traceback.print_exc()
def _start_websocket_server(self):
"""启动WebSocket服务器"""
try:
if self.server_state["is_running"]:
return
# 在实际实现中这里会启动一个WebSocket服务器
# 由于这是一个示例,我们模拟服务器启动过程
self.server_state["is_running"] = True
self.server_state["start_time"] = time.time()
# 触发服务器启动回调
self._trigger_websocket_callback("server_started", {
"host": self.websocket_config["host"],
"port": self.websocket_config["port"],
"timestamp": self.server_state["start_time"]
})
print(f"✓ WebSocket服务器已启动: ws://{self.websocket_config['host']}:{self.websocket_config['port']}")
except Exception as e:
print(f"✗ WebSocket服务器启动失败: {e}")
self.server_stats["errors"] += 1
def _stop_websocket_server(self):
"""停止WebSocket服务器"""
try:
if not self.server_state["is_running"]:
return
# 断开所有客户端连接
self._disconnect_all_clients()
self.server_state["is_running"] = False
self.server_state["start_time"] = 0.0
self.server_state["uptime"] = 0.0
# 触发服务器停止回调
self._trigger_websocket_callback("server_stopped", {
"timestamp": time.time()
})
print("✓ WebSocket服务器已停止")
except Exception as e:
print(f"✗ WebSocket服务器停止失败: {e}")
self.server_stats["errors"] += 1
def _process_message_queue(self):
"""处理消息队列"""
try:
if not self.message_queue:
return
with self.message_queue_lock:
messages_to_process = self.message_queue[:]
self.message_queue.clear()
for message_data in messages_to_process:
try:
client_id = message_data.get("client_id")
message = message_data.get("message")
# 处理消息
self._handle_incoming_message(client_id, message)
except Exception as e:
print(f"✗ 消息处理失败: {e}")
self.server_stats["errors"] += 1
except Exception as e:
print(f"✗ 消息队列处理失败: {e}")
self.server_stats["errors"] += 1
def _handle_incoming_message(self, client_id: str, message: Dict[str, Any]):
"""
处理传入消息
Args:
client_id: 客户端ID
message: 消息数据
"""
try:
self.server_stats["messages_received"] += 1
# 触发消息接收回调
self._trigger_websocket_callback("message_received", {
"client_id": client_id,
"message": message,
"timestamp": time.time()
})
# 将消息传递给消息路由器处理
if self.plugin.message_router:
self.plugin.message_router.route_message(client_id, message)
except Exception as e:
print(f"✗ 传入消息处理失败: {e}")
self.server_stats["errors"] += 1
def _send_ping_to_all_clients(self):
"""向所有客户端发送心跳"""
try:
ping_message = {
"type": "ping",
"timestamp": time.time()
}
with self.connection_lock:
for client_id, connection in self.connections.items():
try:
self._send_message_to_client(client_id, ping_message)
except Exception as e:
print(f"✗ 心跳发送失败: {client_id} - {e}")
except Exception as e:
print(f"✗ 心跳发送失败: {e}")
self.server_stats["errors"] += 1
def _disconnect_all_clients(self):
"""断开所有客户端连接"""
try:
with self.connection_lock:
client_ids = list(self.connections.keys())
for client_id in client_ids:
self.disconnect_client(client_id, "server_shutdown")
except Exception as e:
print(f"✗ 断开所有客户端连接失败: {e}")
self.server_stats["errors"] += 1
def send_message_to_client(self, client_id: str, message: Dict[str, Any]) -> bool:
"""
向客户端发送消息
Args:
client_id: 客户端ID
message: 消息数据
Returns:
是否发送成功
"""
try:
if not self.enabled:
return False
return self._send_message_to_client(client_id, message)
except Exception as e:
print(f"✗ 向客户端发送消息失败: {e}")
self.server_stats["errors"] += 1
return False
def _send_message_to_client(self, client_id: str, message: Dict[str, Any]) -> bool:
"""
向客户端发送消息内部实现
Args:
client_id: 客户端ID
message: 消息数据
Returns:
是否发送成功
"""
try:
# 检查客户端连接是否存在
with self.connection_lock:
if client_id not in self.connections:
return False
# 序列化消息
if self.plugin.data_serializer:
serialized_message = self.plugin.data_serializer.serialize(message)
else:
serialized_message = json.dumps(message, ensure_ascii=False)
# 发送消息(模拟)
message_size = len(serialized_message.encode('utf-8'))
self.server_state["bytes_sent"] += message_size
self.server_stats["messages_sent"] += 1
return True
except Exception as e:
print(f"✗ 向客户端发送消息失败: {e}")
self.server_stats["errors"] += 1
return False
def broadcast_message(self, message: Dict[str, Any], exclude_client_id: str = None) -> bool:
"""
广播消息到所有客户端
Args:
message: 消息数据
exclude_client_id: 要排除的客户端ID
Returns:
是否广播成功
"""
try:
if not self.enabled:
return False
success_count = 0
with self.connection_lock:
for client_id in self.connections.keys():
# 跳过排除的客户端
if client_id == exclude_client_id:
continue
if self._send_message_to_client(client_id, message):
success_count += 1
return success_count > 0
except Exception as e:
print(f"✗ 消息广播失败: {e}")
self.server_stats["errors"] += 1
return False
def add_client_connection(self, client_id: str, connection_data: Dict[str, Any]) -> bool:
"""
添加客户端连接
Args:
client_id: 客户端ID
connection_data: 连接数据
Returns:
是否添加成功
"""
try:
if not self.enabled:
return False
with self.connection_lock:
# 检查连接数限制
if len(self.connections) >= self.websocket_config["max_connections"]:
print("✗ 连接数已达上限")
return False
# 添加连接
self.connections[client_id] = {
"connection_data": connection_data,
"connect_time": time.time(),
"last_activity": time.time(),
"bytes_sent": 0,
"bytes_received": 0,
"messages_sent": 0,
"messages_received": 0
}
self.server_state["current_connections"] = len(self.connections)
self.server_state["total_connections"] += 1
self.server_stats["connections_accepted"] += 1
# 触发客户端连接回调
self._trigger_websocket_callback("client_connected", {
"client_id": client_id,
"connection_data": connection_data,
"timestamp": time.time()
})
print(f"✓ 客户端已连接: {client_id}")
return True
except Exception as e:
print(f"✗ 添加客户端连接失败: {e}")
self.server_stats["errors"] += 1
return False
def remove_client_connection(self, client_id: str, reason: str = "unknown") -> bool:
"""
移除客户端连接
Args:
client_id: 客户端ID
reason: 断开原因
Returns:
是否移除成功
"""
try:
with self.connection_lock:
if client_id in self.connections:
del self.connections[client_id]
self.server_state["current_connections"] = len(self.connections)
self.server_stats["connections_dropped"] += 1
# 触发客户端断开回调
self._trigger_websocket_callback("client_disconnected", {
"client_id": client_id,
"reason": reason,
"timestamp": time.time()
})
print(f"✓ 客户端已断开: {client_id} (原因: {reason})")
return True
except Exception as e:
print(f"✗ 移除客户端连接失败: {e}")
self.server_stats["errors"] += 1
return False
def disconnect_client(self, client_id: str, reason: str = "kicked") -> bool:
"""
断开客户端连接
Args:
client_id: 客户端ID
reason: 断开原因
Returns:
是否断开成功
"""
try:
# 通知客户端断开连接
disconnect_message = {
"type": "disconnect",
"reason": reason,
"timestamp": time.time()
}
self._send_message_to_client(client_id, disconnect_message)
# 移除连接
return self.remove_client_connection(client_id, reason)
except Exception as e:
print(f"✗ 断开客户端连接失败: {e}")
self.server_stats["errors"] += 1
return False
def get_connection_info(self, client_id: str) -> Optional[Dict[str, Any]]:
"""
获取连接信息
Args:
client_id: 客户端ID
Returns:
连接信息或None
"""
try:
with self.connection_lock:
if client_id in self.connections:
return self.connections[client_id].copy()
else:
return None
except Exception as e:
print(f"✗ 获取连接信息失败: {e}")
self.server_stats["errors"] += 1
return None
def get_all_connections(self) -> Dict[str, Any]:
"""
获取所有连接信息
Returns:
所有连接信息字典
"""
try:
with self.connection_lock:
return {k: v.copy() for k, v in self.connections.items()}
except Exception as e:
print(f"✗ 获取所有连接信息失败: {e}")
self.server_stats["errors"] += 1
return {}
def get_server_stats(self) -> Dict[str, Any]:
"""
获取服务器统计信息
Returns:
服务器统计字典
"""
return {
"state": self.server_state.copy(),
"stats": self.server_stats.copy(),
"config": self.websocket_config.copy()
}
def reset_stats(self):
"""重置服务器统计信息"""
try:
self.server_stats = {
"messages_sent": 0,
"messages_received": 0,
"connections_accepted": 0,
"connections_dropped": 0,
"errors": 0
}
self.server_state["bytes_sent"] = 0
self.server_state["bytes_received"] = 0
print("✓ 服务器统计信息已重置")
except Exception as e:
print(f"✗ 服务器统计信息重置失败: {e}")
def set_websocket_config(self, config: Dict[str, Any]) -> bool:
"""
设置WebSocket配置
Args:
config: WebSocket配置字典
Returns:
是否设置成功
"""
try:
old_port = self.websocket_config.get("port")
new_port = config.get("port", old_port)
# 如果服务器正在运行且端口发生变化,重启服务器
if (self.server_state["is_running"] and
old_port != new_port):
self._stop_websocket_server()
self.websocket_config.update(config)
self._start_websocket_server()
else:
self.websocket_config.update(config)
print(f"✓ WebSocket配置已更新: {self.websocket_config}")
return True
except Exception as e:
print(f"✗ WebSocket配置设置失败: {e}")
return False
def get_websocket_config(self) -> Dict[str, Any]:
"""
获取WebSocket配置
Returns:
WebSocket配置字典
"""
return self.websocket_config.copy()
def _trigger_websocket_callback(self, callback_type: str, data: Dict[str, Any]):
"""
触发WebSocket回调
Args:
callback_type: 回调类型
data: 回调数据
"""
try:
if callback_type in self.websocket_callbacks:
for callback in self.websocket_callbacks[callback_type]:
try:
callback(data)
except Exception as e:
print(f"✗ WebSocket回调执行失败: {callback_type} - {e}")
except Exception as e:
print(f"✗ WebSocket回调触发失败: {e}")
def register_websocket_callback(self, callback_type: str, callback: callable):
"""
注册WebSocket回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.websocket_callbacks:
self.websocket_callbacks[callback_type].append(callback)
print(f"✓ WebSocket回调已注册: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ WebSocket回调注册失败: {e}")
def unregister_websocket_callback(self, callback_type: str, callback: callable):
"""
注销WebSocket回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.websocket_callbacks:
if callback in self.websocket_callbacks[callback_type]:
self.websocket_callbacks[callback_type].remove(callback)
print(f"✓ WebSocket回调已注销: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ WebSocket回调注销失败: {e}")

View File

@ -0,0 +1,596 @@
"""
通信编辑器模块
提供图形界面配置通信参数
"""
import time
from typing import Dict, Any, List, Optional
class CommEditor:
"""
通信编辑器
提供图形界面配置通信参数
"""
def __init__(self, plugin):
"""
初始化通信编辑器
Args:
plugin: 实时通信插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 编辑器配置
self.editor_config = {
"enable_editor": True,
"enable_realtime_monitoring": True,
"enable_performance_display": True,
"enable_config_editor": True,
"enable_statistics_display": True,
"refresh_interval": 1.0,
"max_data_points": 100
}
# 编辑器状态
self.editor_state = {
"is_visible": False,
"last_update": 0.0,
"active_tab": "overview",
"selected_client": None,
"selected_room": None
}
# UI组件
self.ui_components = {
"main_window": None,
"tabs": {},
"panels": {},
"charts": {},
"controls": {}
}
# 编辑器统计
self.editor_stats = {
"updates": 0,
"ui_refreshes": 0,
"data_points": 0,
"editor_errors": 0
}
# 实时数据缓存
self.realtime_data = {
"performance_metrics": {},
"client_data": {},
"room_data": {},
"message_stats": {},
"network_stats": {}
}
# 回调函数
self.editor_callbacks = {
"ui_updated": [],
"data_refreshed": [],
"config_changed": [],
"editor_error": []
}
# 时间戳记录
self.last_ui_update = 0.0
self.last_data_refresh = 0.0
print("✓ 通信编辑器已创建")
def initialize(self) -> bool:
"""
初始化通信编辑器
Returns:
是否初始化成功
"""
try:
print("正在初始化通信编辑器...")
# 初始化UI组件模拟
self._initialize_ui_components()
self.initialized = True
print("✓ 通信编辑器初始化完成")
return True
except Exception as e:
print(f"✗ 通信编辑器初始化失败: {e}")
self.editor_stats["editor_errors"] += 1
import traceback
traceback.print_exc()
return False
def _initialize_ui_components(self):
"""初始化UI组件"""
try:
# 创建主窗口
self.ui_components["main_window"] = {
"title": "实时通信插件编辑器",
"size": (1200, 800),
"position": (100, 100)
}
# 创建标签页
self.ui_components["tabs"] = {
"overview": {"name": "概览", "icon": "dashboard"},
"clients": {"name": "客户端", "icon": "people"},
"rooms": {"name": "房间", "icon": "meeting_room"},
"messages": {"name": "消息", "icon": "message"},
"network": {"name": "网络", "icon": "network"},
"config": {"name": "配置", "icon": "settings"},
"statistics": {"name": "统计", "icon": "bar_chart"}
}
# 创建面板
self.ui_components["panels"] = {
"server_status": {"title": "服务器状态", "visible": True},
"performance": {"title": "性能指标", "visible": True},
"clients_list": {"title": "客户端列表", "visible": True},
"rooms_list": {"title": "房间列表", "visible": True},
"message_stats": {"title": "消息统计", "visible": True}
}
print("✓ UI组件已初始化")
except Exception as e:
print(f"✗ UI组件初始化失败: {e}")
self.editor_stats["editor_errors"] += 1
def enable(self) -> bool:
"""
启用通信编辑器
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ 通信编辑器未初始化")
return False
self.enabled = True
print("✓ 通信编辑器已启用")
return True
except Exception as e:
print(f"✗ 通信编辑器启用失败: {e}")
self.editor_stats["editor_errors"] += 1
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用通信编辑器"""
try:
self.enabled = False
# 隐藏UI
self.hide_editor()
print("✓ 通信编辑器已禁用")
except Exception as e:
print(f"✗ 通信编辑器禁用失败: {e}")
self.editor_stats["editor_errors"] += 1
import traceback
traceback.print_exc()
def finalize(self):
"""清理通信编辑器资源"""
try:
# 禁用通信编辑器
if self.enabled:
self.disable()
# 清理回调
self.editor_callbacks.clear()
self.initialized = False
print("✓ 通信编辑器资源已清理")
except Exception as e:
print(f"✗ 通信编辑器资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新通信编辑器状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
current_time = time.time()
# 定期刷新UI
if current_time - self.last_ui_update >= self.editor_config["refresh_interval"]:
self._refresh_ui()
self.last_ui_update = current_time
# 定期更新数据
if current_time - self.last_data_refresh >= 0.5: # 每0.5秒更新一次数据
self._update_realtime_data()
self.last_data_refresh = current_time
self.editor_state["last_update"] = current_time
except Exception as e:
print(f"✗ 通信编辑器更新失败: {e}")
self.editor_stats["editor_errors"] += 1
import traceback
traceback.print_exc()
def _refresh_ui(self):
"""刷新UI"""
try:
# 更新UI组件状态
self._update_ui_components()
# 更新统计信息
self.editor_stats["ui_refreshes"] += 1
# 触发UI更新回调
self._trigger_editor_callback("ui_updated", {
"timestamp": time.time()
})
except Exception as e:
print(f"✗ UI刷新失败: {e}")
self.editor_stats["editor_errors"] += 1
def _update_ui_components(self):
"""更新UI组件"""
try:
# 更新服务器状态面板
if self.plugin.websocket_server:
server_stats = self.plugin.websocket_server.get_server_stats()
self.ui_components["panels"]["server_status"]["data"] = server_stats
# 更新客户端列表面板
if self.plugin.client_manager:
clients = self.plugin.client_manager.get_all_clients()
self.ui_components["panels"]["clients_list"]["data"] = clients
# 更新房间列表面板
if self.plugin.room_manager:
rooms = self.plugin.room_manager.get_all_rooms()
self.ui_components["panels"]["rooms_list"]["data"] = rooms
# 更新消息统计面板
if self.plugin.message_router:
message_stats = self.plugin.message_router.get_message_stats()
self.ui_components["panels"]["message_stats"]["data"] = message_stats
except Exception as e:
print(f"✗ UI组件更新失败: {e}")
self.editor_stats["editor_errors"] += 1
def _update_realtime_data(self):
"""更新实时数据"""
try:
current_time = time.time()
# 更新性能指标
if self.plugin.monitor:
metrics = self.plugin.monitor.get_performance_metrics()
self.realtime_data["performance_metrics"] = metrics
# 更新客户端数据
if self.plugin.client_manager:
clients = self.plugin.client_manager.get_all_clients()
self.realtime_data["client_data"] = clients
# 更新房间数据
if self.plugin.room_manager:
rooms = self.plugin.room_manager.get_all_rooms()
self.realtime_data["room_data"] = rooms
# 更新消息统计
if self.plugin.message_router:
message_stats = self.plugin.message_router.get_message_stats()
self.realtime_data["message_stats"] = message_stats
# 更新网络统计
if self.plugin.websocket_server:
network_stats = self.plugin.websocket_server.get_server_stats()
self.realtime_data["network_stats"] = network_stats
# 触发数据刷新回调
self._trigger_editor_callback("data_refreshed", {
"data": self.realtime_data,
"timestamp": current_time
})
except Exception as e:
print(f"✗ 实时数据更新失败: {e}")
self.editor_stats["editor_errors"] += 1
def show_editor(self):
"""显示编辑器"""
try:
self.editor_state["is_visible"] = True
print("✓ 通信编辑器已显示")
# 刷新数据
self._update_realtime_data()
except Exception as e:
print(f"✗ 编辑器显示失败: {e}")
self.editor_stats["editor_errors"] += 1
def hide_editor(self):
"""隐藏编辑器"""
try:
self.editor_state["is_visible"] = False
print("✓ 通信编辑器已隐藏")
except Exception as e:
print(f"✗ 编辑器隐藏失败: {e}")
self.editor_stats["editor_errors"] += 1
def switch_tab(self, tab_name: str):
"""
切换标签页
Args:
tab_name: 标签页名称
"""
try:
if tab_name in self.ui_components["tabs"]:
self.editor_state["active_tab"] = tab_name
print(f"✓ 切换到标签页: {tab_name}")
else:
print(f"✗ 无效的标签页: {tab_name}")
except Exception as e:
print(f"✗ 标签页切换失败: {e}")
self.editor_stats["editor_errors"] += 1
def select_client(self, client_id: str):
"""
选择客户端
Args:
client_id: 客户端ID
"""
try:
self.editor_state["selected_client"] = client_id
print(f"✓ 选择客户端: {client_id}")
except Exception as e:
print(f"✗ 客户端选择失败: {e}")
self.editor_stats["editor_errors"] += 1
def select_room(self, room_id: str):
"""
选择房间
Args:
room_id: 房间ID
"""
try:
self.editor_state["selected_room"] = room_id
print(f"✓ 选择房间: {room_id}")
except Exception as e:
print(f"✗ 房间选择失败: {e}")
self.editor_stats["editor_errors"] += 1
def update_config(self, section: str, key: str, value: Any) -> bool:
"""
更新配置
Args:
section: 配置节
key: 配置键
value: 配置值
Returns:
是否更新成功
"""
try:
# 通过配置管理器更新配置
if self.plugin.config_manager:
result = self.plugin.config_manager.set_config(section, key, value)
if result:
self.editor_stats["updates"] += 1
# 触发配置更改回调
self._trigger_editor_callback("config_changed", {
"section": section,
"key": key,
"value": value,
"timestamp": time.time()
})
print(f"✓ 配置已更新: {section}.{key} = {value}")
return True
else:
print(f"✗ 配置更新失败: {section}.{key}")
return False
else:
print("✗ 配置管理器不可用")
return False
except Exception as e:
print(f"✗ 配置更新失败: {e}")
self.editor_stats["editor_errors"] += 1
return False
def get_editor_stats(self) -> Dict[str, Any]:
"""
获取编辑器统计信息
Returns:
编辑器统计字典
"""
return {
"state": self.editor_state.copy(),
"stats": self.editor_stats.copy(),
"config": self.editor_config.copy(),
"ui_components": len(self.ui_components["tabs"])
}
def reset_stats(self):
"""重置编辑器统计信息"""
try:
self.editor_stats = {
"updates": 0,
"ui_refreshes": 0,
"data_points": 0,
"editor_errors": 0
}
print("✓ 编辑器统计信息已重置")
except Exception as e:
print(f"✗ 编辑器统计信息重置失败: {e}")
def set_editor_config(self, config: Dict[str, Any]) -> bool:
"""
设置编辑器配置
Args:
config: 编辑器配置字典
Returns:
是否设置成功
"""
try:
self.editor_config.update(config)
print(f"✓ 编辑器配置已更新: {self.editor_config}")
return True
except Exception as e:
print(f"✗ 编辑器配置设置失败: {e}")
return False
def get_editor_config(self) -> Dict[str, Any]:
"""
获取编辑器配置
Returns:
编辑器配置字典
"""
return self.editor_config.copy()
def get_realtime_data(self) -> Dict[str, Any]:
"""
获取实时数据
Returns:
实时数据字典
"""
return self.realtime_data.copy()
def export_data(self, data_type: str, file_path: str) -> bool:
"""
导出数据
Args:
data_type: 数据类型
file_path: 导出文件路径
Returns:
是否导出成功
"""
try:
import json
import os
# 创建导出目录
export_dir = os.path.dirname(file_path)
if not os.path.exists(export_dir):
os.makedirs(export_dir)
# 获取要导出的数据
export_data = None
if data_type == "performance":
export_data = self.realtime_data["performance_metrics"]
elif data_type == "clients":
export_data = self.realtime_data["client_data"]
elif data_type == "rooms":
export_data = self.realtime_data["room_data"]
elif data_type == "messages":
export_data = self.realtime_data["message_stats"]
elif data_type == "network":
export_data = self.realtime_data["network_stats"]
elif data_type == "all":
export_data = self.realtime_data
else:
print(f"✗ 不支持的数据类型: {data_type}")
return False
# 导出数据
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(export_data, f, indent=2, ensure_ascii=False, default=str)
print(f"✓ 数据已导出到: {file_path}")
return True
except Exception as e:
print(f"✗ 数据导出失败: {e}")
self.editor_stats["editor_errors"] += 1
return False
def _trigger_editor_callback(self, callback_type: str, data: Dict[str, Any]):
"""
触发编辑器回调
Args:
callback_type: 回调类型
data: 回调数据
"""
try:
if callback_type in self.editor_callbacks:
for callback in self.editor_callbacks[callback_type]:
try:
callback(data)
except Exception as e:
print(f"✗ 编辑器回调执行失败: {callback_type} - {e}")
except Exception as e:
print(f"✗ 编辑器回调触发失败: {e}")
def register_editor_callback(self, callback_type: str, callback: callable):
"""
注册编辑器回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.editor_callbacks:
self.editor_callbacks[callback_type].append(callback)
print(f"✓ 编辑器回调已注册: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 编辑器回调注册失败: {e}")
def unregister_editor_callback(self, callback_type: str, callback: callable):
"""
注销编辑器回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.editor_callbacks:
if callback in self.editor_callbacks[callback_type]:
self.editor_callbacks[callback_type].remove(callback)
print(f"✓ 编辑器回调已注销: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 编辑器回调注销失败: {e}")

View File

@ -0,0 +1,716 @@
"""
事件处理器模块
处理通信事件和系统响应
"""
import time
import threading
import queue
from typing import Dict, Any, List, Optional, Callable
class EventHandler:
"""
事件处理器
处理通信事件和系统响应
"""
def __init__(self, plugin):
"""
初始化事件处理器
Args:
plugin: 实时通信插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 事件配置
self.event_config = {
"enable_event_system": True,
"max_event_queue_size": 10000,
"enable_event_filtering": True,
"event_processing_interval": 0.01, # 10ms
"enable_async_processing": True,
"max_concurrent_events": 100,
"enable_event_prioritization": True,
"enable_event_logging": True
}
# 事件状态
self.event_state = {
"is_processing": False,
"pending_events": 0,
"processed_events": 0,
"dropped_events": 0,
"last_event_time": 0.0
}
# 事件队列
self.event_queue = queue.Queue(maxsize=self.event_config["max_event_queue_size"])
self.event_queue_lock = threading.RLock()
# 事件处理器存储
self.event_handlers = {}
# 事件统计
self.event_stats = {
"events_received": 0,
"events_processed": 0,
"events_dropped": 0,
"handler_errors": 0,
"async_events": 0
}
# 事件过滤器
self.event_filters = {}
# 回调函数
self.event_callbacks = {
"event_received": [],
"event_processed": [],
"event_dropped": [],
"event_error": []
}
# 事件处理线程
self.event_thread = None
self.event_thread_running = False
# 时间戳记录
self.last_event_process = 0.0
self.last_stats_reset = 0.0
print("✓ 事件处理器已创建")
def initialize(self) -> bool:
"""
初始化事件处理器
Returns:
是否初始化成功
"""
try:
print("正在初始化事件处理器...")
# 注册默认事件处理器
self._register_default_handlers()
# 启动事件处理线程
self._start_event_thread()
self.initialized = True
print("✓ 事件处理器初始化完成")
return True
except Exception as e:
print(f"✗ 事件处理器初始化失败: {e}")
self.event_stats["handler_errors"] += 1
import traceback
traceback.print_exc()
return False
def _register_default_handlers(self):
"""注册默认事件处理器"""
try:
# 注册系统事件处理器
self.register_event_handler("client_connected", self._handle_client_connected)
self.register_event_handler("client_disconnected", self._handle_client_disconnected)
self.register_event_handler("message_received", self._handle_message_received)
self.register_event_handler("room_created", self._handle_room_created)
self.register_event_handler("room_destroyed", self._handle_room_destroyed)
self.register_event_handler("client_joined_room", self._handle_client_joined_room)
self.register_event_handler("client_left_room", self._handle_client_left_room)
print("✓ 默认事件处理器已注册")
except Exception as e:
print(f"✗ 默认事件处理器注册失败: {e}")
self.event_stats["handler_errors"] += 1
def _start_event_thread(self):
"""启动事件处理线程"""
try:
self.event_thread_running = True
self.event_thread = threading.Thread(target=self._event_loop, daemon=True)
self.event_thread.start()
print("✓ 事件处理线程已启动")
except Exception as e:
print(f"✗ 事件处理线程启动失败: {e}")
self.event_stats["handler_errors"] += 1
def _event_loop(self):
"""事件处理循环"""
try:
while self.event_thread_running:
try:
if self.enabled and self.event_config["enable_event_system"]:
# 处理事件队列
self._process_event_queue()
# 短暂休眠
time.sleep(self.event_config["event_processing_interval"])
except Exception as e:
print(f"✗ 事件处理循环错误: {e}")
self.event_stats["handler_errors"] += 1
time.sleep(1.0) # 出错时延长休眠
except Exception as e:
print(f"✗ 事件处理线程失败: {e}")
self.event_stats["handler_errors"] += 1
def enable(self) -> bool:
"""
启用事件处理器
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ 事件处理器未初始化")
return False
self.enabled = True
print("✓ 事件处理器已启用")
return True
except Exception as e:
print(f"✗ 事件处理器启用失败: {e}")
self.event_stats["handler_errors"] += 1
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用事件处理器"""
try:
self.enabled = False
# 停止事件处理线程
if self.event_thread_running:
self.event_thread_running = False
if self.event_thread and self.event_thread.is_alive():
self.event_thread.join(timeout=5.0)
print("✓ 事件处理器已禁用")
except Exception as e:
print(f"✗ 事件处理器禁用失败: {e}")
self.event_stats["handler_errors"] += 1
import traceback
traceback.print_exc()
def finalize(self):
"""清理事件处理器资源"""
try:
# 禁用事件处理器
if self.enabled:
self.disable()
# 清理回调和处理器
self.event_callbacks.clear()
self.event_handlers.clear()
self.event_filters.clear()
self.initialized = False
print("✓ 事件处理器资源已清理")
except Exception as e:
print(f"✗ 事件处理器资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新事件处理器状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
current_time = time.time()
self.event_state["last_event_time"] = current_time
except Exception as e:
print(f"✗ 事件处理器更新失败: {e}")
self.event_stats["handler_errors"] += 1
import traceback
traceback.print_exc()
def _process_event_queue(self):
"""处理事件队列"""
try:
processed_count = 0
max_process_per_loop = 100 # 每次循环最多处理100个事件
while not self.event_queue.empty() and processed_count < max_process_per_loop:
try:
# 从队列获取事件
event_data = self.event_queue.get_nowait()
# 处理事件
self._handle_event_internal(event_data)
processed_count += 1
self.event_stats["events_processed"] += 1
except queue.Empty:
break
except Exception as e:
print(f"✗ 事件队列处理失败: {e}")
self.event_stats["handler_errors"] += 1
self.event_state["pending_events"] = self.event_queue.qsize()
except Exception as e:
print(f"✗ 事件队列处理失败: {e}")
self.event_stats["handler_errors"] += 1
def _handle_event_internal(self, event_data: Dict[str, Any]):
"""
内部事件处理
Args:
event_data: 事件数据
"""
try:
event_type = event_data.get("type")
event_payload = event_data.get("payload", {})
event_priority = event_data.get("priority", 0)
event_timestamp = event_data.get("timestamp", time.time())
# 应用事件过滤器
if self.event_config["enable_event_filtering"]:
if not self._apply_event_filters(event_type, event_payload):
# 事件被过滤掉
return
# 查找事件处理器
if event_type in self.event_handlers:
handlers = self.event_handlers[event_type]
# 按优先级排序处理器
if self.event_config["enable_event_prioritization"]:
handlers = sorted(handlers, key=lambda x: x.get("priority", 0), reverse=True)
# 调用所有处理器
for handler_info in handlers:
try:
handler_func = handler_info["function"]
handler_result = handler_func(event_payload)
# 检查是否需要停止传播
if handler_result is False:
break
except Exception as e:
print(f"✗ 事件处理器执行失败: {event_type} - {e}")
self.event_stats["handler_errors"] += 1
# 触发事件处理回调
self._trigger_event_callback("event_processed", {
"event_type": event_type,
"event_payload": event_payload,
"processing_time": time.time() - event_timestamp,
"timestamp": time.time()
})
except Exception as e:
print(f"✗ 内部事件处理失败: {e}")
self.event_stats["handler_errors"] += 1
def _apply_event_filters(self, event_type: str, event_payload: Dict[str, Any]) -> bool:
"""
应用事件过滤器
Args:
event_type: 事件类型
event_payload: 事件载荷
Returns:
是否通过过滤器
"""
try:
if event_type in self.event_filters:
filters = self.event_filters[event_type]
for filter_func in filters:
if not filter_func(event_payload):
return False
return True
except Exception as e:
print(f"✗ 事件过滤器应用失败: {e}")
self.event_stats["handler_errors"] += 1
return True
def emit_event(self, event_type: str, event_payload: Dict[str, Any] = None,
priority: int = 0, async_process: bool = None) -> bool:
"""
发出事件
Args:
event_type: 事件类型
event_payload: 事件载荷
priority: 事件优先级
async_process: 是否异步处理
Returns:
是否发出成功
"""
try:
if not self.enabled or not self.event_config["enable_event_system"]:
return False
# 使用默认异步处理设置或指定设置
if async_process is None:
async_process = self.event_config["enable_async_processing"]
event_data = {
"type": event_type,
"payload": event_payload or {},
"priority": priority,
"timestamp": time.time(),
"async": async_process
}
# 触发事件接收回调
self._trigger_event_callback("event_received", {
"event_type": event_type,
"event_payload": event_payload,
"priority": priority,
"timestamp": time.time()
})
# 更新统计
self.event_stats["events_received"] += 1
if async_process:
# 异步处理:添加到队列
try:
self.event_queue.put_nowait(event_data)
self.event_stats["async_events"] += 1
return True
except queue.Full:
# 队列已满,丢弃事件
self.event_stats["events_dropped"] += 1
self.event_state["dropped_events"] += 1
# 触发事件丢弃回调
self._trigger_event_callback("event_dropped", {
"event_type": event_type,
"event_payload": event_payload,
"reason": "queue_full",
"timestamp": time.time()
})
return False
else:
# 同步处理:立即处理
self._handle_event_internal(event_data)
return True
except Exception as e:
print(f"✗ 事件发出失败: {e}")
self.event_stats["handler_errors"] += 1
return False
def register_event_handler(self, event_type: str, handler: Callable, priority: int = 0):
"""
注册事件处理器
Args:
event_type: 事件类型
handler: 处理器函数
priority: 处理器优先级
"""
try:
if event_type not in self.event_handlers:
self.event_handlers[event_type] = []
handler_info = {
"function": handler,
"priority": priority
}
self.event_handlers[event_type].append(handler_info)
print(f"✓ 事件处理器已注册: {event_type} (优先级: {priority})")
except Exception as e:
print(f"✗ 事件处理器注册失败: {e}")
self.event_stats["handler_errors"] += 1
def unregister_event_handler(self, event_type: str, handler: Callable):
"""
注销事件处理器
Args:
event_type: 事件类型
handler: 处理器函数
"""
try:
if event_type in self.event_handlers:
handlers = self.event_handlers[event_type]
for i, handler_info in enumerate(handlers):
if handler_info["function"] == handler:
del handlers[i]
print(f"✓ 事件处理器已注销: {event_type}")
return
print(f"✗ 事件处理器不存在: {event_type}")
except Exception as e:
print(f"✗ 事件处理器注销失败: {e}")
self.event_stats["handler_errors"] += 1
def register_event_filter(self, event_type: str, filter_func: Callable):
"""
注册事件过滤器
Args:
event_type: 事件类型
filter_func: 过滤器函数
"""
try:
if event_type not in self.event_filters:
self.event_filters[event_type] = []
self.event_filters[event_type].append(filter_func)
print(f"✓ 事件过滤器已注册: {event_type}")
except Exception as e:
print(f"✗ 事件过滤器注册失败: {e}")
self.event_stats["handler_errors"] += 1
def unregister_event_filter(self, event_type: str, filter_func: Callable):
"""
注销事件过滤器
Args:
event_type: 事件类型
filter_func: 过滤器函数
"""
try:
if event_type in self.event_filters:
filters = self.event_filters[event_type]
if filter_func in filters:
filters.remove(filter_func)
print(f"✓ 事件过滤器已注销: {event_type}")
return
print(f"✗ 事件过滤器不存在: {event_type}")
except Exception as e:
print(f"✗ 事件过滤器注销失败: {e}")
self.event_stats["handler_errors"] += 1
# 默认事件处理器
def _handle_client_connected(self, payload: Dict[str, Any]):
"""处理客户端连接事件"""
try:
client_id = payload.get("client_id")
connection_data = payload.get("connection_data")
# 添加客户端到客户端管理器
if self.plugin.client_manager:
self.plugin.client_manager.add_client(client_id, {
"connection_data": connection_data,
"ip_address": connection_data.get("remote_address", "") if connection_data else ""
})
except Exception as e:
print(f"✗ 客户端连接事件处理失败: {e}")
self.event_stats["handler_errors"] += 1
def _handle_client_disconnected(self, payload: Dict[str, Any]):
"""处理客户端断开连接事件"""
try:
client_id = payload.get("client_id")
reason = payload.get("reason", "unknown")
# 从客户端管理器移除客户端
if self.plugin.client_manager:
self.plugin.client_manager.remove_client(client_id, reason)
except Exception as e:
print(f"✗ 客户端断开连接事件处理失败: {e}")
self.event_stats["handler_errors"] += 1
def _handle_message_received(self, payload: Dict[str, Any]):
"""处理消息接收事件"""
try:
client_id = payload.get("client_id")
message = payload.get("message")
# 将消息传递给消息路由器
if self.plugin.message_router:
self.plugin.message_router.route_message(client_id, message)
except Exception as e:
print(f"✗ 消息接收事件处理失败: {e}")
self.event_stats["handler_errors"] += 1
def _handle_room_created(self, payload: Dict[str, Any]):
"""处理房间创建事件"""
try:
room_id = payload.get("room_id")
room_name = payload.get("room_name")
# 可以在这里添加额外的房间创建逻辑
print(f"房间已创建: {room_name} ({room_id})")
except Exception as e:
print(f"✗ 房间创建事件处理失败: {e}")
self.event_stats["handler_errors"] += 1
def _handle_room_destroyed(self, payload: Dict[str, Any]):
"""处理房间销毁事件"""
try:
room_id = payload.get("room_id")
room_name = payload.get("room_name")
# 可以在这里添加额外的房间销毁逻辑
print(f"房间已销毁: {room_name} ({room_id})")
except Exception as e:
print(f"✗ 房间销毁事件处理失败: {e}")
self.event_stats["handler_errors"] += 1
def _handle_client_joined_room(self, payload: Dict[str, Any]):
"""处理客户端加入房间事件"""
try:
room_id = payload.get("room_id")
client_id = payload.get("client_id")
# 可以在这里添加额外的客户端加入房间逻辑
print(f"客户端 {client_id} 已加入房间 {room_id}")
except Exception as e:
print(f"✗ 客户端加入房间事件处理失败: {e}")
self.event_stats["handler_errors"] += 1
def _handle_client_left_room(self, payload: Dict[str, Any]):
"""处理客户端离开房间事件"""
try:
room_id = payload.get("room_id")
client_id = payload.get("client_id")
# 可以在这里添加额外的客户端离开房间逻辑
print(f"客户端 {client_id} 已离开房间 {room_id}")
except Exception as e:
print(f"✗ 客户端离开房间事件处理失败: {e}")
self.event_stats["handler_errors"] += 1
def get_event_stats(self) -> Dict[str, Any]:
"""
获取事件统计信息
Returns:
事件统计字典
"""
return {
"state": self.event_state.copy(),
"stats": self.event_stats.copy(),
"config": self.event_config.copy(),
"pending_events": self.event_queue.qsize()
}
def reset_stats(self):
"""重置事件统计信息"""
try:
self.event_stats = {
"events_received": 0,
"events_processed": 0,
"events_dropped": 0,
"handler_errors": 0,
"async_events": 0
}
print("✓ 事件统计信息已重置")
except Exception as e:
print(f"✗ 事件统计信息重置失败: {e}")
def set_event_config(self, config: Dict[str, Any]) -> bool:
"""
设置事件配置
Args:
config: 事件配置字典
Returns:
是否设置成功
"""
try:
self.event_config.update(config)
print(f"✓ 事件配置已更新: {self.event_config}")
return True
except Exception as e:
print(f"✗ 事件配置设置失败: {e}")
return False
def get_event_config(self) -> Dict[str, Any]:
"""
获取事件配置
Returns:
事件配置字典
"""
return self.event_config.copy()
def _trigger_event_callback(self, callback_type: str, data: Dict[str, Any]):
"""
触发事件回调
Args:
callback_type: 回调类型
data: 回调数据
"""
try:
if callback_type in self.event_callbacks:
for callback in self.event_callbacks[callback_type]:
try:
callback(data)
except Exception as e:
print(f"✗ 事件回调执行失败: {callback_type} - {e}")
except Exception as e:
print(f"✗ 事件回调触发失败: {e}")
def register_event_callback(self, callback_type: str, callback: callable):
"""
注册事件回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.event_callbacks:
self.event_callbacks[callback_type].append(callback)
print(f"✓ 事件回调已注册: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 事件回调注册失败: {e}")
def unregister_event_callback(self, callback_type: str, callback: callable):
"""
注销事件回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.event_callbacks:
if callback in self.event_callbacks[callback_type]:
self.event_callbacks[callback_type].remove(callback)
print(f"✓ 事件回调已注销: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 事件回调注销失败: {e}")

View File

@ -0,0 +1,771 @@
"""
消息路由器模块
处理客户端间的消息传递
"""
import time
import threading
import json
from typing import Dict, Any, List, Optional
class MessageRouter:
"""
消息路由器
处理客户端间的消息传递
"""
def __init__(self, plugin):
"""
初始化消息路由器
Args:
plugin: 实时通信插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 消息路由配置
self.message_config = {
"enable_message_filtering": True,
"max_message_size": 65536, # 64KB
"enable_message_queue": True,
"message_queue_size": 10000,
"enable_broadcast_optimization": True,
"enable_message_compression": True,
"enable_rate_limiting": True,
"max_messages_per_second_per_client": 100,
"enable_message_logging": False
}
# 消息路由状态
self.router_state = {
"is_processing": False,
"pending_messages": 0,
"active_routes": 0,
"last_message_time": 0.0
}
# 消息路由统计
self.message_stats = {
"messages_routed": 0,
"messages_broadcast": 0,
"messages_filtered": 0,
"messages_dropped": 0,
"bytes_routed": 0,
"routing_errors": 0
}
# 消息处理器存储
self.message_handlers = {}
# 消息队列
self.message_queue = []
self.message_queue_lock = threading.RLock()
# 路由表
self.routing_table = {}
# 回调函数
self.message_callbacks = {
"message_routed": [],
"message_broadcast": [],
"message_filtered": [],
"message_error": []
}
# 时间戳记录
self.last_queue_process = 0.0
self.last_stats_reset = 0.0
print("✓ 消息路由器已创建")
def initialize(self) -> bool:
"""
初始化消息路由器
Returns:
是否初始化成功
"""
try:
print("正在初始化消息路由器...")
# 注册默认消息处理器
self._register_default_handlers()
self.initialized = True
print("✓ 消息路由器初始化完成")
return True
except Exception as e:
print(f"✗ 消息路由器初始化失败: {e}")
self.message_stats["routing_errors"] += 1
import traceback
traceback.print_exc()
return False
def _register_default_handlers(self):
"""注册默认消息处理器"""
try:
# 注册系统消息处理器
self.register_message_handler("ping", self._handle_ping_message)
self.register_message_handler("pong", self._handle_pong_message)
self.register_message_handler("chat", self._handle_chat_message)
self.register_message_handler("join_room", self._handle_join_room_message)
self.register_message_handler("leave_room", self._handle_leave_room_message)
self.register_message_handler("broadcast", self._handle_broadcast_message)
print("✓ 默认消息处理器已注册")
except Exception as e:
print(f"✗ 默认消息处理器注册失败: {e}")
self.message_stats["routing_errors"] += 1
def enable(self) -> bool:
"""
启用消息路由器
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ 消息路由器未初始化")
return False
self.enabled = True
print("✓ 消息路由器已启用")
return True
except Exception as e:
print(f"✗ 消息路由器启用失败: {e}")
self.message_stats["routing_errors"] += 1
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用消息路由器"""
try:
self.enabled = False
# 清空消息队列
with self.message_queue_lock:
self.message_queue.clear()
print("✓ 消息路由器已禁用")
except Exception as e:
print(f"✗ 消息路由器禁用失败: {e}")
self.message_stats["routing_errors"] += 1
import traceback
traceback.print_exc()
def finalize(self):
"""清理消息路由器资源"""
try:
# 禁用消息路由器
if self.enabled:
self.disable()
# 清理回调和处理器
self.message_callbacks.clear()
self.message_handlers.clear()
self.initialized = False
print("✓ 消息路由器资源已清理")
except Exception as e:
print(f"✗ 消息路由器资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新消息路由器状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
current_time = time.time()
# 处理消息队列
if self.message_config["enable_message_queue"]:
self._process_message_queue()
self.router_state["last_message_time"] = current_time
except Exception as e:
print(f"✗ 消息路由器更新失败: {e}")
self.message_stats["routing_errors"] += 1
import traceback
traceback.print_exc()
def _process_message_queue(self):
"""处理消息队列"""
try:
if not self.message_queue:
return
with self.message_queue_lock:
messages_to_process = self.message_queue[:]
self.message_queue.clear()
for message_data in messages_to_process:
try:
client_id = message_data.get("client_id")
message = message_data.get("message")
# 处理消息
self._route_message_internal(client_id, message)
except Exception as e:
print(f"✗ 队列消息处理失败: {e}")
self.message_stats["routing_errors"] += 1
self.router_state["pending_messages"] = len(self.message_queue)
except Exception as e:
print(f"✗ 消息队列处理失败: {e}")
self.message_stats["routing_errors"] += 1
def register_message_handler(self, message_type: str, handler: callable):
"""
注册消息处理器
Args:
message_type: 消息类型
handler: 处理器函数
"""
try:
self.message_handlers[message_type] = handler
print(f"✓ 消息处理器已注册: {message_type}")
except Exception as e:
print(f"✗ 消息处理器注册失败: {e}")
self.message_stats["routing_errors"] += 1
def unregister_message_handler(self, message_type: str):
"""
注销消息处理器
Args:
message_type: 消息类型
"""
try:
if message_type in self.message_handlers:
del self.message_handlers[message_type]
print(f"✓ 消息处理器已注销: {message_type}")
else:
print(f"✗ 消息处理器不存在: {message_type}")
except Exception as e:
print(f"✗ 消息处理器注销失败: {e}")
self.message_stats["routing_errors"] += 1
def route_message(self, client_id: str, message: Dict[str, Any]) -> bool:
"""
路由消息
Args:
client_id: 客户端ID
message: 消息数据
Returns:
是否路由成功
"""
try:
if not self.enabled:
return False
# 检查消息大小
if self.message_config["enable_message_filtering"]:
message_size = len(json.dumps(message, ensure_ascii=False).encode('utf-8'))
if message_size > self.message_config["max_message_size"]:
print(f"✗ 消息过大: {message_size} bytes")
self.message_stats["messages_dropped"] += 1
return False
# 如果启用消息队列,将消息加入队列
if self.message_config["enable_message_queue"]:
with self.message_queue_lock:
if len(self.message_queue) >= self.message_config["message_queue_size"]:
print("✗ 消息队列已满,丢弃消息")
self.message_stats["messages_dropped"] += 1
return False
self.message_queue.append({
"client_id": client_id,
"message": message,
"timestamp": time.time()
})
self.router_state["pending_messages"] = len(self.message_queue)
return True
else:
# 直接处理消息
return self._route_message_internal(client_id, message)
except Exception as e:
print(f"✗ 消息路由失败: {e}")
self.message_stats["routing_errors"] += 1
return False
def _route_message_internal(self, client_id: str, message: Dict[str, Any]) -> bool:
"""
内部消息路由处理
Args:
client_id: 客户端ID
message: 消息数据
Returns:
是否路由成功
"""
try:
# 更新统计信息
self.message_stats["messages_routed"] += 1
message_size = len(json.dumps(message, ensure_ascii=False).encode('utf-8'))
self.message_stats["bytes_routed"] += message_size
# 触发消息路由回调
self._trigger_message_callback("message_routed", {
"client_id": client_id,
"message": message,
"timestamp": time.time()
})
# 获取消息类型
message_type = message.get("type", "unknown")
# 查找对应的消息处理器
if message_type in self.message_handlers:
try:
# 调用消息处理器
handler_result = self.message_handlers[message_type](client_id, message)
return handler_result if handler_result is not None else True
except Exception as e:
print(f"✗ 消息处理器执行失败: {message_type} - {e}")
self.message_stats["routing_errors"] += 1
return False
else:
# 默认处理:广播给所有客户端(除了发送者)
return self._handle_default_message(client_id, message)
except Exception as e:
print(f"✗ 内部消息路由处理失败: {e}")
self.message_stats["routing_errors"] += 1
return False
def _handle_default_message(self, client_id: str, message: Dict[str, Any]) -> bool:
"""
处理默认消息广播给其他客户端
Args:
client_id: 发送客户端ID
message: 消息数据
Returns:
是否处理成功
"""
try:
# 广播消息给所有其他客户端
if self.plugin.websocket_server:
broadcast_success = self.plugin.websocket_server.broadcast_message(
message, exclude_client_id=client_id)
if broadcast_success:
self.message_stats["messages_broadcast"] += 1
return True
else:
return False
else:
return False
except Exception as e:
print(f"✗ 默认消息处理失败: {e}")
self.message_stats["routing_errors"] += 1
return False
# 默认消息处理器
def _handle_ping_message(self, client_id: str, message: Dict[str, Any]) -> bool:
"""
处理ping消息
Args:
client_id: 客户端ID
message: 消息数据
Returns:
是否处理成功
"""
try:
# 更新客户端心跳
if self.plugin.client_manager:
self.plugin.client_manager.update_client_heartbeat(client_id)
# 回复pong消息
pong_message = {
"type": "pong",
"timestamp": time.time(),
"ping_timestamp": message.get("timestamp", 0)
}
if self.plugin.websocket_server:
return self.plugin.websocket_server.send_message_to_client(client_id, pong_message)
else:
return False
except Exception as e:
print(f"✗ ping消息处理失败: {e}")
self.message_stats["routing_errors"] += 1
return False
def _handle_pong_message(self, client_id: str, message: Dict[str, Any]) -> bool:
"""
处理pong消息
Args:
client_id: 客户端ID
message: 消息数据
Returns:
是否处理成功
"""
try:
# 更新客户端心跳
if self.plugin.client_manager:
self.plugin.client_manager.update_client_heartbeat(client_id)
return True
except Exception as e:
print(f"✗ pong消息处理失败: {e}")
self.message_stats["routing_errors"] += 1
return False
def _handle_chat_message(self, client_id: str, message: Dict[str, Any]) -> bool:
"""
处理聊天消息
Args:
client_id: 客户端ID
message: 消息数据
Returns:
是否处理成功
"""
try:
# 获取客户端信息
client_data = self.plugin.client_manager.get_client(client_id) if self.plugin.client_manager else None
if not client_data:
return False
# 添加发送者信息
message["sender_id"] = client_id
message["sender_name"] = client_data.get("username", "Unknown")
message["sender_time"] = time.time()
# 广播聊天消息
if self.plugin.websocket_server:
broadcast_success = self.plugin.websocket_server.broadcast_message(message)
if broadcast_success:
self.message_stats["messages_broadcast"] += 1
return broadcast_success
else:
return False
except Exception as e:
print(f"✗ 聊天消息处理失败: {e}")
self.message_stats["routing_errors"] += 1
return False
def _handle_join_room_message(self, client_id: str, message: Dict[str, Any]) -> bool:
"""
处理加入房间消息
Args:
client_id: 客户端ID
message: 消息数据
Returns:
是否处理成功
"""
try:
room_id = message.get("room_id")
if not room_id:
return False
# 使用房间管理器处理加入房间请求
if self.plugin.room_manager:
join_success = self.plugin.room_manager.add_client_to_room(room_id, client_id)
if join_success:
# 通知客户端加入成功
response_message = {
"type": "room_joined",
"room_id": room_id,
"timestamp": time.time()
}
if self.plugin.websocket_server:
self.plugin.websocket_server.send_message_to_client(client_id, response_message)
return join_success
else:
return False
except Exception as e:
print(f"✗ 加入房间消息处理失败: {e}")
self.message_stats["routing_errors"] += 1
return False
def _handle_leave_room_message(self, client_id: str, message: Dict[str, Any]) -> bool:
"""
处理离开房间消息
Args:
client_id: 客户端ID
message: 消息数据
Returns:
是否处理成功
"""
try:
room_id = message.get("room_id")
if not room_id:
return False
# 使用房间管理器处理离开房间请求
if self.plugin.room_manager:
leave_success = self.plugin.room_manager.remove_client_from_room(room_id, client_id)
if leave_success:
# 通知客户端离开成功
response_message = {
"type": "room_left",
"room_id": room_id,
"timestamp": time.time()
}
if self.plugin.websocket_server:
self.plugin.websocket_server.send_message_to_client(client_id, response_message)
return leave_success
else:
return False
except Exception as e:
print(f"✗ 离开房间消息处理失败: {e}")
self.message_stats["routing_errors"] += 1
return False
def _handle_broadcast_message(self, client_id: str, message: Dict[str, Any]) -> bool:
"""
处理广播消息
Args:
client_id: 客户端ID
message: 消息数据
Returns:
是否处理成功
"""
try:
# 广播消息给所有客户端
if self.plugin.websocket_server:
broadcast_success = self.plugin.websocket_server.broadcast_message(message)
if broadcast_success:
self.message_stats["messages_broadcast"] += 1
return broadcast_success
else:
return False
except Exception as e:
print(f"✗ 广播消息处理失败: {e}")
self.message_stats["routing_errors"] += 1
return False
def send_direct_message(self, from_client_id: str, to_client_id: str, message: Dict[str, Any]) -> bool:
"""
发送直接消息
Args:
from_client_id: 发送客户端ID
to_client_id: 接收客户端ID
message: 消息数据
Returns:
是否发送成功
"""
try:
if not self.enabled:
return False
# 添加发送者信息
message["sender_id"] = from_client_id
message["timestamp"] = time.time()
# 发送消息到目标客户端
if self.plugin.websocket_server:
send_success = self.plugin.websocket_server.send_message_to_client(to_client_id, message)
if send_success:
self.message_stats["messages_routed"] += 1
return send_success
else:
return False
except Exception as e:
print(f"✗ 直接消息发送失败: {e}")
self.message_stats["routing_errors"] += 1
return False
def broadcast_to_room(self, room_id: str, message: Dict[str, Any], exclude_client_id: str = None) -> bool:
"""
广播消息到房间
Args:
room_id: 房间ID
message: 消息数据
exclude_client_id: 要排除的客户端ID
Returns:
是否广播成功
"""
try:
if not self.enabled:
return False
# 使用房间管理器获取房间内的客户端
if self.plugin.room_manager:
room_clients = self.plugin.room_manager.get_room_clients(room_id)
if not room_clients:
return False
success_count = 0
for client_id in room_clients:
# 跳过排除的客户端
if client_id == exclude_client_id:
continue
# 发送消息
if self.plugin.websocket_server:
send_success = self.plugin.websocket_server.send_message_to_client(client_id, message)
if send_success:
success_count += 1
return success_count > 0
else:
return False
except Exception as e:
print(f"✗ 房间广播失败: {e}")
self.message_stats["routing_errors"] += 1
return False
def get_message_stats(self) -> Dict[str, Any]:
"""
获取消息统计信息
Returns:
消息统计字典
"""
return {
"state": self.router_state.copy(),
"stats": self.message_stats.copy(),
"config": self.message_config.copy()
}
def reset_stats(self):
"""重置消息统计信息"""
try:
self.message_stats = {
"messages_routed": 0,
"messages_broadcast": 0,
"messages_filtered": 0,
"messages_dropped": 0,
"bytes_routed": 0,
"routing_errors": 0
}
print("✓ 消息统计信息已重置")
except Exception as e:
print(f"✗ 消息统计信息重置失败: {e}")
def set_message_config(self, config: Dict[str, Any]) -> bool:
"""
设置消息配置
Args:
config: 消息配置字典
Returns:
是否设置成功
"""
try:
self.message_config.update(config)
print(f"✓ 消息配置已更新: {self.message_config}")
return True
except Exception as e:
print(f"✗ 消息配置设置失败: {e}")
return False
def get_message_config(self) -> Dict[str, Any]:
"""
获取消息配置
Returns:
消息配置字典
"""
return self.message_config.copy()
def _trigger_message_callback(self, callback_type: str, data: Dict[str, Any]):
"""
触发消息回调
Args:
callback_type: 回调类型
data: 回调数据
"""
try:
if callback_type in self.message_callbacks:
for callback in self.message_callbacks[callback_type]:
try:
callback(data)
except Exception as e:
print(f"✗ 消息回调执行失败: {callback_type} - {e}")
except Exception as e:
print(f"✗ 消息回调触发失败: {e}")
def register_message_callback(self, callback_type: str, callback: callable):
"""
注册消息回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.message_callbacks:
self.message_callbacks[callback_type].append(callback)
print(f"✓ 消息回调已注册: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 消息回调注册失败: {e}")
def unregister_message_callback(self, callback_type: str, callback: callable):
"""
注销消息回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.message_callbacks:
if callback in self.message_callbacks[callback_type]:
self.message_callbacks[callback_type].remove(callback)
print(f"✓ 消息回调已注销: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 消息回调注销失败: {e}")

View File

@ -0,0 +1,825 @@
"""
通信监控模块
实时监控通信性能和记录日志
"""
import time
import threading
import json
import os
from typing import Dict, Any, List, Optional
from collections import deque
class CommunicationMonitor:
"""
通信监控器
实时监控通信性能和记录日志
"""
def __init__(self, plugin):
"""
初始化通信监控器
Args:
plugin: 实时通信插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 监控配置
self.monitor_config = {
"enable_monitoring": True,
"monitoring_interval": 5.0,
"log_level": "INFO",
"enable_file_logging": True,
"log_file_path": "/home/hello/EG/plugins/user/realtime_communication/logs/communication_monitor.log",
"max_log_file_size": 10485760, # 10MB
"enable_performance_monitoring": True,
"enable_alerts": True,
"alert_thresholds": {
"cpu_usage": 80.0,
"memory_usage": 85.0,
"network_latency": 100.0,
"error_rate": 5.0,
"message_queue_size": 1000
},
"enable_metrics_collection": True,
"metrics_retention_period": 3600, # 1小时
"enable_realtime_dashboard": True
}
# 性能指标存储
self.performance_metrics = {
"cpu_usage": deque(maxlen=1000),
"memory_usage": deque(maxlen=1000),
"network_in": deque(maxlen=1000),
"network_out": deque(maxlen=1000),
"active_connections": deque(maxlen=1000),
"messages_per_second": deque(maxlen=1000),
"message_queue_size": deque(maxlen=1000),
"error_rate": deque(maxlen=1000)
}
# 监控状态
self.monitor_state = {
"last_monitoring_update": 0.0,
"last_performance_check": 0.0,
"total_logs": 0,
"total_alerts": 0,
"active_alerts": 0
}
# 警报系统
self.active_alerts = {}
self.alert_history = deque(maxlen=1000)
# 日志文件
self.log_file = None
self.log_file_size = 0
# 监控统计
self.monitor_stats = {
"metrics_collected": 0,
"logs_written": 0,
"alerts_generated": 0,
"alerts_resolved": 0,
"performance_checks": 0,
"monitor_errors": 0
}
# 线程锁
self.monitor_lock = threading.RLock()
# 回调函数
self.monitor_callbacks = {
"metric_collected": [],
"alert_triggered": [],
"alert_resolved": [],
"log_entry": [],
"performance_degraded": []
}
# 监控线程
self.monitor_thread = None
self.monitor_thread_running = False
# 时间戳记录
self.last_log_write = 0.0
self.last_metric_collection = 0.0
print("✓ 通信监控器已创建")
def initialize(self) -> bool:
"""
初始化通信监控器
Returns:
是否初始化成功
"""
try:
print("正在初始化通信监控器...")
# 创建日志目录
log_dir = os.path.dirname(self.monitor_config["log_file_path"])
if not os.path.exists(log_dir):
os.makedirs(log_dir)
# 初始化日志文件
if self.monitor_config["enable_file_logging"]:
self._initialize_log_file()
# 启动监控线程
self._start_monitor_thread()
self.initialized = True
print("✓ 通信监控器初始化完成")
return True
except Exception as e:
print(f"✗ 通信监控器初始化失败: {e}")
self.monitor_stats["monitor_errors"] += 1
import traceback
traceback.print_exc()
return False
def _initialize_log_file(self):
"""初始化日志文件"""
try:
# 检查文件是否存在
if os.path.exists(self.monitor_config["log_file_path"]):
self.log_file_size = os.path.getsize(self.monitor_config["log_file_path"])
# 打开日志文件
self.log_file = open(self.monitor_config["log_file_path"], "a", encoding="utf-8")
print(f"✓ 日志文件已初始化: {self.monitor_config['log_file_path']}")
except Exception as e:
print(f"✗ 日志文件初始化失败: {e}")
self.monitor_stats["monitor_errors"] += 1
def _start_monitor_thread(self):
"""启动监控线程"""
try:
self.monitor_thread_running = True
self.monitor_thread = threading.Thread(target=self._monitor_loop, daemon=True)
self.monitor_thread.start()
print("✓ 监控线程已启动")
except Exception as e:
print(f"✗ 监控线程启动失败: {e}")
self.monitor_stats["monitor_errors"] += 1
def _monitor_loop(self):
"""监控线程循环"""
try:
while self.monitor_thread_running:
try:
if self.enabled and self.monitor_config["enable_monitoring"]:
current_time = time.time()
# 收集性能指标
if current_time - self.last_metric_collection >= self.monitor_config["monitoring_interval"]:
self._collect_performance_metrics()
self.last_metric_collection = current_time
# 检查警报
self._check_alerts()
# 检查日志文件大小
self._check_log_file_size()
# 短暂休眠
time.sleep(1.0)
except Exception as e:
print(f"✗ 监控循环错误: {e}")
self.monitor_stats["monitor_errors"] += 1
time.sleep(5.0) # 出错时延长休眠
except Exception as e:
print(f"✗ 监控线程失败: {e}")
self.monitor_stats["monitor_errors"] += 1
def enable(self) -> bool:
"""
启用通信监控器
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ 通信监控器未初始化")
return False
self.enabled = True
print("✓ 通信监控器已启用")
return True
except Exception as e:
print(f"✗ 通信监控器启用失败: {e}")
self.monitor_stats["monitor_errors"] += 1
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用通信监控器"""
try:
self.enabled = False
# 停止监控线程
if self.monitor_thread_running:
self.monitor_thread_running = False
if self.monitor_thread and self.monitor_thread.is_alive():
self.monitor_thread.join(timeout=5.0)
# 关闭日志文件
if self.log_file:
self.log_file.close()
self.log_file = None
print("✓ 通信监控器已禁用")
except Exception as e:
print(f"✗ 通信监控器禁用失败: {e}")
self.monitor_stats["monitor_errors"] += 1
import traceback
traceback.print_exc()
def finalize(self):
"""清理通信监控器资源"""
try:
# 禁用通信监控器
if self.enabled:
self.disable()
# 清理回调
self.monitor_callbacks.clear()
self.initialized = False
print("✓ 通信监控器资源已清理")
except Exception as e:
print(f"✗ 通信监控器资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新通信监控器状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
current_time = time.time()
self.monitor_state["last_monitoring_update"] = current_time
except Exception as e:
print(f"✗ 通信监控器更新失败: {e}")
self.monitor_stats["monitor_errors"] += 1
import traceback
traceback.print_exc()
def _collect_performance_metrics(self):
"""收集性能指标"""
try:
current_time = time.time()
metrics = {}
# 收集系统资源使用情况
try:
import psutil
# CPU使用率
cpu_percent = psutil.cpu_percent(interval=0.1)
metrics["cpu_usage"] = cpu_percent
self.performance_metrics["cpu_usage"].append((current_time, cpu_percent))
# 内存使用率
memory_info = psutil.virtual_memory()
memory_percent = memory_info.percent
metrics["memory_usage"] = memory_percent
self.performance_metrics["memory_usage"].append((current_time, memory_percent))
# 网络使用情况
net_io = psutil.net_io_counters()
metrics["network_in"] = net_io.bytes_recv
metrics["network_out"] = net_io.bytes_sent
self.performance_metrics["network_in"].append((current_time, net_io.bytes_recv))
self.performance_metrics["network_out"].append((current_time, net_io.bytes_sent))
except ImportError:
# 如果没有psutil使用简化的指标
metrics["cpu_usage"] = 0.0
metrics["memory_usage"] = 0.0
metrics["network_in"] = 0
metrics["network_out"] = 0
# 收集服务器指标
if self.plugin.websocket_server:
server_stats = self.plugin.websocket_server.get_server_stats()
server_state = server_stats.get("state", {})
# 活跃连接数
active_connections = server_state.get("current_connections", 0)
metrics["active_connections"] = active_connections
self.performance_metrics["active_connections"].append((current_time, active_connections))
# 数据传输量
bytes_sent = server_state.get("bytes_sent", 0)
bytes_received = server_state.get("bytes_received", 0)
metrics["bytes_sent"] = bytes_sent
metrics["bytes_received"] = bytes_received
# 收集客户端指标
if self.plugin.client_manager:
client_stats = self.plugin.client_manager.get_client_stats()
client_state = client_stats.get("state", {})
client_count = client_state.get("current_clients", 0)
metrics["client_count"] = client_count
# 收集消息指标
if self.plugin.message_router:
message_stats = self.plugin.message_router.get_message_stats()
message_state = message_stats.get("state", {})
message_stats_data = message_stats.get("stats", {})
# 消息队列大小
pending_messages = message_state.get("pending_messages", 0)
metrics["message_queue_size"] = pending_messages
self.performance_metrics["message_queue_size"].append((current_time, pending_messages))
# 消息处理速率
messages_routed = message_stats_data.get("messages_routed", 0)
if hasattr(self, '_last_messages_routed'):
mps = (messages_routed - self._last_messages_routed) / self.monitor_config["monitoring_interval"]
metrics["messages_per_second"] = max(0, mps)
self.performance_metrics["messages_per_second"].append((current_time, metrics["messages_per_second"]))
else:
metrics["messages_per_second"] = 0
self.performance_metrics["messages_per_second"].append((current_time, 0))
self._last_messages_routed = messages_routed
# 收集房间指标
if self.plugin.room_manager:
room_stats = self.plugin.room_manager.get_room_stats()
room_state = room_stats.get("state", {})
active_rooms = room_state.get("active_rooms", 0)
metrics["active_rooms"] = active_rooms
# 更新统计
self.monitor_stats["metrics_collected"] += 1
self.last_metric_collection = current_time
# 触发指标收集回调
self._trigger_monitor_callback("metric_collected", {
"metrics": metrics,
"timestamp": current_time
})
# 记录日志
if self._should_log("DEBUG"):
self._write_log("DEBUG", f"性能指标收集: {metrics}")
except Exception as e:
print(f"✗ 性能指标收集失败: {e}")
self.monitor_stats["monitor_errors"] += 1
def _check_alerts(self):
"""检查警报条件"""
try:
if not self.monitor_config["enable_alerts"]:
return
current_time = time.time()
thresholds = self.monitor_config["alert_thresholds"]
# 检查CPU使用率
if self.performance_metrics["cpu_usage"]:
latest_cpu = self.performance_metrics["cpu_usage"][-1][1]
if latest_cpu > thresholds["cpu_usage"]:
self._trigger_alert("high_cpu_usage", f"CPU使用率过高: {latest_cpu:.2f}%", current_time)
# 检查内存使用率
if self.performance_metrics["memory_usage"]:
latest_memory = self.performance_metrics["memory_usage"][-1][1]
if latest_memory > thresholds["memory_usage"]:
self._trigger_alert("high_memory_usage", f"内存使用率过高: {latest_memory:.2f}%", current_time)
# 检查消息队列大小
if self.performance_metrics["message_queue_size"]:
latest_queue_size = self.performance_metrics["message_queue_size"][-1][1]
if latest_queue_size > thresholds["message_queue_size"]:
self._trigger_alert("high_message_queue", f"消息队列过大: {latest_queue_size}", current_time)
# 检查错误率
if self.performance_metrics["error_rate"]:
latest_error_rate = self.performance_metrics["error_rate"][-1][1]
if latest_error_rate > thresholds["error_rate"]:
self._trigger_alert("high_error_rate", f"错误率过高: {latest_error_rate:.2f}%", current_time)
# 检查活跃连接数
if self.performance_metrics["active_connections"]:
latest_connections = self.performance_metrics["active_connections"][-1][1]
if self.plugin.websocket_server:
max_connections = self.plugin.websocket_server.websocket_config.get("max_connections", 1000)
if latest_connections > max_connections * 0.9: # 90%阈值
self._trigger_alert("high_connections", f"连接数接近上限: {latest_connections}/{max_connections}", current_time)
except Exception as e:
print(f"✗ 警报检查失败: {e}")
self.monitor_stats["monitor_errors"] += 1
def _trigger_alert(self, alert_type: str, message: str, timestamp: float = None):
"""
触发警报
Args:
alert_type: 警报类型
message: 警报消息
timestamp: 时间戳
"""
try:
if timestamp is None:
timestamp = time.time()
alert_id = f"{alert_type}_{int(timestamp)}"
# 检查是否已存在相同类型的活动警报
with self.monitor_lock:
if alert_type in self.active_alerts:
# 更新现有警报
self.active_alerts[alert_type]["count"] += 1
self.active_alerts[alert_type]["last_triggered"] = timestamp
else:
# 创建新警报
self.active_alerts[alert_type] = {
"id": alert_id,
"type": alert_type,
"message": message,
"first_triggered": timestamp,
"last_triggered": timestamp,
"count": 1,
"resolved": False
}
self.monitor_state["active_alerts"] += 1
self.monitor_stats["alerts_generated"] += 1
# 添加到警报历史
self.alert_history.append({
"id": alert_id,
"type": alert_type,
"message": message,
"timestamp": timestamp,
"resolved": False
})
# 触发警报回调
self._trigger_monitor_callback("alert_triggered", {
"alert_id": alert_id,
"alert_type": alert_type,
"message": message,
"timestamp": timestamp
})
# 记录日志
self._write_log("WARNING", f"警报触发 [{alert_type}]: {message}")
except Exception as e:
print(f"✗ 警报触发失败: {e}")
self.monitor_stats["monitor_errors"] += 1
def resolve_alert(self, alert_type: str):
"""
解决警报
Args:
alert_type: 警报类型
"""
try:
with self.monitor_lock:
if alert_type in self.active_alerts:
alert_data = self.active_alerts[alert_type]
alert_data["resolved"] = True
alert_data["resolved_time"] = time.time()
self.monitor_state["active_alerts"] -= 1
self.monitor_stats["alerts_resolved"] += 1
# 触发警报解决回调
self._trigger_monitor_callback("alert_resolved", {
"alert_type": alert_type,
"alert_data": alert_data
})
# 从活动警报中移除
del self.active_alerts[alert_type]
# 记录日志
self._write_log("INFO", f"警报已解决: {alert_type}")
except Exception as e:
print(f"✗ 警报解决失败: {e}")
self.monitor_stats["monitor_errors"] += 1
def _check_log_file_size(self):
"""检查日志文件大小"""
try:
if not self.monitor_config["enable_file_logging"] or not self.log_file:
return
# 检查文件大小
if os.path.exists(self.monitor_config["log_file_path"]):
current_size = os.path.getsize(self.monitor_config["log_file_path"])
if current_size > self.monitor_config["max_log_file_size"]:
# 轮转日志文件
self._rotate_log_file()
except Exception as e:
print(f"✗ 日志文件大小检查失败: {e}")
self.monitor_stats["monitor_errors"] += 1
def _rotate_log_file(self):
"""轮转日志文件"""
try:
if self.log_file:
self.log_file.close()
# 重命名当前日志文件
timestamp = int(time.time())
rotated_filename = f"{self.monitor_config['log_file_path']}.{timestamp}"
os.rename(self.monitor_config["log_file_path"], rotated_filename)
# 重新初始化日志文件
self._initialize_log_file()
print(f"✓ 日志文件已轮转: {rotated_filename}")
except Exception as e:
print(f"✗ 日志文件轮转失败: {e}")
self.monitor_stats["monitor_errors"] += 1
def _write_log(self, level: str, message: str, extra_data: Dict[str, Any] = None):
"""
写入日志
Args:
level: 日志级别
message: 日志消息
extra_data: 额外数据
"""
try:
if not self._should_log(level):
return
timestamp = time.time()
log_entry = {
"timestamp": timestamp,
"level": level,
"message": message,
"extra_data": extra_data
}
# 控制台输出
print(f"[{level}] {message}")
# 文件日志
if self.monitor_config["enable_file_logging"] and self.log_file:
try:
log_line = json.dumps(log_entry, ensure_ascii=False)
self.log_file.write(log_line + "\n")
self.log_file.flush()
self.log_file_size += len(log_line) + 1
self.monitor_stats["logs_written"] += 1
self.monitor_state["total_logs"] += 1
except Exception as e:
print(f"✗ 文件日志写入失败: {e}")
# 触发日志条目回调
self._trigger_monitor_callback("log_entry", log_entry)
self.last_log_write = timestamp
except Exception as e:
print(f"✗ 日志写入失败: {e}")
self.monitor_stats["monitor_errors"] += 1
def _should_log(self, level: str) -> bool:
"""
检查是否应该记录指定级别的日志
Args:
level: 日志级别
Returns:
是否应该记录日志
"""
try:
log_levels = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
current_level = self.monitor_config["log_level"]
if current_level not in log_levels:
return True # 默认记录所有日志
if level not in log_levels:
return True # 默认记录未知级别的日志
current_index = log_levels.index(current_level)
level_index = log_levels.index(level)
# 只记录等于或高于当前级别的日志
return level_index >= current_index
except Exception as e:
print(f"✗ 日志级别检查失败: {e}")
return True
def get_performance_metrics(self, metric_name: str = None, limit: int = 100) -> Any:
"""
获取性能指标
Args:
metric_name: 指标名称可选
limit: 限制返回的数量
Returns:
性能指标数据
"""
try:
with self.monitor_lock:
if metric_name:
if metric_name in self.performance_metrics:
metrics = list(self.performance_metrics[metric_name])
return metrics[-limit:] if len(metrics) > limit else metrics
else:
return []
else:
# 返回所有指标
result = {}
for name, metrics in self.performance_metrics.items():
metric_list = list(metrics)
result[name] = metric_list[-limit:] if len(metric_list) > limit else metric_list
return result
except Exception as e:
print(f"✗ 获取性能指标失败: {e}")
self.monitor_stats["monitor_errors"] += 1
return {}
def get_active_alerts(self) -> Dict[str, Any]:
"""
获取活动警报
Returns:
活动警报字典
"""
try:
with self.monitor_lock:
return self.active_alerts.copy()
except Exception as e:
print(f"✗ 获取活动警报失败: {e}")
self.monitor_stats["monitor_errors"] += 1
return {}
def get_alert_history(self, limit: int = 100) -> List[Dict[str, Any]]:
"""
获取警报历史
Args:
limit: 限制返回的数量
Returns:
警报历史列表
"""
try:
with self.monitor_lock:
history = list(self.alert_history)
return history[-limit:] if len(history) > limit else history
except Exception as e:
print(f"✗ 获取警报历史失败: {e}")
self.monitor_stats["monitor_errors"] += 1
return []
def get_monitor_stats(self) -> Dict[str, Any]:
"""
获取监控统计信息
Returns:
监控统计字典
"""
return {
"state": self.monitor_state.copy(),
"stats": self.monitor_stats.copy(),
"config": self.monitor_config.copy(),
"active_alerts_count": len(self.active_alerts),
"alert_history_count": len(self.alert_history)
}
def reset_stats(self):
"""重置监控统计信息"""
try:
self.monitor_stats = {
"metrics_collected": 0,
"logs_written": 0,
"alerts_generated": 0,
"alerts_resolved": 0,
"performance_checks": 0,
"monitor_errors": 0
}
self.monitor_state["total_logs"] = 0
self.monitor_state["total_alerts"] = 0
self.monitor_state["active_alerts"] = 0
print("✓ 监控统计信息已重置")
except Exception as e:
print(f"✗ 监控统计信息重置失败: {e}")
def set_monitor_config(self, config: Dict[str, Any]) -> bool:
"""
设置监控配置
Args:
config: 监控配置字典
Returns:
是否设置成功
"""
try:
self.monitor_config.update(config)
print(f"✓ 监控配置已更新: {self.monitor_config}")
return True
except Exception as e:
print(f"✗ 监控配置设置失败: {e}")
return False
def get_monitor_config(self) -> Dict[str, Any]:
"""
获取监控配置
Returns:
监控配置字典
"""
return self.monitor_config.copy()
def _trigger_monitor_callback(self, callback_type: str, data: Dict[str, Any]):
"""
触发监控回调
Args:
callback_type: 回调类型
data: 回调数据
"""
try:
if callback_type in self.monitor_callbacks:
for callback in self.monitor_callbacks[callback_type]:
try:
callback(data)
except Exception as e:
print(f"✗ 监控回调执行失败: {callback_type} - {e}")
except Exception as e:
print(f"✗ 监控回调触发失败: {e}")
def register_monitor_callback(self, callback_type: str, callback: callable):
"""
注册监控回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.monitor_callbacks:
self.monitor_callbacks[callback_type].append(callback)
print(f"✓ 监控回调已注册: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 监控回调注册失败: {e}")
def unregister_monitor_callback(self, callback_type: str, callback: callable):
"""
注销监控回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.monitor_callbacks:
if callback in self.monitor_callbacks[callback_type]:
self.monitor_callbacks[callback_type].remove(callback)
print(f"✓ 监控回调已注销: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 监控回调注销失败: {e}")

View File

@ -0,0 +1,391 @@
"""
实时通信插件主文件
为EG引擎提供实时通信功能
"""
import time
from typing import Dict, Any
# 导入各个模块
from .core.websocket_server import WebSocketServer
from .clients.client_manager import ClientManager
from .messaging.message_router import MessageRouter
from .rooms.room_manager import RoomManager
from .protocol.protocol_handler import ProtocolHandler
from .auth.auth_manager import AuthManager
from .serialization.data_serializer import DataSerializer
from .monitoring.communication_monitor import CommunicationMonitor
from .config.comm_config import CommConfig
from .events.event_handler import EventHandler
from .editor.comm_editor import CommEditor
class RealtimeCommunicationPlugin:
"""
实时通信插件主类
整合所有通信功能模块
"""
def __init__(self, engine):
"""
初始化实时通信插件
Args:
engine: EG引擎实例
"""
self.engine = engine
self.enabled = False
self.initialized = False
# 插件信息
self.plugin_info = {
"name": "Realtime Communication Plugin",
"version": "1.0.0",
"author": "EG Plugin System",
"description": "为EG引擎提供实时通信功能"
}
# 插件状态
self.plugin_state = {
"initialized_modules": [],
"last_update": 0.0,
"total_messages": 0,
"active_connections": 0
}
# 插件统计
self.plugin_stats = {
"messages_sent": 0,
"messages_received": 0,
"connections_accepted": 0,
"connections_dropped": 0,
"errors": 0
}
# 功能模块
self.websocket_server = None
self.client_manager = None
self.message_router = None
self.room_manager = None
self.protocol_handler = None
self.auth_manager = None
self.data_serializer = None
self.monitor = None
self.config_manager = None
self.event_handler = None
self.editor = None
print("✓ 实时通信插件已创建")
def initialize(self) -> bool:
"""
初始化插件
Returns:
是否初始化成功
"""
try:
print("正在初始化实时通信插件...")
# 初始化配置管理器
self.config_manager = CommConfig(self)
if self.config_manager.initialize():
self.plugin_state["initialized_modules"].append("config_manager")
else:
print("✗ 配置管理器初始化失败")
return False
# 初始化认证管理器
self.auth_manager = AuthManager(self)
if self.auth_manager.initialize():
self.plugin_state["initialized_modules"].append("auth_manager")
else:
print("✗ 认证管理器初始化失败")
return False
# 初始化数据序列化器
self.data_serializer = DataSerializer(self)
if self.data_serializer.initialize():
self.plugin_state["initialized_modules"].append("data_serializer")
else:
print("✗ 数据序列化器初始化失败")
return False
# 初始化协议处理器
self.protocol_handler = ProtocolHandler(self)
if self.protocol_handler.initialize():
self.plugin_state["initialized_modules"].append("protocol_handler")
else:
print("✗ 协议处理器初始化失败")
return False
# 初始化客户端管理器
self.client_manager = ClientManager(self)
if self.client_manager.initialize():
self.plugin_state["initialized_modules"].append("client_manager")
else:
print("✗ 客户端管理器初始化失败")
return False
# 初始化消息路由器
self.message_router = MessageRouter(self)
if self.message_router.initialize():
self.plugin_state["initialized_modules"].append("message_router")
else:
print("✗ 消息路由器初始化失败")
return False
# 初始化房间管理器
self.room_manager = RoomManager(self)
if self.room_manager.initialize():
self.plugin_state["initialized_modules"].append("room_manager")
else:
print("✗ 房间管理器初始化失败")
return False
# 初始化WebSocket服务器
self.websocket_server = WebSocketServer(self)
if self.websocket_server.initialize():
self.plugin_state["initialized_modules"].append("websocket_server")
else:
print("✗ WebSocket服务器初始化失败")
return False
# 初始化事件处理器
self.event_handler = EventHandler(self)
if self.event_handler.initialize():
self.plugin_state["initialized_modules"].append("event_handler")
else:
print("✗ 事件处理器初始化失败")
return False
# 初始化监控系统
self.monitor = CommunicationMonitor(self)
if self.monitor.initialize():
self.plugin_state["initialized_modules"].append("monitor")
else:
print("✗ 监控系统初始化失败")
return False
# 初始化编辑器接口
self.editor = CommEditor(self)
if self.editor.initialize():
self.plugin_state["initialized_modules"].append("editor")
else:
print("✗ 编辑器接口初始化失败")
return False
self.initialized = True
print("✓ 实时通信插件初始化完成")
return True
except Exception as e:
print(f"✗ 实时通信插件初始化失败: {e}")
self.plugin_stats["errors"] += 1
import traceback
traceback.print_exc()
return False
def enable(self) -> bool:
"""
启用插件
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ 实时通信插件未初始化")
return False
print("正在启用实时通信插件...")
# 启用各模块(按依赖顺序)
modules_to_enable = [
("config_manager", self.config_manager),
("auth_manager", self.auth_manager),
("data_serializer", self.data_serializer),
("protocol_handler", self.protocol_handler),
("client_manager", self.client_manager),
("message_router", self.message_router),
("room_manager", self.room_manager),
("event_handler", self.event_handler),
("monitor", self.monitor),
("editor", self.editor),
("websocket_server", self.websocket_server)
]
for module_name, module in modules_to_enable:
if module and not module.enable():
print(f"{module_name} 启用失败")
return False
elif module:
print(f"{module_name} 已启用")
self.enabled = True
print("✓ 实时通信插件已启用")
return True
except Exception as e:
print(f"✗ 实时通信插件启用失败: {e}")
self.plugin_stats["errors"] += 1
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用插件"""
try:
print("正在禁用实时通信插件...")
# 禁用各模块(按依赖顺序倒序)
modules_to_disable = [
("websocket_server", self.websocket_server),
("editor", self.editor),
("monitor", self.monitor),
("event_handler", self.event_handler),
("room_manager", self.room_manager),
("message_router", self.message_router),
("client_manager", self.client_manager),
("protocol_handler", self.protocol_handler),
("data_serializer", self.data_serializer),
("auth_manager", self.auth_manager),
("config_manager", self.config_manager)
]
for module_name, module in modules_to_disable:
if module:
module.disable()
print(f"{module_name} 已禁用")
self.enabled = False
print("✓ 实时通信插件已禁用")
except Exception as e:
print(f"✗ 实时通信插件禁用失败: {e}")
self.plugin_stats["errors"] += 1
import traceback
traceback.print_exc()
def finalize(self):
"""清理插件资源"""
try:
print("正在清理实时通信插件资源...")
# 禁用插件
if self.enabled:
self.disable()
# 清理各模块
modules_to_finalize = [
self.websocket_server,
self.client_manager,
self.message_router,
self.room_manager,
self.protocol_handler,
self.auth_manager,
self.data_serializer,
self.monitor,
self.config_manager,
self.event_handler,
self.editor
]
for module in modules_to_finalize:
if module:
module.finalize()
self.initialized = False
print("✓ 实时通信插件资源已清理")
except Exception as e:
print(f"✗ 实时通信插件资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新插件状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
current_time = time.time()
# 更新各模块
if self.websocket_server:
self.websocket_server.update(dt)
if self.client_manager:
self.client_manager.update(dt)
if self.message_router:
self.message_router.update(dt)
if self.room_manager:
self.room_manager.update(dt)
if self.monitor:
self.monitor.update(dt)
if self.editor:
self.editor.update(dt)
self.plugin_state["last_update"] = current_time
except Exception as e:
print(f"✗ 实时通信插件更新失败: {e}")
self.plugin_stats["errors"] += 1
import traceback
traceback.print_exc()
def get_plugin_info(self) -> Dict[str, Any]:
"""
获取插件信息
Returns:
插件信息字典
"""
return self.plugin_info.copy()
def get_plugin_state(self) -> Dict[str, Any]:
"""
获取插件状态
Returns:
插件状态字典
"""
return self.plugin_state.copy()
def get_plugin_stats(self) -> Dict[str, Any]:
"""
获取插件统计信息
Returns:
插件统计字典
"""
return {
"info": self.plugin_info.copy(),
"state": self.plugin_state.copy(),
"stats": self.plugin_stats.copy()
}
def reset_stats(self):
"""重置插件统计信息"""
try:
self.plugin_stats = {
"messages_sent": 0,
"messages_received": 0,
"connections_accepted": 0,
"connections_dropped": 0,
"errors": 0
}
print("✓ 插件统计信息已重置")
except Exception as e:
print(f"✗ 插件统计信息重置失败: {e}")
# 插件导出
plugin = RealtimeCommunicationPlugin

View File

@ -0,0 +1,658 @@
"""
协议处理器模块
处理各种通信协议和消息格式
"""
import time
import json
import zlib
import base64
from typing import Dict, Any, List, Optional
class ProtocolHandler:
"""
协议处理器
处理各种通信协议和消息格式
"""
def __init__(self, plugin):
"""
初始化协议处理器
Args:
plugin: 实时通信插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 协议配置
self.protocol_config = {
"supported_protocols": ["websocket", "json", "binary"],
"default_protocol": "json",
"enable_compression": True,
"compression_threshold": 1024, # 1KB
"enable_encryption": False,
"enable_message_validation": True,
"max_message_size": 65536, # 64KB
"enable_fragmentation": True,
"fragment_size": 8192, # 8KB
"enable_checksum": True
}
# 协议状态
self.protocol_state = {
"active_protocols": [],
"compressed_messages": 0,
"encrypted_messages": 0,
"fragmented_messages": 0
}
# 协议统计
self.protocol_stats = {
"messages_encoded": 0,
"messages_decoded": 0,
"bytes_encoded": 0,
"bytes_decoded": 0,
"compression_savings": 0,
"protocol_errors": 0
}
# 协议处理器映射
self.protocol_handlers = {
"json": {
"encode": self._encode_json_message,
"decode": self._decode_json_message
},
"binary": {
"encode": self._encode_binary_message,
"decode": self._decode_binary_message
}
}
# 回调函数
self.protocol_callbacks = {
"message_encoded": [],
"message_decoded": [],
"compression_applied": [],
"encryption_applied": [],
"protocol_error": []
}
# 时间戳记录
self.last_compression = 0.0
self.last_encryption = 0.0
print("✓ 协议处理器已创建")
def initialize(self) -> bool:
"""
初始化协议处理器
Returns:
是否初始化成功
"""
try:
print("正在初始化协议处理器...")
self.initialized = True
print("✓ 协议处理器初始化完成")
return True
except Exception as e:
print(f"✗ 协议处理器初始化失败: {e}")
self.protocol_stats["protocol_errors"] += 1
import traceback
traceback.print_exc()
return False
def enable(self) -> bool:
"""
启用协议处理器
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ 协议处理器未初始化")
return False
self.enabled = True
print("✓ 协议处理器已启用")
return True
except Exception as e:
print(f"✗ 协议处理器启用失败: {e}")
self.protocol_stats["protocol_errors"] += 1
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用协议处理器"""
try:
self.enabled = False
print("✓ 协议处理器已禁用")
except Exception as e:
print(f"✗ 协议处理器禁用失败: {e}")
self.protocol_stats["protocol_errors"] += 1
import traceback
traceback.print_exc()
def finalize(self):
"""清理协议处理器资源"""
try:
# 禁用协议处理器
if self.enabled:
self.disable()
# 清理回调
self.protocol_callbacks.clear()
self.initialized = False
print("✓ 协议处理器资源已清理")
except Exception as e:
print(f"✗ 协议处理器资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新协议处理器状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
# 协议处理器不需要频繁更新
pass
except Exception as e:
print(f"✗ 协议处理器更新失败: {e}")
self.protocol_stats["protocol_errors"] += 1
import traceback
traceback.print_exc()
def encode_message(self, message: Dict[str, Any], protocol: str = None) -> Optional[bytes]:
"""
编码消息
Args:
message: 消息数据
protocol: 协议类型
Returns:
编码后的消息或None
"""
try:
if not self.enabled:
return None
# 使用默认协议或指定协议
if protocol is None:
protocol = self.protocol_config["default_protocol"]
# 验证协议支持
if protocol not in self.protocol_handlers:
print(f"✗ 不支持的协议: {protocol}")
self.protocol_stats["protocol_errors"] += 1
return None
# 验证消息大小
if self.protocol_config["enable_message_validation"]:
message_size = len(json.dumps(message, ensure_ascii=False).encode('utf-8'))
if message_size > self.protocol_config["max_message_size"]:
print(f"✗ 消息过大: {message_size} bytes")
self.protocol_stats["protocol_errors"] += 1
return None
# 获取协议处理器
encoder = self.protocol_handlers[protocol]["encode"]
# 编码消息
encoded_message = encoder(message)
if encoded_message is None:
return None
# 更新统计
self.protocol_stats["messages_encoded"] += 1
self.protocol_stats["bytes_encoded"] += len(encoded_message)
# 触发消息编码回调
self._trigger_protocol_callback("message_encoded", {
"protocol": protocol,
"message_size": len(encoded_message),
"timestamp": time.time()
})
return encoded_message
except Exception as e:
print(f"✗ 消息编码失败: {e}")
self.protocol_stats["protocol_errors"] += 1
return None
def decode_message(self, encoded_message: bytes, protocol: str = None) -> Optional[Dict[str, Any]]:
"""
解码消息
Args:
encoded_message: 编码后的消息
protocol: 协议类型
Returns:
解码后的消息或None
"""
try:
if not self.enabled:
return None
# 使用默认协议或指定协议
if protocol is None:
protocol = self.protocol_config["default_protocol"]
# 验证协议支持
if protocol not in self.protocol_handlers:
print(f"✗ 不支持的协议: {protocol}")
self.protocol_stats["protocol_errors"] += 1
return None
# 获取协议处理器
decoder = self.protocol_handlers[protocol]["decode"]
# 解码消息
decoded_message = decoder(encoded_message)
if decoded_message is None:
return None
# 更新统计
self.protocol_stats["messages_decoded"] += 1
self.protocol_stats["bytes_decoded"] += len(encoded_message)
# 触发消息解码回调
self._trigger_protocol_callback("message_decoded", {
"protocol": protocol,
"message_size": len(encoded_message),
"timestamp": time.time()
})
return decoded_message
except Exception as e:
print(f"✗ 消息解码失败: {e}")
self.protocol_stats["protocol_errors"] += 1
return None
def _encode_json_message(self, message: Dict[str, Any]) -> Optional[bytes]:
"""
JSON消息编码
Args:
message: 消息数据
Returns:
编码后的消息或None
"""
try:
# 序列化为JSON
json_string = json.dumps(message, ensure_ascii=False)
encoded_message = json_string.encode('utf-8')
# 检查是否需要压缩
if (self.protocol_config["enable_compression"] and
len(encoded_message) > self.protocol_config["compression_threshold"]):
compressed_message = zlib.compress(encoded_message)
if len(compressed_message) < len(encoded_message):
# 使用压缩版本
encoded_message = compressed_message
self.protocol_state["compressed_messages"] += 1
self.protocol_stats["compression_savings"] += len(encoded_message) - len(compressed_message)
# 触发压缩应用回调
self._trigger_protocol_callback("compression_applied", {
"original_size": len(json_string.encode('utf-8')),
"compressed_size": len(compressed_message),
"timestamp": time.time()
})
return encoded_message
except Exception as e:
print(f"✗ JSON消息编码失败: {e}")
self.protocol_stats["protocol_errors"] += 1
return None
def _decode_json_message(self, encoded_message: bytes) -> Optional[Dict[str, Any]]:
"""
JSON消息解码
Args:
encoded_message: 编码后的消息
Returns:
解码后的消息或None
"""
try:
# 尝试解压缩
try:
decompressed_message = zlib.decompress(encoded_message)
encoded_message = decompressed_message
except zlib.error:
# 不是压缩数据,使用原始数据
pass
# 解码为JSON
json_string = encoded_message.decode('utf-8')
decoded_message = json.loads(json_string)
return decoded_message
except Exception as e:
print(f"✗ JSON消息解码失败: {e}")
self.protocol_stats["protocol_errors"] += 1
return None
def _encode_binary_message(self, message: Dict[str, Any]) -> Optional[bytes]:
"""
二进制消息编码
Args:
message: 消息数据
Returns:
编码后的消息或None
"""
try:
# 将消息转换为二进制格式(简化实现)
json_string = json.dumps(message, ensure_ascii=False)
binary_message = json_string.encode('utf-8')
# 添加简单的头部信息
header = len(binary_message).to_bytes(4, byteorder='big')
encoded_message = header + binary_message
# 检查是否需要压缩
if (self.protocol_config["enable_compression"] and
len(encoded_message) > self.protocol_config["compression_threshold"]):
compressed_message = zlib.compress(encoded_message)
if len(compressed_message) < len(encoded_message):
# 使用压缩版本
encoded_message = compressed_message
self.protocol_state["compressed_messages"] += 1
self.protocol_stats["compression_savings"] += len(encoded_message) - len(compressed_message)
# 触发压缩应用回调
self._trigger_protocol_callback("compression_applied", {
"original_size": len(header + binary_message),
"compressed_size": len(compressed_message),
"timestamp": time.time()
})
return encoded_message
except Exception as e:
print(f"✗ 二进制消息编码失败: {e}")
self.protocol_stats["protocol_errors"] += 1
return None
def _decode_binary_message(self, encoded_message: bytes) -> Optional[Dict[str, Any]]:
"""
二进制消息解码
Args:
encoded_message: 编码后的消息
Returns:
解码后的消息或None
"""
try:
# 尝试解压缩
try:
decompressed_message = zlib.decompress(encoded_message)
encoded_message = decompressed_message
except zlib.error:
# 不是压缩数据,使用原始数据
pass
# 解析头部信息
if len(encoded_message) < 4:
raise ValueError("消息太短")
message_length = int.from_bytes(encoded_message[:4], byteorder='big')
binary_message = encoded_message[4:4 + message_length]
# 解码为JSON
json_string = binary_message.decode('utf-8')
decoded_message = json.loads(json_string)
return decoded_message
except Exception as e:
print(f"✗ 二进制消息解码失败: {e}")
self.protocol_stats["protocol_errors"] += 1
return None
def fragment_message(self, message: bytes, fragment_size: int = None) -> List[bytes]:
"""
分片消息
Args:
message: 消息数据
fragment_size: 分片大小
Returns:
分片列表
"""
try:
if not self.protocol_config["enable_fragmentation"]:
return [message]
if fragment_size is None:
fragment_size = self.protocol_config["fragment_size"]
fragments = []
for i in range(0, len(message), fragment_size):
fragment = message[i:i + fragment_size]
fragments.append(fragment)
self.protocol_state["fragmented_messages"] += 1
return fragments
except Exception as e:
print(f"✗ 消息分片失败: {e}")
self.protocol_stats["protocol_errors"] += 1
return [message]
def reassemble_message(self, fragments: List[bytes]) -> Optional[bytes]:
"""
重组消息
Args:
fragments: 分片列表
Returns:
重组后的消息或None
"""
try:
if not fragments:
return None
reassembled_message = b''.join(fragments)
return reassembled_message
except Exception as e:
print(f"✗ 消息重组失败: {e}")
self.protocol_stats["protocol_errors"] += 1
return None
def add_protocol_handler(self, protocol: str, encode_func: callable, decode_func: callable) -> bool:
"""
添加协议处理器
Args:
protocol: 协议名称
encode_func: 编码函数
decode_func: 解码函数
Returns:
是否添加成功
"""
try:
self.protocol_handlers[protocol] = {
"encode": encode_func,
"decode": decode_func
}
if protocol not in self.protocol_config["supported_protocols"]:
self.protocol_config["supported_protocols"].append(protocol)
print(f"✓ 协议处理器已添加: {protocol}")
return True
except Exception as e:
print(f"✗ 协议处理器添加失败: {e}")
self.protocol_stats["protocol_errors"] += 1
return False
def remove_protocol_handler(self, protocol: str) -> bool:
"""
移除协议处理器
Args:
protocol: 协议名称
Returns:
是否移除成功
"""
try:
if protocol in self.protocol_handlers:
del self.protocol_handlers[protocol]
if protocol in self.protocol_config["supported_protocols"]:
self.protocol_config["supported_protocols"].remove(protocol)
print(f"✓ 协议处理器已移除: {protocol}")
return True
else:
print(f"✗ 协议处理器不存在: {protocol}")
return False
except Exception as e:
print(f"✗ 协议处理器移除失败: {e}")
self.protocol_stats["protocol_errors"] += 1
return False
def get_protocol_stats(self) -> Dict[str, Any]:
"""
获取协议统计信息
Returns:
协议统计字典
"""
return {
"state": self.protocol_state.copy(),
"stats": self.protocol_stats.copy(),
"config": self.protocol_config.copy()
}
def reset_stats(self):
"""重置协议统计信息"""
try:
self.protocol_stats = {
"messages_encoded": 0,
"messages_decoded": 0,
"bytes_encoded": 0,
"bytes_decoded": 0,
"compression_savings": 0,
"protocol_errors": 0
}
print("✓ 协议统计信息已重置")
except Exception as e:
print(f"✗ 协议统计信息重置失败: {e}")
def set_protocol_config(self, config: Dict[str, Any]) -> bool:
"""
设置协议配置
Args:
config: 协议配置字典
Returns:
是否设置成功
"""
try:
self.protocol_config.update(config)
print(f"✓ 协议配置已更新: {self.protocol_config}")
return True
except Exception as e:
print(f"✗ 协议配置设置失败: {e}")
return False
def get_protocol_config(self) -> Dict[str, Any]:
"""
获取协议配置
Returns:
协议配置字典
"""
return self.protocol_config.copy()
def _trigger_protocol_callback(self, callback_type: str, data: Dict[str, Any]):
"""
触发协议回调
Args:
callback_type: 回调类型
data: 回调数据
"""
try:
if callback_type in self.protocol_callbacks:
for callback in self.protocol_callbacks[callback_type]:
try:
callback(data)
except Exception as e:
print(f"✗ 协议回调执行失败: {callback_type} - {e}")
except Exception as e:
print(f"✗ 协议回调触发失败: {e}")
def register_protocol_callback(self, callback_type: str, callback: callable):
"""
注册协议回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.protocol_callbacks:
self.protocol_callbacks[callback_type].append(callback)
print(f"✓ 协议回调已注册: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 协议回调注册失败: {e}")
def unregister_protocol_callback(self, callback_type: str, callback: callable):
"""
注销协议回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.protocol_callbacks:
if callback in self.protocol_callbacks[callback_type]:
self.protocol_callbacks[callback_type].remove(callback)
print(f"✓ 协议回调已注销: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 协议回调注销失败: {e}")

View File

@ -0,0 +1,894 @@
"""
房间管理器模块
管理通信组和广播消息
"""
import time
import threading
import uuid
from typing import Dict, Any, List, Optional
class RoomManager:
"""
房间管理器
管理通信组和广播消息
"""
def __init__(self, plugin):
"""
初始化房间管理器
Args:
plugin: 实时通信插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 房间配置
self.room_config = {
"max_rooms": 1000,
"max_clients_per_room": 100,
"enable_room_persistence": False,
"room_timeout": 3600, # 1小时无活动房间自动关闭
"enable_room_passwords": True,
"enable_room_visibility": True,
"default_room_settings": {
"max_clients": 50,
"is_public": True,
"allow_spectators": True,
"enable_voice_chat": True
}
}
# 房间状态
self.room_state = {
"total_rooms": 0,
"active_rooms": 0,
"clients_in_rooms": 0
}
# 房间存储
self.rooms = {}
self.client_rooms = {} # 客户端所在房间映射
self.room_lock = threading.RLock()
# 房间统计
self.room_stats = {
"rooms_created": 0,
"rooms_destroyed": 0,
"clients_joined": 0,
"clients_left": 0,
"messages_broadcast": 0,
"errors": 0
}
# 回调函数
self.room_callbacks = {
"room_created": [],
"room_destroyed": [],
"client_joined": [],
"client_left": [],
"room_updated": [],
"room_error": []
}
# 时间戳记录
self.last_cleanup = 0.0
self.last_room_check = 0.0
print("✓ 房间管理器已创建")
def initialize(self) -> bool:
"""
初始化房间管理器
Returns:
是否初始化成功
"""
try:
print("正在初始化房间管理器...")
self.initialized = True
print("✓ 房间管理器初始化完成")
return True
except Exception as e:
print(f"✗ 房间管理器初始化失败: {e}")
self.room_stats["errors"] += 1
import traceback
traceback.print_exc()
return False
def enable(self) -> bool:
"""
启用房间管理器
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ 房间管理器未初始化")
return False
self.enabled = True
print("✓ 房间管理器已启用")
return True
except Exception as e:
print(f"✗ 房间管理器启用失败: {e}")
self.room_stats["errors"] += 1
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用房间管理器"""
try:
self.enabled = False
# 销毁所有房间
self._destroy_all_rooms()
print("✓ 房间管理器已禁用")
except Exception as e:
print(f"✗ 房间管理器禁用失败: {e}")
self.room_stats["errors"] += 1
import traceback
traceback.print_exc()
def finalize(self):
"""清理房间管理器资源"""
try:
# 禁用房间管理器
if self.enabled:
self.disable()
# 清理回调
self.room_callbacks.clear()
self.initialized = False
print("✓ 房间管理器资源已清理")
except Exception as e:
print(f"✗ 房间管理器资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新房间管理器状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
current_time = time.time()
# 定期清理过期房间
if current_time - self.last_cleanup > 60.0: # 每分钟清理一次
self._cleanup_expired_rooms(current_time)
self.last_cleanup = current_time
except Exception as e:
print(f"✗ 房间管理器更新失败: {e}")
self.room_stats["errors"] += 1
import traceback
traceback.print_exc()
def _cleanup_expired_rooms(self, current_time: float):
"""清理过期房间"""
try:
expired_rooms = []
with self.room_lock:
for room_id, room_data in self.rooms.items():
# 检查房间是否超时
if current_time - room_data["last_activity"] > self.room_config["room_timeout"]:
# 检查房间是否为空
if len(room_data["clients"]) == 0:
expired_rooms.append(room_id)
# 销毁过期房间
for room_id in expired_rooms:
self.destroy_room(room_id)
except Exception as e:
print(f"✗ 过期房间清理失败: {e}")
self.room_stats["errors"] += 1
def _destroy_all_rooms(self):
"""销毁所有房间"""
try:
with self.room_lock:
room_ids = list(self.rooms.keys())
for room_id in room_ids:
self.destroy_room(room_id)
except Exception as e:
print(f"✗ 销毁所有房间失败: {e}")
self.room_stats["errors"] += 1
def create_room(self, room_name: str = None, room_settings: Dict[str, Any] = None,
room_password: str = None) -> Optional[str]:
"""
创建房间
Args:
room_name: 房间名称
room_settings: 房间设置
room_password: 房间密码
Returns:
房间ID或None
"""
try:
if not self.enabled:
return None
# 检查房间数量限制
with self.room_lock:
if len(self.rooms) >= self.room_config["max_rooms"]:
print("✗ 房间数量已达上限")
return None
# 生成房间ID
room_id = str(uuid.uuid4())
# 使用默认设置或传入设置
settings = self.room_config["default_room_settings"].copy()
if room_settings:
settings.update(room_settings)
# 创建房间数据
room_data = {
"room_id": room_id,
"room_name": room_name or f"房间-{room_id[:8]}",
"settings": settings,
"password": room_password,
"clients": {}, # 客户端ID到客户端数据的映射
"host_client_id": None,
"created_time": time.time(),
"last_activity": time.time(),
"room_state": {}, # 房间状态数据
"custom_data": {} # 自定义房间数据
}
# 添加到房间列表
with self.room_lock:
self.rooms[room_id] = room_data
self.room_state["total_rooms"] += 1
self.room_state["active_rooms"] += 1
self.room_stats["rooms_created"] += 1
# 触发房间创建回调
self._trigger_room_callback("room_created", {
"room_id": room_id,
"room_name": room_data["room_name"],
"settings": settings,
"timestamp": room_data["created_time"]
})
print(f"✓ 房间已创建: {room_id} ({room_data['room_name']})")
return room_id
except Exception as e:
print(f"✗ 房间创建失败: {e}")
self.room_stats["errors"] += 1
return None
def destroy_room(self, room_id: str) -> bool:
"""
销毁房间
Args:
room_id: 房间ID
Returns:
是否销毁成功
"""
try:
if not self.enabled:
return False
# 检查房间是否存在
with self.room_lock:
if room_id not in self.rooms:
print(f"✗ 房间不存在: {room_id}")
return False
room_data = self.rooms[room_id]
# 通知房间内所有客户端
for client_id in list(room_data["clients"].keys()):
self._notify_client_room_destroyed(client_id, room_id)
# 移除房间
del self.rooms[room_id]
self.room_state["active_rooms"] -= 1
self.room_stats["rooms_destroyed"] += 1
# 触发房间销毁回调
self._trigger_room_callback("room_destroyed", {
"room_id": room_id,
"room_name": room_data["room_name"],
"timestamp": time.time()
})
print(f"✓ 房间已销毁: {room_id}")
return True
except Exception as e:
print(f"✗ 房间销毁失败: {e}")
self.room_stats["errors"] += 1
return False
def _notify_client_room_destroyed(self, client_id: str, room_id: str):
"""
通知客户端房间被销毁
Args:
client_id: 客户端ID
room_id: 房间ID
"""
try:
# 从客户端房间映射中移除
if client_id in self.client_rooms:
del self.client_rooms[client_id]
# 发送房间销毁通知
if self.plugin.websocket_server:
destroy_message = {
"type": "room_destroyed",
"room_id": room_id,
"timestamp": time.time()
}
self.plugin.websocket_server.send_message_to_client(client_id, destroy_message)
except Exception as e:
print(f"✗ 通知客户端房间销毁失败: {e}")
self.room_stats["errors"] += 1
def add_client_to_room(self, room_id: str, client_id: str, client_data: Dict[str, Any] = None) -> bool:
"""
添加客户端到房间
Args:
room_id: 房间ID
client_id: 客户端ID
client_data: 客户端数据
Returns:
是否添加成功
"""
try:
if not self.enabled:
return False
# 检查客户端是否已认证
if self.plugin.client_manager and not self.plugin.client_manager.is_client_authenticated(client_id):
print(f"✗ 客户端未认证: {client_id}")
return False
# 检查房间是否存在
with self.room_lock:
if room_id not in self.rooms:
print(f"✗ 房间不存在: {room_id}")
return False
room_data = self.rooms[room_id]
# 检查房间是否已满
if len(room_data["clients"]) >= room_data["settings"]["max_clients"]:
print(f"✗ 房间已满: {room_id}")
return False
# 检查房间密码
if room_data["password"] and not self._verify_room_password(room_id, client_data):
print(f"✗ 房间密码错误: {room_id}")
return False
# 添加客户端到房间
client_info = client_data or {}
client_info["join_time"] = time.time()
client_info["last_activity"] = time.time()
room_data["clients"][client_id] = client_info
room_data["last_activity"] = time.time()
# 设置房间主机(如果是第一个客户端)
if room_data["host_client_id"] is None:
room_data["host_client_id"] = client_id
# 更新客户端房间映射
self.client_rooms[client_id] = room_id
self.room_state["clients_in_rooms"] += 1
self.room_stats["clients_joined"] += 1
# 触发客户端加入回调
self._trigger_room_callback("client_joined", {
"room_id": room_id,
"room_name": room_data["room_name"],
"client_id": client_id,
"timestamp": time.time()
})
# 通知客户端加入成功
join_success_message = {
"type": "room_join_success",
"room_id": room_id,
"room_name": room_data["room_name"],
"timestamp": time.time()
}
if self.plugin.websocket_server:
self.plugin.websocket_server.send_message_to_client(client_id, join_success_message)
print(f"✓ 客户端已加入房间: {client_id} -> {room_id}")
return True
except Exception as e:
print(f"✗ 添加客户端到房间失败: {e}")
self.room_stats["errors"] += 1
return False
def remove_client_from_room(self, room_id: str, client_id: str) -> bool:
"""
从房间移除客户端
Args:
room_id: 房间ID
client_id: 客户端ID
Returns:
是否移除成功
"""
try:
if not self.enabled:
return False
# 检查房间是否存在
with self.room_lock:
if room_id not in self.rooms:
print(f"✗ 房间不存在: {room_id}")
return False
room_data = self.rooms[room_id]
# 检查客户端是否在房间中
if client_id not in room_data["clients"]:
print(f"✗ 客户端不在房间中: {client_id}")
return False
# 移除客户端
del room_data["clients"][client_id]
room_data["last_activity"] = time.time()
# 更新主机(如果移除的是主机)
if room_data["host_client_id"] == client_id:
if room_data["clients"]:
# 选择第一个客户端作为新主机
room_data["host_client_id"] = next(iter(room_data["clients"]))
else:
room_data["host_client_id"] = None
# 移除客户端房间映射
if client_id in self.client_rooms:
del self.client_rooms[client_id]
self.room_state["clients_in_rooms"] -= 1
self.room_stats["clients_left"] += 1
# 触发客户端离开回调
self._trigger_room_callback("client_left", {
"room_id": room_id,
"room_name": room_data["room_name"],
"client_id": client_id,
"timestamp": time.time()
})
# 通知客户端离开成功
leave_success_message = {
"type": "room_leave_success",
"room_id": room_id,
"timestamp": time.time()
}
if self.plugin.websocket_server:
self.plugin.websocket_server.send_message_to_client(client_id, leave_success_message)
# 如果房间为空,销毁房间
if len(room_data["clients"]) == 0:
self.destroy_room(room_id)
print(f"✓ 客户端已离开房间: {client_id} <- {room_id}")
return True
except Exception as e:
print(f"✗ 从房间移除客户端失败: {e}")
self.room_stats["errors"] += 1
return False
def _verify_room_password(self, room_id: str, client_data: Dict[str, Any]) -> bool:
"""
验证房间密码
Args:
room_id: 房间ID
client_data: 客户端数据
Returns:
密码是否正确
"""
try:
if not self.room_config["enable_room_passwords"]:
return True
with self.room_lock:
if room_id not in self.rooms:
return False
room_data = self.rooms[room_id]
if not room_data["password"]:
return True
client_password = client_data.get("password") if client_data else None
return client_password == room_data["password"]
except Exception as e:
print(f"✗ 房间密码验证失败: {e}")
self.room_stats["errors"] += 1
return False
def get_room_info(self, room_id: str) -> Optional[Dict[str, Any]]:
"""
获取房间信息
Args:
room_id: 房间ID
Returns:
房间信息或None
"""
try:
with self.room_lock:
if room_id in self.rooms:
room_data = self.rooms[room_id]
# 返回不包含敏感信息的房间信息
safe_room_data = {
"room_id": room_data["room_id"],
"room_name": room_data["room_name"],
"settings": room_data["settings"],
"client_count": len(room_data["clients"]),
"has_password": bool(room_data["password"]),
"host_client_id": room_data["host_client_id"],
"created_time": room_data["created_time"],
"last_activity": room_data["last_activity"]
}
return safe_room_data
else:
return None
except Exception as e:
print(f"✗ 获取房间信息失败: {e}")
self.room_stats["errors"] += 1
return None
def get_all_rooms(self) -> List[Dict[str, Any]]:
"""
获取所有房间信息
Returns:
房间信息列表
"""
try:
rooms_info = []
with self.room_lock:
for room_id, room_data in self.rooms.items():
# 只返回公开房间或用户所在的房间
if room_data["settings"].get("is_public", True):
safe_room_data = {
"room_id": room_data["room_id"],
"room_name": room_data["room_name"],
"settings": room_data["settings"],
"client_count": len(room_data["clients"]),
"has_password": bool(room_data["password"]),
"host_client_id": room_data["host_client_id"],
"created_time": room_data["created_time"],
"last_activity": room_data["last_activity"]
}
rooms_info.append(safe_room_data)
return rooms_info
except Exception as e:
print(f"✗ 获取所有房间信息失败: {e}")
self.room_stats["errors"] += 1
return []
def get_client_room(self, client_id: str) -> Optional[str]:
"""
获取客户端所在房间
Args:
client_id: 客户端ID
Returns:
房间ID或None
"""
try:
return self.client_rooms.get(client_id)
except Exception as e:
print(f"✗ 获取客户端房间失败: {e}")
self.room_stats["errors"] += 1
return None
def get_room_clients(self, room_id: str) -> List[str]:
"""
获取房间内所有客户端
Args:
room_id: 房间ID
Returns:
客户端ID列表
"""
try:
with self.room_lock:
if room_id in self.rooms:
return list(self.rooms[room_id]["clients"].keys())
else:
return []
except Exception as e:
print(f"✗ 获取房间客户端失败: {e}")
self.room_stats["errors"] += 1
return []
def update_room_state(self, room_id: str, state_data: Dict[str, Any]) -> bool:
"""
更新房间状态
Args:
room_id: 房间ID
state_data: 状态数据
Returns:
是否更新成功
"""
try:
with self.room_lock:
if room_id not in self.rooms:
return False
self.rooms[room_id]["room_state"].update(state_data)
self.rooms[room_id]["last_activity"] = time.time()
# 触发房间更新回调
self._trigger_room_callback("room_updated", {
"room_id": room_id,
"state_data": state_data,
"timestamp": time.time()
})
return True
except Exception as e:
print(f"✗ 更新房间状态失败: {e}")
self.room_stats["errors"] += 1
return False
def broadcast_to_room(self, room_id: str, message_data: Dict[str, Any],
exclude_client_id: str = None) -> bool:
"""
向房间内所有客户端广播消息
Args:
room_id: 房间ID
message_data: 消息数据
exclude_client_id: 要排除的客户端ID
Returns:
是否广播成功
"""
try:
if not self.enabled:
return False
with self.room_lock:
if room_id not in self.rooms:
return False
room_data = self.rooms[room_id]
success_count = 0
# 向房间内每个客户端发送消息
for client_id in room_data["clients"]:
# 跳过排除的客户端
if client_id == exclude_client_id:
continue
# 发送消息
if self.plugin.websocket_server:
send_success = self.plugin.websocket_server.send_message_to_client(
client_id, message_data)
if send_success:
success_count += 1
if success_count > 0:
self.room_stats["messages_broadcast"] += 1
return success_count > 0
except Exception as e:
print(f"✗ 房间广播失败: {e}")
self.room_stats["errors"] += 1
return False
def set_room_custom_data(self, room_id: str, key: str, value: Any) -> bool:
"""
设置房间自定义数据
Args:
room_id: 房间ID
key: 数据键
value: 数据值
Returns:
是否设置成功
"""
try:
with self.room_lock:
if room_id not in self.rooms:
return False
self.rooms[room_id]["custom_data"][key] = value
return True
except Exception as e:
print(f"✗ 设置房间自定义数据失败: {e}")
self.room_stats["errors"] += 1
return False
def get_room_custom_data(self, room_id: str, key: str, default: Any = None) -> Any:
"""
获取房间自定义数据
Args:
room_id: 房间ID
key: 数据键
default: 默认值
Returns:
数据值或默认值
"""
try:
with self.room_lock:
if room_id not in self.rooms:
return default
return self.rooms[room_id]["custom_data"].get(key, default)
except Exception as e:
print(f"✗ 获取房间自定义数据失败: {e}")
self.room_stats["errors"] += 1
return default
def get_room_stats(self) -> Dict[str, Any]:
"""
获取房间统计信息
Returns:
房间统计字典
"""
return {
"state": self.room_state.copy(),
"stats": self.room_stats.copy(),
"config": self.room_config.copy(),
"current_rooms": len(self.rooms),
"current_clients_in_rooms": len(self.client_rooms)
}
def reset_stats(self):
"""重置房间统计信息"""
try:
self.room_stats = {
"rooms_created": 0,
"rooms_destroyed": 0,
"clients_joined": 0,
"clients_left": 0,
"messages_broadcast": 0,
"errors": 0
}
print("✓ 房间统计信息已重置")
except Exception as e:
print(f"✗ 房间统计信息重置失败: {e}")
def set_room_config(self, config: Dict[str, Any]) -> bool:
"""
设置房间配置
Args:
config: 房间配置字典
Returns:
是否设置成功
"""
try:
self.room_config.update(config)
print(f"✓ 房间配置已更新: {self.room_config}")
return True
except Exception as e:
print(f"✗ 房间配置设置失败: {e}")
return False
def get_room_config(self) -> Dict[str, Any]:
"""
获取房间配置
Returns:
房间配置字典
"""
return self.room_config.copy()
def _trigger_room_callback(self, callback_type: str, data: Dict[str, Any]):
"""
触发房间回调
Args:
callback_type: 回调类型
data: 回调数据
"""
try:
if callback_type in self.room_callbacks:
for callback in self.room_callbacks[callback_type]:
try:
callback(data)
except Exception as e:
print(f"✗ 房间回调执行失败: {callback_type} - {e}")
except Exception as e:
print(f"✗ 房间回调触发失败: {e}")
def register_room_callback(self, callback_type: str, callback: callable):
"""
注册房间回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.room_callbacks:
self.room_callbacks[callback_type].append(callback)
print(f"✓ 房间回调已注册: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 房间回调注册失败: {e}")
def unregister_room_callback(self, callback_type: str, callback: callable):
"""
注销房间回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.room_callbacks:
if callback in self.room_callbacks[callback_type]:
self.room_callbacks[callback_type].remove(callback)
print(f"✓ 房间回调已注销: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 房间回调注销失败: {e}")

View File

@ -0,0 +1,773 @@
"""
数据序列化器模块
将消息序列化为网络数据
"""
import time
import json
import pickle
import zlib
from typing import Dict, Any, List, Optional, Union
class DataSerializer:
"""
数据序列化器
将消息序列化为网络数据
"""
def __init__(self, plugin):
"""
初始化数据序列化器
Args:
plugin: 实时通信插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 序列化配置
self.serializer_config = {
"default_format": "json",
"supported_formats": ["json", "pickle", "binary"],
"enable_compression": True,
"compression_threshold": 1024, # 1KB
"enable_caching": True,
"cache_size": 1000,
"enable_incremental_encoding": True,
"enable_type_preservation": True
}
# 序列化状态
self.serializer_state = {
"cached_objects": 0,
"compressed_objects": 0,
"serialized_objects": 0
}
# 序列化统计
self.serializer_stats = {
"objects_serialized": 0,
"objects_deserialized": 0,
"bytes_serialized": 0,
"bytes_deserialized": 0,
"compression_savings": 0,
"cache_hits": 0,
"cache_misses": 0,
"serializer_errors": 0
}
# 缓存管理
self.serialization_cache = {}
self.cache_timestamps = {}
# 序列化器映射
self.serializers = {
"json": {
"serialize": self._serialize_json,
"deserialize": self._deserialize_json
},
"pickle": {
"serialize": self._serialize_pickle,
"deserialize": self._deserialize_pickle
},
"binary": {
"serialize": self._serialize_binary,
"deserialize": self._deserialize_binary
}
}
# 回调函数
self.serializer_callbacks = {
"object_serialized": [],
"object_deserialized": [],
"compression_applied": [],
"cache_hit": [],
"serializer_error": []
}
# 时间戳记录
self.last_serialization = 0.0
self.last_cache_cleanup = 0.0
print("✓ 数据序列化器已创建")
def initialize(self) -> bool:
"""
初始化数据序列化器
Returns:
是否初始化成功
"""
try:
print("正在初始化数据序列化器...")
self.initialized = True
print("✓ 数据序列化器初始化完成")
return True
except Exception as e:
print(f"✗ 数据序列化器初始化失败: {e}")
self.serializer_stats["serializer_errors"] += 1
import traceback
traceback.print_exc()
return False
def enable(self) -> bool:
"""
启用数据序列化器
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ 数据序列化器未初始化")
return False
self.enabled = True
print("✓ 数据序列化器已启用")
return True
except Exception as e:
print(f"✗ 数据序列化器启用失败: {e}")
self.serializer_stats["serializer_errors"] += 1
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用数据序列化器"""
try:
self.enabled = False
# 清理缓存
self.serialization_cache.clear()
self.cache_timestamps.clear()
print("✓ 数据序列化器已禁用")
except Exception as e:
print(f"✗ 数据序列化器禁用失败: {e}")
self.serializer_stats["serializer_errors"] += 1
import traceback
traceback.print_exc()
def finalize(self):
"""清理数据序列化器资源"""
try:
# 禁用数据序列化器
if self.enabled:
self.disable()
# 清理回调
self.serializer_callbacks.clear()
self.initialized = False
print("✓ 数据序列化器资源已清理")
except Exception as e:
print(f"✗ 数据序列化器资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新数据序列化器状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
current_time = time.time()
# 定期清理缓存
if current_time - self.last_cache_cleanup > 300: # 每5分钟清理一次
self._cleanup_cache(current_time)
self.last_cache_cleanup = current_time
self.last_serialization = current_time
except Exception as e:
print(f"✗ 数据序列化器更新失败: {e}")
self.serializer_stats["serializer_errors"] += 1
import traceback
traceback.print_exc()
def _cleanup_cache(self, current_time: float):
"""清理缓存"""
try:
if not self.serializer_config["enable_caching"]:
return
expired_keys = []
for key, timestamp in self.cache_timestamps.items():
# 缓存对象超过10分钟未使用则清除
if current_time - timestamp > 600:
expired_keys.append(key)
for key in expired_keys:
if key in self.serialization_cache:
del self.serialization_cache[key]
if key in self.cache_timestamps:
del self.cache_timestamps[key]
self.serializer_state["cached_objects"] = len(self.serialization_cache)
except Exception as e:
print(f"✗ 缓存清理失败: {e}")
self.serializer_stats["serializer_errors"] += 1
def serialize(self, obj: Any, format: str = None) -> Optional[bytes]:
"""
序列化对象
Args:
obj: 要序列化的对象
format: 序列化格式
Returns:
序列化后的字节数据或None
"""
try:
if not self.enabled:
return None
# 使用默认格式或指定格式
if format is None:
format = self.serializer_config["default_format"]
# 验证格式支持
if format not in self.serializers:
print(f"✗ 不支持的序列化格式: {format}")
self.serializer_stats["serializer_errors"] += 1
return None
# 检查缓存
cache_key = None
if self.serializer_config["enable_caching"]:
cache_key = self._generate_cache_key(obj, format)
if cache_key in self.serialization_cache:
self.serializer_stats["cache_hits"] += 1
self.cache_timestamps[cache_key] = time.time()
# 触发缓存命中回调
self._trigger_serializer_callback("cache_hit", {
"cache_key": cache_key,
"format": format,
"timestamp": time.time()
})
return self.serialization_cache[cache_key]
else:
self.serializer_stats["cache_misses"] += 1
# 获取序列化器
serializer = self.serializers[format]["serialize"]
# 序列化对象
serialized_data = serializer(obj)
if serialized_data is None:
return None
# 更新统计
self.serializer_stats["objects_serialized"] += 1
self.serializer_stats["bytes_serialized"] += len(serialized_data)
self.serializer_state["serialized_objects"] += 1
# 缓存结果
if (self.serializer_config["enable_caching"] and
cache_key and
len(self.serialization_cache) < self.serializer_config["cache_size"]):
self.serialization_cache[cache_key] = serialized_data
self.cache_timestamps[cache_key] = time.time()
self.serializer_state["cached_objects"] = len(self.serialization_cache)
# 触发对象序列化回调
self._trigger_serializer_callback("object_serialized", {
"format": format,
"data_size": len(serialized_data),
"timestamp": time.time()
})
return serialized_data
except Exception as e:
print(f"✗ 对象序列化失败: {e}")
self.serializer_stats["serializer_errors"] += 1
return None
def deserialize(self, data: bytes, format: str = None) -> Optional[Any]:
"""
反序列化对象
Args:
data: 要反序列化的字节数据
format: 序列化格式
Returns:
反序列化后的对象或None
"""
try:
if not self.enabled:
return None
# 使用默认格式或指定格式
if format is None:
format = self.serializer_config["default_format"]
# 验证格式支持
if format not in self.serializers:
print(f"✗ 不支持的反序列化格式: {format}")
self.serializer_stats["serializer_errors"] += 1
return None
# 获取反序列化器
deserializer = self.serializers[format]["deserialize"]
# 反序列化对象
deserialized_obj = deserializer(data)
if deserialized_obj is None:
return None
# 更新统计
self.serializer_stats["objects_deserialized"] += 1
self.serializer_stats["bytes_deserialized"] += len(data)
# 触发对象反序列化回调
self._trigger_serializer_callback("object_deserialized", {
"format": format,
"data_size": len(data),
"timestamp": time.time()
})
return deserialized_obj
except Exception as e:
print(f"✗ 对象反序列化失败: {e}")
self.serializer_stats["serializer_errors"] += 1
return None
def _serialize_json(self, obj: Any) -> Optional[bytes]:
"""
JSON序列化
Args:
obj: 要序列化的对象
Returns:
序列化后的字节数据或None
"""
try:
# 序列化为JSON字符串
json_string = json.dumps(obj, ensure_ascii=False, default=self._json_default)
serialized_data = json_string.encode('utf-8')
# 检查是否需要压缩
if (self.serializer_config["enable_compression"] and
len(serialized_data) > self.serializer_config["compression_threshold"]):
compressed_data = zlib.compress(serialized_data)
if len(compressed_data) < len(serialized_data):
# 使用压缩版本
serialized_data = compressed_data
self.serializer_state["compressed_objects"] += 1
self.serializer_stats["compression_savings"] += len(serialized_data) - len(compressed_data)
# 触发压缩应用回调
self._trigger_serializer_callback("compression_applied", {
"original_size": len(json_string.encode('utf-8')),
"compressed_size": len(compressed_data),
"compression_ratio": len(compressed_data) / len(json_string.encode('utf-8')),
"timestamp": time.time()
})
return serialized_data
except Exception as e:
print(f"✗ JSON序列化失败: {e}")
self.serializer_stats["serializer_errors"] += 1
return None
def _deserialize_json(self, data: bytes) -> Optional[Any]:
"""
JSON反序列化
Args:
data: 要反序列化的字节数据
Returns:
反序列化后的对象或None
"""
try:
# 尝试解压缩
try:
decompressed_data = zlib.decompress(data)
data = decompressed_data
except zlib.error:
# 不是压缩数据,使用原始数据
pass
# 解码为JSON
json_string = data.decode('utf-8')
deserialized_obj = json.loads(json_string)
return deserialized_obj
except Exception as e:
print(f"✗ JSON反序列化失败: {e}")
self.serializer_stats["serializer_errors"] += 1
return None
def _json_default(self, obj):
"""
JSON默认序列化方法
Args:
obj: 要序列化的对象
Returns:
可序列化的对象
"""
# 处理不能直接序列化的对象
return str(obj)
def _serialize_pickle(self, obj: Any) -> Optional[bytes]:
"""
Pickle序列化
Args:
obj: 要序列化的对象
Returns:
序列化后的字节数据或None
"""
try:
# 序列化为pickle数据
pickle_data = pickle.dumps(obj)
# 检查是否需要压缩
if (self.serializer_config["enable_compression"] and
len(pickle_data) > self.serializer_config["compression_threshold"]):
compressed_data = zlib.compress(pickle_data)
if len(compressed_data) < len(pickle_data):
# 使用压缩版本
pickle_data = compressed_data
self.serializer_state["compressed_objects"] += 1
self.serializer_stats["compression_savings"] += len(pickle_data) - len(compressed_data)
# 触发压缩应用回调
self._trigger_serializer_callback("compression_applied", {
"original_size": len(pickle.dumps(obj)),
"compressed_size": len(compressed_data),
"compression_ratio": len(compressed_data) / len(pickle.dumps(obj)),
"timestamp": time.time()
})
return pickle_data
except Exception as e:
print(f"✗ Pickle序列化失败: {e}")
self.serializer_stats["serializer_errors"] += 1
return None
def _deserialize_pickle(self, data: bytes) -> Optional[Any]:
"""
Pickle反序列化
Args:
data: 要反序列化的字节数据
Returns:
反序列化后的对象或None
"""
try:
# 尝试解压缩
try:
decompressed_data = zlib.decompress(data)
data = decompressed_data
except zlib.error:
# 不是压缩数据,使用原始数据
pass
# 反序列化pickle数据
deserialized_obj = pickle.loads(data)
return deserialized_obj
except Exception as e:
print(f"✗ Pickle反序列化失败: {e}")
self.serializer_stats["serializer_errors"] += 1
return None
def _serialize_binary(self, obj: Any) -> Optional[bytes]:
"""
二进制序列化
Args:
obj: 要序列化的对象
Returns:
序列化后的字节数据或None
"""
try:
# 简化实现将对象转换为JSON再编码为二进制
json_string = json.dumps(obj, ensure_ascii=False, default=self._json_default)
binary_data = json_string.encode('utf-8')
# 添加简单的头部信息
header = len(binary_data).to_bytes(4, byteorder='big')
serialized_data = header + binary_data
# 检查是否需要压缩
if (self.serializer_config["enable_compression"] and
len(serialized_data) > self.serializer_config["compression_threshold"]):
compressed_data = zlib.compress(serialized_data)
if len(compressed_data) < len(serialized_data):
# 使用压缩版本
serialized_data = compressed_data
self.serializer_state["compressed_objects"] += 1
self.serializer_stats["compression_savings"] += len(serialized_data) - len(compressed_data)
# 触发压缩应用回调
self._trigger_serializer_callback("compression_applied", {
"original_size": len(header + binary_data),
"compressed_size": len(compressed_data),
"compression_ratio": len(compressed_data) / len(header + binary_data),
"timestamp": time.time()
})
return serialized_data
except Exception as e:
print(f"✗ 二进制序列化失败: {e}")
self.serializer_stats["serializer_errors"] += 1
return None
def _deserialize_binary(self, data: bytes) -> Optional[Any]:
"""
二进制反序列化
Args:
data: 要反序列化的字节数据
Returns:
反序列化后的对象或None
"""
try:
# 尝试解压缩
try:
decompressed_data = zlib.decompress(data)
data = decompressed_data
except zlib.error:
# 不是压缩数据,使用原始数据
pass
# 解析头部信息
if len(data) < 4:
raise ValueError("数据太短")
message_length = int.from_bytes(data[:4], byteorder='big')
binary_data = data[4:4 + message_length]
# 解码为JSON
json_string = binary_data.decode('utf-8')
deserialized_obj = json.loads(json_string)
return deserialized_obj
except Exception as e:
print(f"✗ 二进制反序列化失败: {e}")
self.serializer_stats["serializer_errors"] += 1
return None
def _generate_cache_key(self, obj: Any, format: str) -> str:
"""
生成缓存键
Args:
obj: 对象
format: 格式
Returns:
缓存键
"""
try:
# 简化实现:使用对象的字符串表示和格式生成键
obj_str = str(obj)
cache_key = f"{format}:{hash(obj_str)}:{len(obj_str)}"
return cache_key
except Exception as e:
print(f"✗ 缓存键生成失败: {e}")
self.serializer_stats["serializer_errors"] += 1
return f"error_key_{int(time.time() * 1000000)}"
def add_serializer(self, format: str, serialize_func: callable, deserialize_func: callable) -> bool:
"""
添加序列化器
Args:
format: 格式名称
serialize_func: 序列化函数
deserialize_func: 反序列化函数
Returns:
是否添加成功
"""
try:
self.serializers[format] = {
"serialize": serialize_func,
"deserialize": deserialize_func
}
if format not in self.serializer_config["supported_formats"]:
self.serializer_config["supported_formats"].append(format)
print(f"✓ 序列化器已添加: {format}")
return True
except Exception as e:
print(f"✗ 序列化器添加失败: {e}")
self.serializer_stats["serializer_errors"] += 1
return False
def remove_serializer(self, format: str) -> bool:
"""
移除序列化器
Args:
format: 格式名称
Returns:
是否移除成功
"""
try:
if format in self.serializers:
del self.serializers[format]
if format in self.serializer_config["supported_formats"]:
self.serializer_config["supported_formats"].remove(format)
print(f"✓ 序列化器已移除: {format}")
return True
else:
print(f"✗ 序列化器不存在: {format}")
return False
except Exception as e:
print(f"✗ 序列化器移除失败: {e}")
self.serializer_stats["serializer_errors"] += 1
return False
def get_serializer_stats(self) -> Dict[str, Any]:
"""
获取序列化统计信息
Returns:
序列化统计字典
"""
return {
"state": self.serializer_state.copy(),
"stats": self.serializer_stats.copy(),
"config": self.serializer_config.copy(),
"cache_size": len(self.serialization_cache)
}
def reset_stats(self):
"""重置序列化统计信息"""
try:
self.serializer_stats = {
"objects_serialized": 0,
"objects_deserialized": 0,
"bytes_serialized": 0,
"bytes_deserialized": 0,
"compression_savings": 0,
"cache_hits": 0,
"cache_misses": 0,
"serializer_errors": 0
}
print("✓ 序列化统计信息已重置")
except Exception as e:
print(f"✗ 序列化统计信息重置失败: {e}")
def set_serializer_config(self, config: Dict[str, Any]) -> bool:
"""
设置序列化配置
Args:
config: 序列化配置字典
Returns:
是否设置成功
"""
try:
self.serializer_config.update(config)
print(f"✓ 序列化配置已更新: {self.serializer_config}")
return True
except Exception as e:
print(f"✗ 序列化配置设置失败: {e}")
return False
def get_serializer_config(self) -> Dict[str, Any]:
"""
获取序列化配置
Returns:
序列化配置字典
"""
return self.serializer_config.copy()
def _trigger_serializer_callback(self, callback_type: str, data: Dict[str, Any]):
"""
触发序列化回调
Args:
callback_type: 回调类型
data: 回调数据
"""
try:
if callback_type in self.serializer_callbacks:
for callback in self.serializer_callbacks[callback_type]:
try:
callback(data)
except Exception as e:
print(f"✗ 序列化回调执行失败: {callback_type} - {e}")
except Exception as e:
print(f"✗ 序列化回调触发失败: {e}")
def register_serializer_callback(self, callback_type: str, callback: callable):
"""
注册序列化回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.serializer_callbacks:
self.serializer_callbacks[callback_type].append(callback)
print(f"✓ 序列化回调已注册: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 序列化回调注册失败: {e}")
def unregister_serializer_callback(self, callback_type: str, callback: callable):
"""
注销序列化回调
Args:
callback_type: 回调类型
callback: 回调函数
"""
try:
if callback_type in self.serializer_callbacks:
if callback in self.serializer_callbacks[callback_type]:
self.serializer_callbacks[callback_type].remove(callback)
print(f"✓ 序列化回调已注销: {callback_type}")
else:
print(f"✗ 无效的回调类型: {callback_type}")
except Exception as e:
print(f"✗ 序列化回调注销失败: {e}")

View File

@ -0,0 +1,248 @@
"""
通信工具类模块
提供实用工具函数
"""
import time
import hashlib
import json
from typing import Dict, Any, List, Optional
class CommUtils:
"""
通信工具类
提供实用工具函数
"""
@staticmethod
def generate_unique_id(prefix: str = "") -> str:
"""
生成唯一ID
Args:
prefix: ID前缀
Returns:
生成的唯一ID
"""
try:
timestamp = int(time.time() * 1000000) # 微秒时间戳
unique_id = f"{prefix}{timestamp}" if prefix else str(timestamp)
return unique_id
except Exception as e:
print(f"✗ 唯一ID生成失败: {e}")
return f"error_id_{int(time.time() * 1000000)}"
@staticmethod
def calculate_checksum(data: bytes) -> str:
"""
计算数据校验和
Args:
data: 要计算校验和的数据
Returns:
校验和字符串
"""
try:
checksum = hashlib.md5(data).hexdigest()
return checksum
except Exception as e:
print(f"✗ 校验和计算失败: {e}")
return ""
@staticmethod
def format_bytes(bytes_count: int) -> str:
"""
格式化字节数
Args:
bytes_count: 字节数
Returns:
格式化后的字符串
"""
try:
if bytes_count < 1024:
return f"{bytes_count} B"
elif bytes_count < 1024 * 1024:
return f"{bytes_count / 1024:.2f} KB"
elif bytes_count < 1024 * 1024 * 1024:
return f"{bytes_count / (1024 * 1024):.2f} MB"
else:
return f"{bytes_count / (1024 * 1024 * 1024):.2f} GB"
except Exception as e:
print(f"✗ 字节格式化失败: {e}")
return f"{bytes_count} B"
@staticmethod
def validate_json(data: str) -> bool:
"""
验证JSON数据
Args:
data: JSON字符串
Returns:
是否为有效JSON
"""
try:
json.loads(data)
return True
except Exception:
return False
@staticmethod
def sanitize_input(input_str: str) -> str:
"""
清理输入字符串
Args:
input_str: 输入字符串
Returns:
清理后的字符串
"""
try:
# 移除潜在的危险字符
sanitized = input_str.replace("<", "&lt;").replace(">", "&gt;")
sanitized = sanitized.replace("\"", "&quot;").replace("'", "&#x27;")
return sanitized
except Exception as e:
print(f"✗ 输入清理失败: {e}")
return input_str
@staticmethod
def create_response(success: bool, message: str = "", data: Any = None) -> Dict[str, Any]:
"""
创建响应数据
Args:
success: 是否成功
message: 消息
data: 数据
Returns:
响应数据字典
"""
try:
response = {
"success": success,
"message": message,
"timestamp": time.time()
}
if data is not None:
response["data"] = data
return response
except Exception as e:
print(f"✗ 响应创建失败: {e}")
return {
"success": False,
"message": "响应创建失败",
"timestamp": time.time()
}
@staticmethod
def merge_dicts(dict1: Dict[str, Any], dict2: Dict[str, Any]) -> Dict[str, Any]:
"""
合并字典递归
Args:
dict1: 第一个字典
dict2: 第二个字典
Returns:
合并后的字典
"""
try:
result = dict1.copy()
for key, value in dict2.items():
if key in result and isinstance(result[key], dict) and isinstance(value, dict):
# 递归合并嵌套字典
result[key] = CommUtils.merge_dicts(result[key], value)
else:
# 直接覆盖
result[key] = value
return result
except Exception as e:
print(f"✗ 字典合并失败: {e}")
return dict1
@staticmethod
def get_system_info() -> Dict[str, Any]:
"""
获取系统信息
Returns:
系统信息字典
"""
try:
import platform
import psutil
# 系统信息
system_info = {
"platform": platform.system(),
"platform_version": platform.version(),
"architecture": platform.architecture()[0],
"processor": platform.processor(),
"python_version": platform.python_version()
}
# CPU信息
cpu_info = {
"physical_cores": psutil.cpu_count(logical=False),
"total_cores": psutil.cpu_count(logical=True),
"max_frequency": psutil.cpu_freq().max if psutil.cpu_freq() else 0,
"current_frequency": psutil.cpu_freq().current if psutil.cpu_freq() else 0
}
# 内存信息
memory_info = psutil.virtual_memory()
memory_stats = {
"total": memory_info.total,
"available": memory_info.available,
"used": memory_info.used,
"percentage": memory_info.percent
}
# 网络信息
net_info = psutil.net_io_counters()
network_stats = {
"bytes_sent": net_info.bytes_sent,
"bytes_recv": net_info.bytes_recv,
"packets_sent": net_info.packets_sent,
"packets_recv": net_info.packets_recv
}
return {
"system": system_info,
"cpu": cpu_info,
"memory": memory_stats,
"network": network_stats,
"timestamp": time.time()
}
except Exception as e:
print(f"✗ 系统信息获取失败: {e}")
return {
"system": {},
"cpu": {},
"memory": {},
"network": {},
"timestamp": time.time()
}
# 工具函数别名
generate_id = CommUtils.generate_unique_id
calculate_checksum = CommUtils.calculate_checksum
format_bytes = CommUtils.format_bytes
validate_json = CommUtils.validate_json
sanitize_input = CommUtils.sanitize_input
create_response = CommUtils.create_response
merge_dicts = CommUtils.merge_dicts
get_system_info = CommUtils.get_system_info