""" 对象同步模块 负责同步游戏对象的状态 """ import time from typing import Dict, Any, List, Optional import threading import copy class ObjectSync: """ 对象同步器 负责同步游戏对象的状态 """ def __init__(self, plugin): """ 初始化对象同步器 Args: plugin: 网络同步插件实例 """ self.plugin = plugin self.enabled = False self.initialized = False # 同步配置 self.sync_config = { 'sync_interval': 0.05, # 50ms同步间隔 'interpolation_time': 0.1, # 100ms插值时间 'extrapolation_limit': 0.2, # 200ms外推限制 'position_threshold': 0.01, # 位置变化阈值 'rotation_threshold': 0.1, # 旋转变化阈值 'scale_threshold': 0.01, # 缩放变化阈值 'enable_delta_compression': True, # 启用增量压缩 'enable_interpolation': True, # 启用插值 'enable_extrapolation': True, # 启用外推 'max_sync_distance': 100.0, # 最大同步距离 'sync_area_radius': 50.0 # 同步区域半径 } # 同步对象管理 self.sync_objects = {} # 所有同步对象 self.local_objects = {} # 本地对象 self.remote_objects = {} # 远程对象 # 同步状态 self.sync_state = { 'last_sync_time': 0.0, 'objects_synced': 0, 'sync_operations': 0, 'interpolations': 0, 'extrapolations': 0 } # 插值数据 self.interpolation_data = {} # 外推数据 self.extrapolation_data = {} # 对象历史状态(用于插值) self.object_history = {} # 同步统计 self.sync_stats = { 'objects_registered': 0, 'objects_synced': 0, 'sync_data_sent': 0, 'sync_data_received': 0, 'interpolations': 0, 'extrapolations': 0, 'sync_errors': 0, 'delta_compressions': 0 } # 线程锁 self.sync_lock = threading.RLock() # 回调函数 self.sync_callbacks = { 'object_registered': [], 'object_unregistered': [], 'sync_data_received': [], 'object_updated': [], 'sync_error': [] } # 时间戳记录 self.last_sync_update = 0.0 self.last_interpolation_update = 0.0 print("✓ 对象同步器已创建") def initialize(self) -> bool: """ 初始化对象同步器 Returns: 是否初始化成功 """ try: 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: self.disable() self.sync_objects.clear() self.local_objects.clear() self.remote_objects.clear() self.interpolation_data.clear() self.extrapolation_data.clear() self.object_history.clear() self.sync_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.last_sync_update = current_time # 执行同步操作 if current_time - self.sync_state['last_sync_time'] >= self.sync_config['sync_interval']: self._perform_sync() self.sync_state['last_sync_time'] = current_time # 更新插值和外推 self._update_interpolation(current_time) self._update_extrapolation(current_time) except Exception as e: print(f"✗ 对象同步器更新失败: {e}") import traceback traceback.print_exc() def _perform_sync(self): """执行同步操作""" try: # 收集需要同步的本地对象数据 sync_data = {} with self.sync_lock: for obj_id, obj_data in self.local_objects.items(): # 检查对象是否需要同步 if self._should_sync_object(obj_id, obj_data): sync_data[obj_id] = obj_data.copy() # 发送同步数据 if sync_data and self.plugin.network_manager: success = self.plugin.network_manager.send_sync_data(sync_data) if success: self.sync_stats['sync_data_sent'] += 1 self.sync_stats['objects_synced'] += len(sync_data) self.sync_state['sync_operations'] += 1 else: self.sync_stats['sync_errors'] += 1 except Exception as e: print(f"✗ 对象同步操作失败: {e}") self.sync_stats['sync_errors'] += 1 def _should_sync_object(self, obj_id: str, obj_data: Dict[str, Any]) -> bool: """ 检查对象是否需要同步 Args: obj_id: 对象ID obj_data: 对象数据 Returns: 是否需要同步 """ try: # 检查是否超出同步距离 if not self._is_in_sync_range(obj_data): return False # 检查是否有显著变化 if obj_id in self.sync_objects: old_data = self.sync_objects[obj_id] # 检查位置变化 if 'position' in obj_data and 'position' in old_data: pos_diff = self._calculate_distance(obj_data['position'], old_data['position']) if pos_diff > self.sync_config['position_threshold']: return True # 检查旋转变化 if 'rotation' in obj_data and 'rotation' in old_data: rot_diff = self._calculate_rotation_difference(obj_data['rotation'], old_data['rotation']) if rot_diff > self.sync_config['rotation_threshold']: return True # 检查缩放变化 if 'scale' in obj_data and 'scale' in old_data: scale_diff = self._calculate_scale_difference(obj_data['scale'], old_data['scale']) if scale_diff > self.sync_config['scale_threshold']: return True else: # 新对象总是需要同步 return True return False except Exception as e: print(f"✗ 对象同步检查失败: {e}") return True # 出错时默认同步 def _is_in_sync_range(self, obj_data: Dict[str, Any]) -> bool: """ 检查对象是否在同步范围内 Args: obj_data: 对象数据 Returns: 是否在同步范围内 """ try: # 这里应该根据具体的游戏场景实现 # 简单实现:假设所有对象都在同步范围内 return True except Exception as e: print(f"✗ 同步范围检查失败: {e}") return True def _calculate_distance(self, pos1: List[float], pos2: List[float]) -> float: """ 计算两点间距离 Args: pos1: 位置1 pos2: 位置2 Returns: 距离 """ try: if len(pos1) >= 3 and len(pos2) >= 3: dx = pos1[0] - pos2[0] dy = pos1[1] - pos2[1] dz = pos1[2] - pos2[2] return (dx*dx + dy*dy + dz*dz) ** 0.5 elif len(pos1) >= 2 and len(pos2) >= 2: dx = pos1[0] - pos2[0] dy = pos1[1] - pos2[1] return (dx*dx + dy*dy) ** 0.5 else: return 0.0 except Exception as e: print(f"✗ 距离计算失败: {e}") return 0.0 def _calculate_rotation_difference(self, rot1: List[float], rot2: List[float]) -> float: """ 计算旋转差异 Args: rot1: 旋转1 rot2: 旋转2 Returns: 旋转差异 """ try: # 简单实现:计算欧拉角差异 diff = 0.0 for i in range(min(len(rot1), len(rot2))): diff += abs(rot1[i] - rot2[i]) return diff except Exception as e: print(f"✗ 旋转差异计算失败: {e}") return 0.0 def _calculate_scale_difference(self, scale1: List[float], scale2: List[float]) -> float: """ 计算缩放差异 Args: scale1: 缩放1 scale2: 缩放2 Returns: 缩放差异 """ try: # 简单实现:计算缩放差异 diff = 0.0 for i in range(min(len(scale1), len(scale2))): diff += abs(scale1[i] - scale2[i]) return diff except Exception as e: print(f"✗ 缩放差异计算失败: {e}") return 0.0 def _update_interpolation(self, current_time: float): """ 更新插值 Args: current_time: 当前时间 """ try: if not self.sync_config['enable_interpolation']: return updated_count = 0 with self.sync_lock: for obj_id, interp_data in self.interpolation_data.items(): if self._perform_object_interpolation(obj_id, interp_data, current_time): updated_count += 1 self.sync_stats['interpolations'] += updated_count except Exception as e: print(f"✗ 插值更新失败: {e}") def _perform_object_interpolation(self, obj_id: str, interp_data: Dict[str, Any], current_time: float) -> bool: """ 执行对象插值 Args: obj_id: 对象ID interp_data: 插值数据 current_time: 当前时间 Returns: 是否插值成功 """ try: start_time = interp_data.get('start_time', current_time) end_time = interp_data.get('end_time', current_time) duration = end_time - start_time if duration > 0: progress = (current_time - start_time) / duration progress = max(0.0, min(1.0, progress)) # 限制在0-1之间 # 线性插值位置 if 'start_position' in interp_data and 'end_position' in interp_data: start_pos = interp_data['start_position'] end_pos = interp_data['end_position'] current_pos = [ start_pos[i] + (end_pos[i] - start_pos[i]) * progress for i in range(min(len(start_pos), len(end_pos))) ] # 更新对象位置 if obj_id in self.remote_objects: self.remote_objects[obj_id]['position'] = current_pos # 球面插值旋转(简化为线性插值) if 'start_rotation' in interp_data and 'end_rotation' in interp_data: start_rot = interp_data['start_rotation'] end_rot = interp_data['end_rotation'] current_rot = [ start_rot[i] + (end_rot[i] - start_rot[i]) * progress for i in range(min(len(start_rot), len(end_rot))) ] # 更新对象旋转 if obj_id in self.remote_objects: self.remote_objects[obj_id]['rotation'] = current_rot # 线性插值缩放 if 'start_scale' in interp_data and 'end_scale' in interp_data: start_scale = interp_data['start_scale'] end_scale = interp_data['end_scale'] current_scale = [ start_scale[i] + (end_scale[i] - start_scale[i]) * progress for i in range(min(len(start_scale), len(end_scale))) ] # 更新对象缩放 if obj_id in self.remote_objects: self.remote_objects[obj_id]['scale'] = current_scale return True else: return False except Exception as e: print(f"✗ 对象插值失败: {e}") return False def _update_extrapolation(self, current_time: float): """ 更新外推 Args: current_time: 当前时间 """ try: if not self.sync_config['enable_extrapolation']: return updated_count = 0 with self.sync_lock: for obj_id, extrap_data in self.extrapolation_data.items(): if self._perform_object_extrapolation(obj_id, extrap_data, current_time): updated_count += 1 self.sync_stats['extrapolations'] += updated_count except Exception as e: print(f"✗ 外推更新失败: {e}") def _perform_object_extrapolation(self, obj_id: str, extrap_data: Dict[str, Any], current_time: float) -> bool: """ 执行对象外推 Args: obj_id: 对象ID extrap_data: 外推数据 current_time: 当前时间 Returns: 是否外推成功 """ try: last_update_time = extrap_data.get('last_update_time', current_time) time_diff = current_time - last_update_time # 检查是否超出外推限制 if time_diff > self.sync_config['extrapolation_limit']: return False # 基于速度的外推 if 'position' in extrap_data and 'velocity' in extrap_data: position = extrap_data['position'] velocity = extrap_data['velocity'] # 计算外推位置 extrapolated_pos = [ position[i] + velocity[i] * time_diff for i in range(min(len(position), len(velocity))) ] # 更新对象位置 if obj_id in self.remote_objects: self.remote_objects[obj_id]['position'] = extrapolated_pos return True except Exception as e: print(f"✗ 对象外推失败: {e}") return False def register_object(self, obj_id: str, obj_data: Dict[str, Any], is_local: bool = True) -> bool: """ 注册同步对象 Args: obj_id: 对象ID obj_data: 对象数据 is_local: 是否为本地对象 Returns: 是否注册成功 """ try: with self.sync_lock: # 存储对象数据 self.sync_objects[obj_id] = obj_data.copy() if is_local: self.local_objects[obj_id] = obj_data.copy() else: self.remote_objects[obj_id] = obj_data.copy() # 初始化对象历史 self.object_history[obj_id] = { 'states': [obj_data.copy()], 'timestamps': [time.time()] } # 更新统计信息 self.sync_stats['objects_registered'] += 1 # 触发对象注册回调 self._trigger_sync_callback('object_registered', { 'object_id': obj_id, 'is_local': is_local, 'data': obj_data }) print(f"✓ 对象已注册: {obj_id} ({'本地' if is_local else '远程'})") return True except Exception as e: print(f"✗ 对象注册失败: {e}") self.sync_stats['sync_errors'] += 1 return False def unregister_object(self, obj_id: str) -> bool: """ 注销同步对象 Args: obj_id: 对象ID Returns: 是否注销成功 """ try: with self.sync_lock: # 从各个字典中移除对象 if obj_id in self.sync_objects: del self.sync_objects[obj_id] if obj_id in self.local_objects: del self.local_objects[obj_id] if obj_id in self.remote_objects: del self.remote_objects[obj_id] if obj_id in self.interpolation_data: del self.interpolation_data[obj_id] if obj_id in self.extrapolation_data: del self.extrapolation_data[obj_id] if obj_id in self.object_history: del self.object_history[obj_id] # 触发对象注销回调 self._trigger_sync_callback('object_unregistered', { 'object_id': obj_id }) print(f"✓ 对象已注销: {obj_id}") return True except Exception as e: print(f"✗ 对象注销失败: {e}") self.sync_stats['sync_errors'] += 1 return False def update_object(self, obj_id: str, obj_data: Dict[str, Any]) -> bool: """ 更新对象数据 Args: obj_id: 对象ID obj_data: 对象数据 Returns: 是否更新成功 """ try: with self.sync_lock: # 更新同步对象 if obj_id in self.sync_objects: self.sync_objects[obj_id].update(obj_data) # 更新本地对象 if obj_id in self.local_objects: self.local_objects[obj_id].update(obj_data) # 添加到对象历史(用于插值) if obj_id in self.object_history: history = self.object_history[obj_id] history['states'].append(obj_data.copy()) history['timestamps'].append(time.time()) # 保持历史记录大小 if len(history['states']) > 10: # 保持最近10个状态 history['states'].pop(0) history['timestamps'].pop(0) # 触发对象更新回调 self._trigger_sync_callback('object_updated', { 'object_id': obj_id, 'data': obj_data }) return True except Exception as e: print(f"✗ 对象更新失败: {e}") self.sync_stats['sync_errors'] += 1 return False def sync_object(self, obj_id: str, obj_data: Dict[str, Any]) -> bool: """ 同步对象 Args: obj_id: 对象ID obj_data: 对象数据 Returns: 是否同步成功 """ try: if not self.enabled: print("✗ 对象同步器未启用") return False # 更新对象数据 success = self.update_object(obj_id, obj_data) if success: self.sync_stats['objects_synced'] += 1 return True else: self.sync_stats['sync_errors'] += 1 return False except Exception as e: print(f"✗ 对象同步失败: {e}") self.sync_stats['sync_errors'] += 1 return False def receive_sync_data(self, obj_id: str, obj_data: Dict[str, Any], client_id: str = None) -> bool: """ 接收同步数据 Args: obj_id: 对象ID obj_data: 对象数据 client_id: 客户端ID(可选) Returns: 是否接收成功 """ try: with self.sync_lock: # 存储远程对象数据 self.remote_objects[obj_id] = obj_data.copy() self.sync_objects[obj_id] = obj_data.copy() # 设置插值数据 current_time = time.time() if obj_id in self.interpolation_data: # 更新现有插值数据 interp_data = self.interpolation_data[obj_id] interp_data['start_time'] = current_time interp_data['end_time'] = current_time + self.sync_config['interpolation_time'] interp_data['start_position'] = interp_data.get('end_position', obj_data.get('position', [0, 0, 0])) interp_data['end_position'] = obj_data.get('position', [0, 0, 0]) interp_data['start_rotation'] = interp_data.get('end_rotation', obj_data.get('rotation', [0, 0, 0])) interp_data['end_rotation'] = obj_data.get('rotation', [0, 0, 0]) interp_data['start_scale'] = interp_data.get('end_scale', obj_data.get('scale', [1, 1, 1])) interp_data['end_scale'] = obj_data.get('scale', [1, 1, 1]) else: # 创建新的插值数据 self.interpolation_data[obj_id] = { 'start_time': current_time, 'end_time': current_time + self.sync_config['interpolation_time'], 'start_position': obj_data.get('position', [0, 0, 0]), 'end_position': obj_data.get('position', [0, 0, 0]), 'start_rotation': obj_data.get('rotation', [0, 0, 0]), 'end_rotation': obj_data.get('rotation', [0, 0, 0]), 'start_scale': obj_data.get('scale', [1, 1, 1]), 'end_scale': obj_data.get('scale', [1, 1, 1]) } # 设置外推数据 self.extrapolation_data[obj_id] = { 'position': obj_data.get('position', [0, 0, 0]), 'velocity': obj_data.get('velocity', [0, 0, 0]), 'last_update_time': current_time } # 更新对象历史 if obj_id in self.object_history: history = self.object_history[obj_id] history['states'].append(obj_data.copy()) history['timestamps'].append(current_time) # 保持历史记录大小 if len(history['states']) > 10: history['states'].pop(0) history['timestamps'].pop(0) else: self.object_history[obj_id] = { 'states': [obj_data.copy()], 'timestamps': [current_time] } # 更新统计信息 self.sync_stats['sync_data_received'] += 1 # 触发同步数据接收回调 self._trigger_sync_callback('sync_data_received', { 'object_id': obj_id, 'data': obj_data, 'client_id': client_id }) return True except Exception as e: print(f"✗ 同步数据接收失败: {e}") self.sync_stats['sync_errors'] += 1 return False def get_object_data(self, obj_id: str) -> Optional[Dict[str, Any]]: """ 获取对象数据 Args: obj_id: 对象ID Returns: 对象数据或None """ try: with self.sync_lock: return self.sync_objects.get(obj_id, {}).copy() except Exception as e: print(f"✗ 对象数据获取失败: {e}") return None def get_local_objects(self) -> Dict[str, Dict[str, Any]]: """ 获取所有本地对象 Returns: 本地对象字典 """ try: with self.sync_lock: return {k: v.copy() for k, v in self.local_objects.items()} except Exception as e: print(f"✗ 本地对象获取失败: {e}") return {} def get_remote_objects(self) -> Dict[str, Dict[str, Any]]: """ 获取所有远程对象 Returns: 远程对象字典 """ try: with self.sync_lock: return {k: v.copy() for k, v in self.remote_objects.items()} except Exception as e: print(f"✗ 远程对象获取失败: {e}") return {} def get_sync_stats(self) -> Dict[str, Any]: """ 获取同步统计信息 Returns: 同步统计字典 """ return self.sync_stats.copy() def reset_sync_stats(self): """重置同步统计信息""" try: self.sync_stats = { 'objects_registered': 0, 'objects_synced': 0, 'sync_data_sent': 0, 'sync_data_received': 0, 'interpolations': 0, 'extrapolations': 0, 'sync_errors': 0, 'delta_compressions': 0 } print("✓ 对象同步统计信息已重置") except Exception as e: print(f"✗ 对象同步统计信息重置失败: {e}") def set_sync_config(self, config: Dict[str, Any]) -> bool: """ 设置同步配置 Args: config: 同步配置字典 Returns: 是否设置成功 """ try: self.sync_config.update(config) print(f"✓ 同步配置已更新: {self.sync_config}") return True except Exception as e: print(f"✗ 同步配置设置失败: {e}") return False def get_sync_config(self) -> Dict[str, Any]: """ 获取同步配置 Returns: 同步配置字典 """ return self.sync_config.copy() def _trigger_sync_callback(self, callback_type: str, data: Dict[str, Any]): """ 触发同步回调 Args: callback_type: 回调类型 data: 回调数据 """ try: if callback_type in self.sync_callbacks: for callback in self.sync_callbacks[callback_type]: try: callback(data) except Exception as e: print(f"✗ 同步回调执行失败: {e}") except Exception as e: print(f"✗ 同步回调触发失败: {e}") def register_sync_callback(self, callback_type: str, callback: callable): """ 注册同步回调 Args: callback_type: 回调类型 callback: 回调函数 """ try: if callback_type in self.sync_callbacks: self.sync_callbacks[callback_type].append(callback) print(f"✓ 同步回调已注册: {callback_type}") else: print(f"✗ 无效的回调类型: {callback_type}") except Exception as e: print(f"✗ 同步回调注册失败: {e}") def unregister_sync_callback(self, callback_type: str, callback: callable): """ 注销同步回调 Args: callback_type: 回调类型 callback: 回调函数 """ try: if callback_type in self.sync_callbacks: if callback in self.sync_callbacks[callback_type]: self.sync_callbacks[callback_type].remove(callback) print(f"✓ 同步回调已注销: {callback_type}") except Exception as e: print(f"✗ 同步回调注销失败: {e}")