From bdbef0bd0d268803534169327b61764d593a7cc0 Mon Sep 17 00:00:00 2001 From: YHH <359807859@qq.com> Date: Mon, 18 Aug 2025 20:46:47 +0800 Subject: [PATCH] =?UTF-8?q?core=E6=A0=B8=E5=BF=83rust=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core-rust/Cargo.toml | 34 + packages/core-rust/build-to-core.bat | 41 + packages/core-rust/build-to-core.sh | 40 + packages/core-rust/build.ps1 | 89 ++ packages/core-rust/build.sh | 91 ++ .../core-rust/src/core/archetype_system.rs | 758 ++++++++++++ packages/core-rust/src/core/component.rs | 376 ++++++ .../core-rust/src/core/component_builder.rs | 352 ++++++ packages/core-rust/src/core/entity.rs | 638 ++++++++++ .../src/core/entity_batch_operator.rs | 630 ++++++++++ packages/core-rust/src/core/entity_manager.rs | 405 +++++++ packages/core-rust/src/core/events.rs | 574 +++++++++ packages/core-rust/src/core/fluent_api.rs | 584 +++++++++ packages/core-rust/src/core/mod.rs | 27 + packages/core-rust/src/core/passive_system.rs | 351 ++++++ packages/core-rust/src/core/query_system.rs | 577 +++++++++ packages/core-rust/src/core/scene.rs | 403 +++++++ packages/core-rust/src/core/scene_builder.rs | 598 ++++++++++ packages/core-rust/src/core/systems.rs | 521 ++++++++ packages/core-rust/src/lib.rs | 33 + .../src/storage/component_storage.rs | 301 +++++ packages/core-rust/src/storage/mod.rs | 5 + packages/core-rust/src/storage/soa_storage.rs | 999 ++++++++++++++++ .../core-rust/src/utils/component_pool.rs | 766 ++++++++++++ packages/core-rust/src/utils/debug.rs | 1060 +++++++++++++++++ .../core-rust/src/utils/dirty_tracking.rs | 896 ++++++++++++++ packages/core-rust/src/utils/extensions.rs | 818 +++++++++++++ .../core-rust/src/utils/identifier_pool.rs | 518 ++++++++ packages/core-rust/src/utils/matcher.rs | 456 +++++++ packages/core-rust/src/utils/mod.rs | 46 + .../src/utils/performance_monitor.rs | 824 +++++++++++++ packages/core-rust/src/utils/pool.rs | 871 ++++++++++++++ packages/core-rust/src/utils/sparse_set.rs | 238 ++++ packages/core-rust/src/utils/time.rs | 124 ++ packages/core-rust/src/utils/timer.rs | 665 +++++++++++ packages/core-rust/src/utils/updatable.rs | 802 +++++++++++++ .../core-rust/src/wasm/component_wrapper.rs | 110 ++ .../src/wasm/entity_manager_wrapper.rs | 113 ++ packages/core-rust/src/wasm/entity_wrapper.rs | 139 +++ packages/core-rust/src/wasm/mod.rs | 11 + .../src/wasm/query_system_wrapper.rs | 104 ++ packages/core-rust/src/wasm/scene_wrapper.rs | 169 +++ 42 files changed, 17157 insertions(+) create mode 100644 packages/core-rust/Cargo.toml create mode 100644 packages/core-rust/build-to-core.bat create mode 100644 packages/core-rust/build-to-core.sh create mode 100644 packages/core-rust/build.ps1 create mode 100644 packages/core-rust/build.sh create mode 100644 packages/core-rust/src/core/archetype_system.rs create mode 100644 packages/core-rust/src/core/component.rs create mode 100644 packages/core-rust/src/core/component_builder.rs create mode 100644 packages/core-rust/src/core/entity.rs create mode 100644 packages/core-rust/src/core/entity_batch_operator.rs create mode 100644 packages/core-rust/src/core/entity_manager.rs create mode 100644 packages/core-rust/src/core/events.rs create mode 100644 packages/core-rust/src/core/fluent_api.rs create mode 100644 packages/core-rust/src/core/mod.rs create mode 100644 packages/core-rust/src/core/passive_system.rs create mode 100644 packages/core-rust/src/core/query_system.rs create mode 100644 packages/core-rust/src/core/scene.rs create mode 100644 packages/core-rust/src/core/scene_builder.rs create mode 100644 packages/core-rust/src/core/systems.rs create mode 100644 packages/core-rust/src/lib.rs create mode 100644 packages/core-rust/src/storage/component_storage.rs create mode 100644 packages/core-rust/src/storage/mod.rs create mode 100644 packages/core-rust/src/storage/soa_storage.rs create mode 100644 packages/core-rust/src/utils/component_pool.rs create mode 100644 packages/core-rust/src/utils/debug.rs create mode 100644 packages/core-rust/src/utils/dirty_tracking.rs create mode 100644 packages/core-rust/src/utils/extensions.rs create mode 100644 packages/core-rust/src/utils/identifier_pool.rs create mode 100644 packages/core-rust/src/utils/matcher.rs create mode 100644 packages/core-rust/src/utils/mod.rs create mode 100644 packages/core-rust/src/utils/performance_monitor.rs create mode 100644 packages/core-rust/src/utils/pool.rs create mode 100644 packages/core-rust/src/utils/sparse_set.rs create mode 100644 packages/core-rust/src/utils/time.rs create mode 100644 packages/core-rust/src/utils/timer.rs create mode 100644 packages/core-rust/src/utils/updatable.rs create mode 100644 packages/core-rust/src/wasm/component_wrapper.rs create mode 100644 packages/core-rust/src/wasm/entity_manager_wrapper.rs create mode 100644 packages/core-rust/src/wasm/entity_wrapper.rs create mode 100644 packages/core-rust/src/wasm/mod.rs create mode 100644 packages/core-rust/src/wasm/query_system_wrapper.rs create mode 100644 packages/core-rust/src/wasm/scene_wrapper.rs diff --git a/packages/core-rust/Cargo.toml b/packages/core-rust/Cargo.toml new file mode 100644 index 00000000..d7f4bb67 --- /dev/null +++ b/packages/core-rust/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "ecs-core-rust" +version = "0.0.1" +edition = "2021" +description = "基于Rust和WebAssembly的高性能ECS框架核心实现" +authors = ["yhh"] +license = "MIT" +repository = "https://github.com/esengine/ecs-framework.git" +keywords = ["ecs", "entity-component-system", "game-engine", "wasm", "webassembly"] + +[package.metadata.wasm-pack.profile.release.wasm-bindgen] +out-name = "ecs-core-rust" + +[package.metadata.wasm-pack] +name = "@esengine/ecs-framework-wasm" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +wasm-bindgen = { version = "0.2", features = ["serde-serialize"] } +js-sys = "0.3" +web-sys = "0.3" +serde = { version = "1.0", features = ["derive"] } +serde-wasm-bindgen = "0.4" +serde_json = "1.0" +rustc-hash = "1.1" +console_error_panic_hook = { version = "0.1.7", optional = true } + +[features] +default = ["console_error_panic_hook"] + +[package.metadata.wasm-pack.profile.release] +wasm-opt = false \ No newline at end of file diff --git a/packages/core-rust/build-to-core.bat b/packages/core-rust/build-to-core.bat new file mode 100644 index 00000000..7e79e626 --- /dev/null +++ b/packages/core-rust/build-to-core.bat @@ -0,0 +1,41 @@ +@echo off +setlocal enabledelayedexpansion + +REM 构建WASM到core库的脚本 (Windows版本) + +echo 🚀 开始构建 WASM 到 core 库... + +REM 确保在正确的目录 +cd /d "%~dp0" + +REM 确保目标目录存在 +if not exist "..\core\wasm" mkdir "..\core\wasm" + +REM 构建WASM包 +echo 📦 构建 WASM 包... +wasm-pack build --target web --out-dir temp-pkg + +REM 检查构建是否成功 +if not exist "temp-pkg" ( + echo ❌ WASM构建失败 + exit /b 1 +) + +REM 复制文件到core库 +echo 📁 复制文件到 core\wasm... +copy "temp-pkg\*.wasm" "..\core\wasm\" >nul +copy "temp-pkg\*.js" "..\core\wasm\" >nul +copy "temp-pkg\*.ts" "..\core\wasm\" >nul + +REM 清理临时文件 +echo 🧹 清理临时文件... +rmdir /s /q temp-pkg + +echo ✅ 构建完成!WASM文件已输出到 packages\core\wasm\ +echo. +echo 文件列表: +dir "..\core\wasm\" +echo. +echo 🎯 现在可以在 TypeScript 中直接导入 WASM 模块了! + +pause \ No newline at end of file diff --git a/packages/core-rust/build-to-core.sh b/packages/core-rust/build-to-core.sh new file mode 100644 index 00000000..37892c24 --- /dev/null +++ b/packages/core-rust/build-to-core.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +# 构建WASM到core库的脚本 + +set -e + +echo "🚀 开始构建 WASM 到 core 库..." + +# 确保在正确的目录 +cd "$(dirname "$0")" + +# 确保目标目录存在 +mkdir -p ../core/wasm + +# 构建WASM包 +echo "📦 构建 WASM 包..." +wasm-pack build --target web --out-dir temp-pkg + +# 检查构建是否成功 +if [ ! -d "temp-pkg" ]; then + echo "❌ WASM构建失败" + exit 1 +fi + +# 复制文件到core库,排除不需要的文件 +echo "📁 复制文件到 core/wasm..." +cp temp-pkg/*.wasm ../core/wasm/ +cp temp-pkg/*.js ../core/wasm/ +cp temp-pkg/*.ts ../core/wasm/ + +# 清理临时文件 +echo "🧹 清理临时文件..." +rm -rf temp-pkg + +echo "✅ 构建完成!WASM文件已输出到 packages/core/wasm/" +echo "" +echo "文件列表:" +ls -la ../core/wasm/ +echo "" +echo "🎯 现在可以在 TypeScript 中直接导入 WASM 模块了!" \ No newline at end of file diff --git a/packages/core-rust/build.ps1 b/packages/core-rust/build.ps1 new file mode 100644 index 00000000..c55e942b --- /dev/null +++ b/packages/core-rust/build.ps1 @@ -0,0 +1,89 @@ +# Windows PowerShell构建脚本 +param( + [switch]$Install, + [switch]$Help +) + +if ($Help) { + Write-Host "ECS Core Rust WASM构建脚本" + Write-Host "" + Write-Host "用法:" + Write-Host " .\build.ps1 # 构建WASM包" + Write-Host " .\build.ps1 -Install # 安装依赖并构建" + Write-Host " .\build.ps1 -Help # 显示帮助" + Write-Host "" + Write-Host "环境要求:" + Write-Host " - Rust (rustup)" + Write-Host " - wasm-pack" + exit +} + +Write-Host "开始构建Rust WASM包..." -ForegroundColor Green + +# 检查Rust是否安装 +if (!(Get-Command cargo -ErrorAction SilentlyContinue)) { + Write-Host "错误: 未找到cargo命令" -ForegroundColor Red + if ($Install) { + Write-Host "正在安装Rust..." -ForegroundColor Yellow + # 下载并运行Rust安装程序 + Invoke-RestMethod -Uri https://win.rustup.rs/ -OutFile rustup-init.exe + .\rustup-init.exe -y --default-toolchain stable + Remove-Item rustup-init.exe + + # 重新加载PATH + $env:PATH = [System.Environment]::GetEnvironmentVariable("PATH","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("PATH","User") + + # 添加Cargo到当前会话的PATH + if (Test-Path "$env:USERPROFILE\.cargo\bin") { + $env:PATH += ";$env:USERPROFILE\.cargo\bin" + } + } else { + Write-Host "请先安装Rust: https://rustup.rs/" -ForegroundColor Red + Write-Host "或者使用 -Install 参数自动安装" -ForegroundColor Yellow + exit 1 + } +} + +# 检查wasm-pack是否安装 +if (!(Get-Command wasm-pack -ErrorAction SilentlyContinue)) { + Write-Host "未找到wasm-pack,正在安装..." -ForegroundColor Yellow + if ($Install -or (Read-Host "是否安装wasm-pack? (y/N)").ToLower() -eq 'y') { + # 使用cargo安装wasm-pack + cargo install wasm-pack + } else { + Write-Host "请先安装wasm-pack: https://rustwasm.github.io/wasm-pack/installer/" -ForegroundColor Red + exit 1 + } +} + +# 添加wasm32目标 +Write-Host "添加wasm32目标..." -ForegroundColor Yellow +rustup target add wasm32-unknown-unknown + +# 构建WASM包 +Write-Host "构建WASM包..." -ForegroundColor Yellow +$env:RUST_LOG = "warn" # 减少日志输出 + +try { + wasm-pack build --target web --out-dir ..\core\src\wasm --out-name ecs-core-rust + + if ($LASTEXITCODE -eq 0) { + Write-Host "构建成功!" -ForegroundColor Green + Write-Host "生成的文件位于: ..\core\src\wasm\" -ForegroundColor Green + + # 显示生成的文件 + Write-Host "`n生成的文件:" -ForegroundColor Cyan + Get-ChildItem ..\core\src\wasm\ | ForEach-Object { + Write-Host " $($_.Name)" -ForegroundColor Gray + } + } else { + Write-Host "构建失败,退出码: $LASTEXITCODE" -ForegroundColor Red + exit $LASTEXITCODE + } +} catch { + Write-Host "构建过程中发生错误: $($_.Exception.Message)" -ForegroundColor Red + exit 1 +} + +Write-Host "`n构建完成!" -ForegroundColor Green +Write-Host "现在可以在TypeScript中使用WASM版本的ECS核心了。" -ForegroundColor Green \ No newline at end of file diff --git a/packages/core-rust/build.sh b/packages/core-rust/build.sh new file mode 100644 index 00000000..5e4bf565 --- /dev/null +++ b/packages/core-rust/build.sh @@ -0,0 +1,91 @@ +#!/bin/bash + +# Linux/macOS构建脚本 + +print_help() { + echo "ECS Core Rust WASM构建脚本" + echo "" + echo "用法:" + echo " ./build.sh # 构建WASM包" + echo " ./build.sh --install # 安装依赖并构建" + echo " ./build.sh --help # 显示帮助" + echo "" + echo "环境要求:" + echo " - Rust (rustup)" + echo " - wasm-pack" +} + +# 解析参数 +INSTALL=false +for arg in "$@"; do + case $arg in + --install) + INSTALL=true + shift + ;; + --help) + print_help + exit 0 + ;; + *) + echo "未知参数: $arg" + print_help + exit 1 + ;; + esac +done + +echo "开始构建Rust WASM包..." + +# 检查Rust是否安装 +if ! command -v cargo &> /dev/null; then + echo "错误: 未找到cargo命令" + if [ "$INSTALL" = true ]; then + echo "正在安装Rust..." + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + source ~/.cargo/env + else + echo "请先安装Rust: https://rustup.rs/" + echo "或者使用 --install 参数自动安装" + exit 1 + fi +fi + +# 确保环境变量加载 +if [ -f ~/.cargo/env ]; then + source ~/.cargo/env +fi + +# 检查wasm-pack是否安装 +if ! command -v wasm-pack &> /dev/null; then + echo "未找到wasm-pack,正在安装..." + if [ "$INSTALL" = true ] || { echo "是否安装wasm-pack? (y/N)"; read -r response; [ "$response" = "y" ] || [ "$response" = "Y" ]; }; then + curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh + else + echo "请先安装wasm-pack: https://rustwasm.github.io/wasm-pack/installer/" + exit 1 + fi +fi + +# 添加wasm32目标 +echo "添加wasm32目标..." +rustup target add wasm32-unknown-unknown + +# 构建WASM包 +echo "构建WASM包..." +export RUST_LOG=warn # 减少日志输出 + +if wasm-pack build --target web --out-dir ../core/src/wasm --out-name ecs-core-rust; then + echo "构建成功!" + echo "生成的文件位于: ../core/src/wasm/" + + # 显示生成的文件 + echo -e "\n生成的文件:" + ls -la ../core/src/wasm/ | grep -v '^d' | awk '{print " " $9}' | grep -v '^$' +else + echo "构建失败,退出码: $?" + exit 1 +fi + +echo -e "\n构建完成!" +echo "现在可以在TypeScript中使用WASM版本的ECS核心了。" \ No newline at end of file diff --git a/packages/core-rust/src/core/archetype_system.rs b/packages/core-rust/src/core/archetype_system.rs new file mode 100644 index 00000000..a13104c7 --- /dev/null +++ b/packages/core-rust/src/core/archetype_system.rs @@ -0,0 +1,758 @@ +use crate::utils::ComponentType; +use rustc_hash::FxHashMap; +use std::collections::HashSet; + +/** + * 原型标识符 + * 基于组件类型组合生成的唯一标识符 + */ +pub type ArchetypeId = String; + +/** + * 原型数据结构 + * 将具有相同组件组合的实体分组存储 + */ +#[derive(Debug, Clone)] +pub struct Archetype { + /// 原型唯一标识符 + pub id: ArchetypeId, + /// 包含的组件类型集合 + pub component_types: Vec, + /// 属于该原型的实体列表 + pub entities: Vec, + /// 原型创建时间(毫秒时间戳) + pub created_at: u64, + /// 最后更新时间(毫秒时间戳) + pub updated_at: u64, + /// 组件类型的位掩码(快速匹配) + pub component_mask: u64, +} + +impl Archetype { + /** + * 创建新的原型 + */ + pub fn new(component_types: Vec) -> Self { + let id = Self::generate_id(&component_types); + let component_mask = Self::calculate_mask(&component_types); + let now = current_timestamp(); + + Self { + id, + component_types, + entities: Vec::new(), + created_at: now, + updated_at: now, + component_mask, + } + } + + /** + * 生成原型ID + */ + fn generate_id(component_types: &[ComponentType]) -> ArchetypeId { + let mut sorted_types = component_types.to_vec(); + sorted_types.sort_by_key(|t| format!("{:?}", t)); + + // 使用组件类型的哈希值组合生成ID + let combined = sorted_types.iter() + .map(|t| format!("{:?}", t)) + .collect::>() + .join("|"); + + format!("archetype_{:x}", hash_string(&combined)) + } + + /** + * 计算组件类型的位掩码 + */ + fn calculate_mask(component_types: &[ComponentType]) -> u64 { + // 简化实现:使用组件类型哈希的前64位作为掩码 + let mut mask = 0u64; + for (i, component_type) in component_types.iter().enumerate() { + if i >= 64 { break; } // 最多支持64种组件类型的掩码 + let type_hash = hash_component_type(*component_type); + mask |= 1u64 << (type_hash % 64); + } + mask + } + + /** + * 添加实体到原型 + */ + pub fn add_entity(&mut self, entity_id: u32) { + if !self.entities.contains(&entity_id) { + self.entities.push(entity_id); + self.updated_at = current_timestamp(); + } + } + + /** + * 从原型中移除实体 + */ + pub fn remove_entity(&mut self, entity_id: u32) -> bool { + if let Some(pos) = self.entities.iter().position(|&id| id == entity_id) { + self.entities.remove(pos); + self.updated_at = current_timestamp(); + true + } else { + false + } + } + + /** + * 检查原型是否包含指定组件类型 + */ + pub fn contains_component(&self, component_type: ComponentType) -> bool { + self.component_types.contains(&component_type) + } + + /** + * 检查原型是否包含所有指定的组件类型 + */ + pub fn contains_all_components(&self, component_types: &[ComponentType]) -> bool { + component_types.iter().all(|t| self.contains_component(*t)) + } + + /** + * 检查原型是否包含任意一个指定的组件类型 + */ + pub fn contains_any_component(&self, component_types: &[ComponentType]) -> bool { + component_types.iter().any(|t| self.contains_component(*t)) + } + + /** + * 获取实体数量 + */ + pub fn entity_count(&self) -> usize { + self.entities.len() + } + + /** + * 检查原型是否为空 + */ + pub fn is_empty(&self) -> bool { + self.entities.is_empty() + } +} + +/** + * 原型查询结果 + */ +#[derive(Debug)] +pub struct ArchetypeQueryResult { + /// 匹配的原型列表 + pub archetypes: Vec, + /// 所有匹配实体的总数 + pub total_entities: usize, + /// 查询执行时间(毫秒) + pub execution_time: f64, + /// 是否使用了缓存 + pub from_cache: bool, +} + +/** + * 原型查询统计信息 + */ +#[derive(Debug, Default)] +pub struct ArchetypeSystemStats { + /// 总原型数量 + pub total_archetypes: usize, + /// 总实体数量 + pub total_entities: usize, + /// 平均每个原型的实体数量 + pub average_entities_per_archetype: f64, + /// 查询次数 + pub total_queries: u32, + /// 缓存命中次数 + pub cache_hits: u32, + /// 缓存命中率 + pub cache_hit_rate: f32, + /// 内存使用量(估算) + pub memory_usage_bytes: usize, +} + +/** + * 原型系统 + * + * 根据实体的组件组合将实体分组到不同的原型中,提供高效的查询性能。 + * 这是现代ECS的核心优化技术之一。 + */ +pub struct ArchetypeSystem { + /// 所有原型的映射表(ID -> 原型) + archetypes: FxHashMap, + + /// 实体到原型的映射 + entity_to_archetype: FxHashMap, + + /// 组件类型到原型集合的映射(用于快速查找) + component_to_archetypes: FxHashMap>, + + /// 查询缓存 + query_cache: FxHashMap, + + /// 缓存配置 + cache_timeout_ms: u64, + max_cache_size: usize, + + /// 统计信息 + stats: ArchetypeSystemStats, +} + +/** + * 缓存查询结果 + */ +struct CachedQueryResult { + result: ArchetypeQueryResult, + timestamp: u64, +} + +impl ArchetypeSystem { + /** + * 创建新的原型系统 + */ + pub fn new() -> Self { + Self { + archetypes: FxHashMap::default(), + entity_to_archetype: FxHashMap::default(), + component_to_archetypes: FxHashMap::default(), + query_cache: FxHashMap::default(), + cache_timeout_ms: 5000, // 5秒缓存超时 + max_cache_size: 100, + stats: ArchetypeSystemStats::default(), + } + } + + /** + * 设置缓存配置 + */ + pub fn configure_cache(&mut self, timeout_ms: u64, max_size: usize) { + self.cache_timeout_ms = timeout_ms; + self.max_cache_size = max_size; + } + + /** + * 添加实体到原型系统 + */ + pub fn add_entity(&mut self, entity_id: u32, component_types: Vec) { + if component_types.is_empty() { + return; // 不处理没有组件的实体 + } + + let archetype_id = Archetype::generate_id(&component_types); + + // 如果原型不存在,创建新原型 + if !self.archetypes.contains_key(&archetype_id) { + let archetype = Archetype::new(component_types.clone()); + self.create_archetype(archetype); + } + + // 添加实体到原型 + if let Some(archetype) = self.archetypes.get_mut(&archetype_id) { + archetype.add_entity(entity_id); + } + + // 更新实体到原型的映射 + if let Some(old_archetype_id) = self.entity_to_archetype.get(&entity_id).cloned() { + // 如果实体已存在于其他原型中,先移除 + if old_archetype_id != archetype_id { + self.remove_entity_from_archetype(entity_id, &old_archetype_id); + } + } + + self.entity_to_archetype.insert(entity_id, archetype_id); + + // 清空查询缓存(因为原型变化了) + self.invalidate_query_cache(); + } + + /** + * 从原型系统中移除实体 + */ + pub fn remove_entity(&mut self, entity_id: u32) -> bool { + if let Some(archetype_id) = self.entity_to_archetype.remove(&entity_id) { + let success = self.remove_entity_from_archetype(entity_id, &archetype_id); + + if success { + self.invalidate_query_cache(); + + // 如果原型变空了,可以考虑清理(但这里保留空原型以提高性能) + // 实际生产中可能需要定期清理空原型 + } + + success + } else { + false + } + } + + /** + * 实体组件发生变化时更新原型 + */ + pub fn update_entity_components(&mut self, entity_id: u32, new_component_types: Vec) { + // 先移除实体,再重新添加 + self.remove_entity(entity_id); + if !new_component_types.is_empty() { + self.add_entity(entity_id, new_component_types); + } + } + + /** + * 查询包含所有指定组件的原型 + */ + pub fn query_all_components(&mut self, component_types: &[ComponentType]) -> ArchetypeQueryResult { + let cache_key = format!("all:{:?}", component_types); + + // 检查缓存 + if let Some(cached) = self.get_cached_result(&cache_key) { + self.stats.cache_hits += 1; + self.stats.total_queries += 1; + return cached; + } + + let start_time = current_timestamp_f64(); + let mut matching_archetypes = Vec::new(); + let mut total_entities = 0; + + for archetype in self.archetypes.values() { + if archetype.contains_all_components(component_types) { + total_entities += archetype.entity_count(); + matching_archetypes.push(archetype.clone()); + } + } + + let execution_time = current_timestamp_f64() - start_time; + let result = ArchetypeQueryResult { + archetypes: matching_archetypes, + total_entities, + execution_time, + from_cache: false, + }; + + // 缓存结果 + self.cache_query_result(cache_key, &result); + self.stats.total_queries += 1; + + result + } + + /** + * 查询包含任意指定组件的原型 + */ + pub fn query_any_component(&mut self, component_types: &[ComponentType]) -> ArchetypeQueryResult { + let cache_key = format!("any:{:?}", component_types); + + if let Some(cached) = self.get_cached_result(&cache_key) { + self.stats.cache_hits += 1; + self.stats.total_queries += 1; + return cached; + } + + let start_time = current_timestamp_f64(); + let mut matching_archetypes = Vec::new(); + let mut total_entities = 0; + + for archetype in self.archetypes.values() { + if archetype.contains_any_component(component_types) { + total_entities += archetype.entity_count(); + matching_archetypes.push(archetype.clone()); + } + } + + let execution_time = current_timestamp_f64() - start_time; + let result = ArchetypeQueryResult { + archetypes: matching_archetypes, + total_entities, + execution_time, + from_cache: false, + }; + + self.cache_query_result(cache_key, &result); + self.stats.total_queries += 1; + + result + } + + /** + * 根据组件掩码查询原型 + */ + pub fn query_by_mask(&mut self, component_mask: u64) -> ArchetypeQueryResult { + let cache_key = format!("mask:{}", component_mask); + + if let Some(cached) = self.get_cached_result(&cache_key) { + self.stats.cache_hits += 1; + self.stats.total_queries += 1; + return cached; + } + + let start_time = current_timestamp_f64(); + let mut matching_archetypes = Vec::new(); + let mut total_entities = 0; + + for archetype in self.archetypes.values() { + if (archetype.component_mask & component_mask) == component_mask { + total_entities += archetype.entity_count(); + matching_archetypes.push(archetype.clone()); + } + } + + let execution_time = current_timestamp_f64() - start_time; + let result = ArchetypeQueryResult { + archetypes: matching_archetypes, + total_entities, + execution_time, + from_cache: false, + }; + + self.cache_query_result(cache_key, &result); + self.stats.total_queries += 1; + + result + } + + /** + * 获取实体所属的原型 + */ + pub fn get_entity_archetype(&self, entity_id: u32) -> Option<&Archetype> { + if let Some(archetype_id) = self.entity_to_archetype.get(&entity_id) { + self.archetypes.get(archetype_id) + } else { + None + } + } + + /** + * 获取所有原型的列表 + */ + pub fn get_all_archetypes(&self) -> Vec<&Archetype> { + self.archetypes.values().collect() + } + + /** + * 获取统计信息 + */ + pub fn get_stats(&self) -> ArchetypeSystemStats { + let total_archetypes = self.archetypes.len(); + let total_entities = self.archetypes.values() + .map(|a| a.entity_count()) + .sum(); + + let average_entities = if total_archetypes > 0 { + total_entities as f64 / total_archetypes as f64 + } else { + 0.0 + }; + + let cache_hit_rate = if self.stats.total_queries > 0 { + (self.stats.cache_hits as f32 / self.stats.total_queries as f32) * 100.0 + } else { + 0.0 + }; + + let memory_usage = self.estimate_memory_usage(); + + ArchetypeSystemStats { + total_archetypes, + total_entities, + average_entities_per_archetype: average_entities, + total_queries: self.stats.total_queries, + cache_hits: self.stats.cache_hits, + cache_hit_rate, + memory_usage_bytes: memory_usage, + } + } + + /** + * 清空所有数据 + */ + pub fn clear(&mut self) { + self.archetypes.clear(); + self.entity_to_archetype.clear(); + self.component_to_archetypes.clear(); + self.query_cache.clear(); + self.stats = ArchetypeSystemStats::default(); + } + + // ========== 私有方法 ========== + + /** + * 创建新原型并建立索引 + */ + fn create_archetype(&mut self, archetype: Archetype) { + let archetype_id = archetype.id.clone(); + + // 为每个组件类型建立索引 + for &component_type in &archetype.component_types { + self.component_to_archetypes + .entry(component_type) + .or_insert_with(HashSet::new) + .insert(archetype_id.clone()); + } + + self.archetypes.insert(archetype_id, archetype); + } + + /** + * 从指定原型中移除实体 + */ + fn remove_entity_from_archetype(&mut self, entity_id: u32, archetype_id: &str) -> bool { + if let Some(archetype) = self.archetypes.get_mut(archetype_id) { + archetype.remove_entity(entity_id) + } else { + false + } + } + + /** + * 获取缓存的查询结果 + */ + fn get_cached_result(&self, cache_key: &str) -> Option { + if let Some(cached) = self.query_cache.get(cache_key) { + let now = current_timestamp(); + if now - cached.timestamp < self.cache_timeout_ms { + return Some(ArchetypeQueryResult { + archetypes: cached.result.archetypes.clone(), + total_entities: cached.result.total_entities, + execution_time: cached.result.execution_time, + from_cache: true, + }); + } + } + None + } + + /** + * 缓存查询结果 + */ + fn cache_query_result(&mut self, cache_key: String, result: &ArchetypeQueryResult) { + // 如果缓存已满,清理旧条目 + if self.query_cache.len() >= self.max_cache_size { + self.cleanup_old_cache_entries(); + } + + let cached_result = CachedQueryResult { + result: ArchetypeQueryResult { + archetypes: result.archetypes.clone(), + total_entities: result.total_entities, + execution_time: result.execution_time, + from_cache: false, + }, + timestamp: current_timestamp(), + }; + + self.query_cache.insert(cache_key, cached_result); + } + + /** + * 清理过期的缓存条目 + */ + fn cleanup_old_cache_entries(&mut self) { + let now = current_timestamp(); + let timeout = self.cache_timeout_ms; + + self.query_cache.retain(|_, cached| { + now - cached.timestamp < timeout + }); + + // 如果清理后仍然太多,移除最旧的一半 + if self.query_cache.len() >= self.max_cache_size { + let keys_to_remove: Vec<_> = self.query_cache.keys() + .take(self.query_cache.len() / 2) + .cloned() + .collect(); + + for key in keys_to_remove { + self.query_cache.remove(&key); + } + } + } + + /** + * 使查询缓存失效 + */ + fn invalidate_query_cache(&mut self) { + self.query_cache.clear(); + } + + /** + * 估算内存使用量 + */ + fn estimate_memory_usage(&self) -> usize { + let archetypes_size = self.archetypes.len() * std::mem::size_of::(); + let entity_mapping_size = self.entity_to_archetype.len() * (std::mem::size_of::() + std::mem::size_of::()); + let component_mapping_size = self.component_to_archetypes.len() * std::mem::size_of::<(ComponentType, HashSet)>(); + let cache_size = self.query_cache.len() * std::mem::size_of::(); + + archetypes_size + entity_mapping_size + component_mapping_size + cache_size + } +} + +impl Default for ArchetypeSystem { + fn default() -> Self { + Self::new() + } +} + +// ========== 辅助函数 ========== + +/** + * 获取当前时间戳(毫秒) + */ +fn current_timestamp() -> u64 { + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap_or_default() + .as_millis() as u64 +} + +/** + * 获取当前时间戳(浮点毫秒,用于精确计时) + */ +fn current_timestamp_f64() -> f64 { + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap_or_default() + .as_secs_f64() * 1000.0 +} + +/** + * 计算字符串哈希 + */ +fn hash_string(s: &str) -> u64 { + use std::collections::hash_map::DefaultHasher; + use std::hash::{Hash, Hasher}; + + let mut hasher = DefaultHasher::new(); + s.hash(&mut hasher); + hasher.finish() +} + +/** + * 计算组件类型哈希 + */ +fn hash_component_type(component_type: ComponentType) -> u64 { + use std::collections::hash_map::DefaultHasher; + use std::hash::{Hash, Hasher}; + + let mut hasher = DefaultHasher::new(); + component_type.hash(&mut hasher); + hasher.finish() +} + +#[cfg(test)] +mod tests { + use super::*; + use std::any::TypeId; + + // 测试用的示例组件 + struct TestComponentA; + struct TestComponentB; + struct TestComponentC; + + #[test] + fn test_archetype_creation() { + let component_types = vec![ + TypeId::of::(), + TypeId::of::(), + ]; + + let archetype = Archetype::new(component_types.clone()); + assert_eq!(archetype.component_types.len(), 2); + assert_eq!(archetype.entity_count(), 0); + assert!(!archetype.id.is_empty()); + } + + #[test] + fn test_archetype_system_basic() { + let mut system = ArchetypeSystem::new(); + + let component_types_a = vec![ + TypeId::of::(), + TypeId::of::(), + ]; + + let component_types_b = vec![ + TypeId::of::(), + TypeId::of::(), + ]; + + // 添加实体 + system.add_entity(1, component_types_a.clone()); + system.add_entity(2, component_types_a.clone()); + system.add_entity(3, component_types_b); + + let stats = system.get_stats(); + assert_eq!(stats.total_archetypes, 2); + assert_eq!(stats.total_entities, 3); + } + + #[test] + fn test_archetype_queries() { + let mut system = ArchetypeSystem::new(); + + let component_types_ab = vec![ + TypeId::of::(), + TypeId::of::(), + ]; + + let component_types_ac = vec![ + TypeId::of::(), + TypeId::of::(), + ]; + + system.add_entity(1, component_types_ab); + system.add_entity(2, component_types_ac); + + // 查询包含ComponentA的原型 + let result = system.query_all_components(&[TypeId::of::()]); + assert_eq!(result.archetypes.len(), 2); + assert_eq!(result.total_entities, 2); + + // 查询包含ComponentB的原型 + let result = system.query_all_components(&[TypeId::of::()]); + assert_eq!(result.archetypes.len(), 1); + assert_eq!(result.total_entities, 1); + } + + #[test] + fn test_entity_updates() { + let mut system = ArchetypeSystem::new(); + + let initial_components = vec![TypeId::of::()]; + system.add_entity(1, initial_components); + + assert_eq!(system.get_stats().total_archetypes, 1); + + // 更新实体组件 + let new_components = vec![ + TypeId::of::(), + TypeId::of::(), + ]; + system.update_entity_components(1, new_components); + + // 应该创建新的原型 + assert_eq!(system.get_stats().total_archetypes, 2); + assert_eq!(system.get_stats().total_entities, 1); + } + + #[test] + fn test_cache_functionality() { + let mut system = ArchetypeSystem::new(); + system.configure_cache(1000, 10); // 1秒缓存,最多10条 + + let component_types = vec![TypeId::of::()]; + system.add_entity(1, component_types); + + // 第一次查询 + let result1 = system.query_all_components(&[TypeId::of::()]); + assert!(!result1.from_cache); + + // 第二次查询应该从缓存获取 + let result2 = system.query_all_components(&[TypeId::of::()]); + assert!(result2.from_cache); + + let stats = system.get_stats(); + assert_eq!(stats.cache_hits, 1); + assert_eq!(stats.total_queries, 2); + } +} \ No newline at end of file diff --git a/packages/core-rust/src/core/component.rs b/packages/core-rust/src/core/component.rs new file mode 100644 index 00000000..505d81ec --- /dev/null +++ b/packages/core-rust/src/core/component.rs @@ -0,0 +1,376 @@ +use rustc_hash::FxHashMap; +use std::any::{Any, TypeId}; +use std::sync::atomic::{AtomicU32, Ordering}; + +/** + * 组件ID生成器 + * 全局静态变量,为每个组件实例分配唯一ID + */ +static COMPONENT_ID_GENERATOR: AtomicU32 = AtomicU32::new(0); + + +/** + * 组件注册表 + * 管理组件类型的位掩码分配 + */ +pub struct ComponentRegistry { + component_types: FxHashMap, + component_names: FxHashMap, + component_name_to_id: FxHashMap, + next_bit_index: u32, + max_components: u32, +} + +impl ComponentRegistry { + pub fn new() -> Self { + Self { + component_types: FxHashMap::default(), + component_names: FxHashMap::default(), + component_name_to_id: FxHashMap::default(), + next_bit_index: 0, + max_components: 64, + } + } + + /** + * 注册组件类型并分配位掩码 + * @param type_id 组件类型ID + * @param name 组件名称 + * @returns 分配的位索引 + */ + pub fn register(&mut self, type_id: TypeId, name: String) -> Result { + if let Some(&existing_index) = self.component_types.get(&type_id) { + return Ok(existing_index); + } + + if self.next_bit_index >= self.max_components { + return Err(format!( + "Maximum number of component types ({}) exceeded", + self.max_components + )); + } + + let bit_index = self.next_bit_index; + self.next_bit_index += 1; + + self.component_types.insert(type_id, bit_index); + self.component_names.insert(name.clone(), type_id); + self.component_name_to_id.insert(name, bit_index); + + Ok(bit_index) + } + + /** + * 获取组件类型的位掩码 + * @param type_id 组件类型ID + * @returns 位掩码 + */ + pub fn get_bit_mask(&self, type_id: &TypeId) -> Option { + self.component_types.get(type_id).map(|&bit_index| 1u64 << bit_index) + } + + /** + * 获取组件类型的位索引 + * @param type_id 组件类型ID + * @returns 位索引 + */ + pub fn get_bit_index(&self, type_id: &TypeId) -> Option { + self.component_types.get(type_id).copied() + } + + /** + * 检查组件类型是否已注册 + * @param type_id 组件类型ID + * @returns 是否已注册 + */ + pub fn is_registered(&self, type_id: &TypeId) -> bool { + self.component_types.contains_key(type_id) + } + + /** + * 通过名称获取组件类型ID + * @param name 组件名称 + * @returns 组件类型ID + */ + pub fn get_component_id(&self, name: &str) -> Option { + self.component_name_to_id.get(name).copied() + } + + /** + * 创建组件掩码 + * @param component_names 组件名称数组 + * @returns 组合掩码 + */ + pub fn create_component_mask(&self, component_names: &[String]) -> u64 { + let mut mask = 0u64; + for name in component_names { + if let Some(&component_id) = self.component_name_to_id.get(name) { + mask |= 1u64 << component_id; + } + } + mask + } + + /** + * 重置注册表 + */ + pub fn reset(&mut self) { + self.component_types.clear(); + self.component_names.clear(); + self.component_name_to_id.clear(); + self.next_bit_index = 0; + } +} + +/** + * 游戏组件基础trait + * + * ECS架构中的组件(Component),用于实现具体的游戏功能。 + * 组件包含数据和行为,可以被添加到实体上以扩展实体的功能。 + */ +pub trait Component: Send + Sync where Self: 'static { + /** + * 获取组件的唯一标识符 + * 在整个游戏生命周期中唯一的数字ID + */ + fn id(&self) -> u32; + + /** + * 获取组件启用状态 + * 组件的实际启用状态取决于自身状态和所属实体的状态 + */ + fn enabled(&self) -> bool { + true // 默认启用 + } + + /** + * 设置组件启用状态 + * 当状态改变时会触发相应的生命周期回调 + */ + fn set_enabled(&mut self, enabled: bool); + + /** + * 获取更新顺序 + * 决定组件在更新循环中的执行顺序 + */ + fn update_order(&self) -> i32 { + 0 // 默认更新顺序 + } + + /** + * 设置更新顺序 + */ + fn set_update_order(&mut self, order: i32); + + /** + * 组件添加到实体时的回调 + * 当组件被添加到实体时调用,可以在此方法中进行初始化操作 + */ + fn on_added_to_entity(&mut self) {} + + /** + * 组件从实体移除时的回调 + * 当组件从实体中移除时调用,可以在此方法中进行清理操作 + */ + fn on_removed_from_entity(&mut self) {} + + /** + * 组件启用时的回调 + * 当组件被启用时调用 + */ + fn on_enabled(&mut self) {} + + /** + * 组件禁用时的回调 + * 当组件被禁用时调用 + */ + fn on_disabled(&mut self) {} + + /** + * 实体激活状态改变时的回调 + * 当所属实体的激活状态改变时调用 + */ + fn on_active_changed(&mut self) {} + + /** + * 更新组件 + * 每帧调用,用于更新组件的逻辑 + * 子类应该重写此方法来实现具体的更新逻辑 + */ + fn update(&mut self) {} + + // ========== Any trait 方法 ========== + + /** + * 获取组件作为Any引用,用于类型转换 + */ + fn as_any(&self) -> &dyn Any; + + /** + * 获取组件作为可变Any引用,用于类型转换 + */ + fn as_any_mut(&mut self) -> &mut dyn Any; + + /** + * 克隆组件到Box中 + */ + fn clone_box(&self) -> Box; + + /** + * 获取组件的TypeId + */ + fn type_id(&self) -> TypeId { + TypeId::of::() + } + + /** + * 获取组件类型名称(用于调试) + */ + fn type_name(&self) -> &'static str { + std::any::type_name::() + } +} + +/** + * 为Box实现Clone + */ +impl Clone for Box { + fn clone(&self) -> Box { + self.clone_box() + } +} + +/** + * 基础组件实现 + * 提供默认的组件行为,具体组件可以继承此结构体 + */ +#[derive(Debug, Clone)] +pub struct BaseComponent { + /// 组件唯一标识符 + id: u32, + /// 组件启用状态 + enabled: bool, + /// 更新顺序 + update_order: i32, +} + +impl BaseComponent { + /** + * 创建新的基础组件 + */ + pub fn new() -> Self { + Self { + id: COMPONENT_ID_GENERATOR.fetch_add(1, Ordering::SeqCst), + enabled: true, + update_order: 0, + } + } + + /** + * 生成下一个组件ID + */ + pub fn next_component_id() -> u32 { + COMPONENT_ID_GENERATOR.fetch_add(1, Ordering::SeqCst) + } + + /** + * 设置组件ID + */ + pub fn set_id(&mut self, id: u32) { + self.id = id; + } +} + +impl Default for BaseComponent { + fn default() -> Self { + Self::new() + } +} + +impl Component for BaseComponent { + fn id(&self) -> u32 { + self.id + } + + fn enabled(&self) -> bool { + self.enabled + } + + fn set_enabled(&mut self, enabled: bool) { + if self.enabled != enabled { + self.enabled = enabled; + if enabled { + self.on_enabled(); + } else { + self.on_disabled(); + } + } + } + + fn update_order(&self) -> i32 { + self.update_order + } + + fn set_update_order(&mut self, order: i32) { + self.update_order = order; + } + + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } + + fn clone_box(&self) -> Box { + Box::new(BaseComponent { + id: BaseComponent::next_component_id(), // 新的克隆应该有新的ID + enabled: self.enabled, + update_order: self.update_order, + }) + } +} + +/** + * 组件宏,用于简化自定义组件的实现 + */ +#[macro_export] +macro_rules! impl_component { + ($component_type:ty) => { + impl Component for $component_type { + fn id(&self) -> u32 { + self.base.id() + } + + fn enabled(&self) -> bool { + self.base.enabled() + } + + fn set_enabled(&mut self, enabled: bool) { + self.base.set_enabled(enabled) + } + + fn update_order(&self) -> i32 { + self.base.update_order() + } + + fn set_update_order(&mut self, order: i32) { + self.base.set_update_order(order) + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self + } + + fn clone_box(&self) -> Box { + Box::new(self.clone()) + } + } + }; +} + diff --git a/packages/core-rust/src/core/component_builder.rs b/packages/core-rust/src/core/component_builder.rs new file mode 100644 index 00000000..069bfb43 --- /dev/null +++ b/packages/core-rust/src/core/component_builder.rs @@ -0,0 +1,352 @@ +use std::marker::PhantomData; +use crate::core::{Component, BaseComponent}; + +/** + * 组件构建器 + * 提供流式API创建和配置组件 + */ +pub struct ComponentBuilder { + component: T, + _phantom: PhantomData, +} + +impl ComponentBuilder { + /** + * 创建组件构建器 + */ + pub fn new(component: T) -> Self { + Self { + component, + _phantom: PhantomData, + } + } + + /** + * 设置组件启用状态 + */ + pub fn enabled(mut self, enabled: bool) -> Self { + self.component.set_enabled(enabled); + self + } + + /** + * 条件性设置启用状态 + */ + pub fn enabled_if(mut self, condition: bool, enabled: bool) -> Self { + if condition { + self.component.set_enabled(enabled); + } + self + } + + /** + * 使用配置函数设置组件 + */ + pub fn configure(mut self, configurator: F) -> Self + where + F: FnOnce(&mut T), + { + configurator(&mut self.component); + self + } + + /** + * 条件性配置组件 + */ + pub fn configure_if(mut self, condition: bool, configurator: F) -> Self + where + F: FnOnce(&mut T), + { + if condition { + configurator(&mut self.component); + } + self + } + + /** + * 构建并返回组件 + */ + pub fn build(self) -> T { + self.component + } + + /** + * 验证组件配置并构建 + */ + pub fn validate_and_build(self, validator: F) -> Result + where + F: FnOnce(&T) -> Result<(), String>, + { + match validator(&self.component) { + Ok(()) => Ok(self.component), + Err(error) => Err(error), + } + } +} + +/** + * 基础组件构建器 + * 为BaseComponent提供特化的构建器实现 + */ +pub struct BaseComponentBuilder { + component: BaseComponent, +} + +impl BaseComponentBuilder { + /** + * 创建基础组件构建器 + */ + pub fn new() -> Self { + Self { + component: BaseComponent::new(), + } + } + + /** + * 设置组件启用状态 + */ + pub fn enabled(mut self, enabled: bool) -> Self { + self.component.set_enabled(enabled); + self + } + + /** + * 设置组件ID + */ + pub fn with_id(mut self, id: u32) -> Self { + self.component.set_id(id); + self + } + + /** + * 条件性设置启用状态 + */ + pub fn enabled_if(mut self, condition: bool, enabled: bool) -> Self { + if condition { + self.component.set_enabled(enabled); + } + self + } + + /** + * 使用配置函数设置组件 + */ + pub fn configure(mut self, configurator: F) -> Self + where + F: FnOnce(&mut BaseComponent), + { + configurator(&mut self.component); + self + } + + /** + * 构建并返回组件 + */ + pub fn build(self) -> BaseComponent { + self.component + } +} + +/** + * 组件构建器工厂 + * 提供创建各种组件构建器的便捷方法 + */ +pub struct ComponentBuilderFactory; + +impl ComponentBuilderFactory { + /** + * 创建基础组件构建器 + */ + pub fn base_component() -> BaseComponentBuilder { + BaseComponentBuilder::new() + } + + /** + * 创建通用组件构建器 + */ + pub fn component(component: T) -> ComponentBuilder { + ComponentBuilder::new(component) + } + + /** + * 创建启用的基础组件 + */ + pub fn enabled_base_component() -> BaseComponentBuilder { + BaseComponentBuilder::new().enabled(true) + } + + /** + * 创建禁用的基础组件 + */ + pub fn disabled_base_component() -> BaseComponentBuilder { + BaseComponentBuilder::new().enabled(false) + } +} + +/** + * 组件构建器统计信息 + */ +#[derive(Debug, Clone)] +pub struct ComponentBuilderStats { + pub total_components_built: u64, + pub base_components_built: u64, + pub custom_components_built: u64, + pub validation_failures: u64, +} + +impl ComponentBuilderStats { + pub fn new() -> Self { + Self { + total_components_built: 0, + base_components_built: 0, + custom_components_built: 0, + validation_failures: 0, + } + } + + /** + * 重置统计信息 + */ + pub fn reset(&mut self) { + self.total_components_built = 0; + self.base_components_built = 0; + self.custom_components_built = 0; + self.validation_failures = 0; + } + + /** + * 记录基础组件构建 + */ + pub fn record_base_component_built(&mut self) { + self.total_components_built += 1; + self.base_components_built += 1; + } + + /** + * 记录自定义组件构建 + */ + pub fn record_custom_component_built(&mut self) { + self.total_components_built += 1; + self.custom_components_built += 1; + } + + /** + * 记录验证失败 + */ + pub fn record_validation_failure(&mut self) { + self.validation_failures += 1; + } + + /** + * 获取构建成功率 + */ + pub fn success_rate(&self) -> f64 { + if self.total_components_built + self.validation_failures == 0 { + return 1.0; + } + self.total_components_built as f64 / + (self.total_components_built + self.validation_failures) as f64 + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_base_component_builder() { + let component = BaseComponentBuilder::new() + .enabled(true) + .with_id(123) + .build(); + + assert!(component.enabled()); + assert_eq!(component.id(), 123); + } + + #[test] + fn test_base_component_builder_conditional() { + let component = BaseComponentBuilder::new() + .enabled_if(true, true) + .enabled_if(false, false) + .build(); + + assert!(component.enabled()); + } + + #[test] + fn test_base_component_builder_configure() { + let component = BaseComponentBuilder::new() + .configure(|comp| { + comp.set_enabled(true); + comp.set_id(456); + }) + .build(); + + assert!(component.enabled()); + assert_eq!(component.id(), 456); + } + + #[test] + fn test_component_builder_factory() { + let base_comp = ComponentBuilderFactory::base_component().build(); + assert!(!base_comp.enabled()); // 默认为禁用 + + let enabled_comp = ComponentBuilderFactory::enabled_base_component().build(); + assert!(enabled_comp.enabled()); + + let disabled_comp = ComponentBuilderFactory::disabled_base_component().build(); + assert!(!disabled_comp.enabled()); + } + + #[test] + fn test_component_builder_validation() { + let component = BaseComponent::new(); + let builder = ComponentBuilder::new(component); + + // 验证成功 + let result = builder.validate_and_build(|_| Ok(())); + assert!(result.is_ok()); + + // 验证失败 + let component2 = BaseComponent::new(); + let builder2 = ComponentBuilder::new(component2); + let result2 = builder2.validate_and_build(|_| Err("Invalid component".to_string())); + assert!(result2.is_err()); + assert_eq!(result2.unwrap_err(), "Invalid component"); + } + + #[test] + fn test_component_builder_stats() { + let mut stats = ComponentBuilderStats::new(); + + stats.record_base_component_built(); + stats.record_custom_component_built(); + stats.record_validation_failure(); + + assert_eq!(stats.total_components_built, 2); + assert_eq!(stats.base_components_built, 1); + assert_eq!(stats.custom_components_built, 1); + assert_eq!(stats.validation_failures, 1); + assert!((stats.success_rate() - 0.6666666666666666).abs() < 0.0001); + } + + #[test] + fn test_component_builder_stats_reset() { + let mut stats = ComponentBuilderStats::new(); + + stats.record_base_component_built(); + stats.reset(); + + assert_eq!(stats.total_components_built, 0); + assert_eq!(stats.base_components_built, 0); + assert_eq!(stats.custom_components_built, 0); + assert_eq!(stats.validation_failures, 0); + } + + #[test] + fn test_component_builder_stats_success_rate_empty() { + let stats = ComponentBuilderStats::new(); + assert_eq!(stats.success_rate(), 1.0); + } +} \ No newline at end of file diff --git a/packages/core-rust/src/core/entity.rs b/packages/core-rust/src/core/entity.rs new file mode 100644 index 00000000..dc2f2777 --- /dev/null +++ b/packages/core-rust/src/core/entity.rs @@ -0,0 +1,638 @@ +use crate::core::component::Component; +use rustc_hash::FxHashMap; +use std::any::TypeId; +use std::collections::hash_map::DefaultHasher; +use std::hash::{Hash, Hasher}; + +/// 将TypeId转换为u64的帮助函数 +fn type_id_to_u64(type_id: TypeId) -> u64 { + let mut hasher = DefaultHasher::new(); + type_id.hash(&mut hasher); + hasher.finish() +} + +/** + * 实体比较器 + * + * 用于比较两个实体的优先级,首先按更新顺序比较,然后按ID比较 + */ +pub struct EntityComparer; + +impl EntityComparer { + /** + * 比较两个实体 + * + * @param self_entity - 第一个实体 + * @param other_entity - 第二个实体 + * @returns 比较结果,负数表示self优先级更高,正数表示other优先级更高,0表示相等 + */ + pub fn compare(self_entity: &Entity, other_entity: &Entity) -> i32 { + let mut compare = self_entity.update_order - other_entity.update_order; + if compare == 0 { + compare = self_entity.id as i32 - other_entity.id as i32; + } + compare + } +} + +/** + * 游戏实体类 + * + * ECS架构中的实体(Entity),作为组件的容器。 + * 实体本身不包含游戏逻辑,所有功能都通过组件来实现。 + * 支持父子关系,可以构建实体层次结构。 + */ +#[derive(Clone)] +pub struct Entity { + /// 实体名称,用于标识和调试的友好名称 + pub name: String, + + /// 实体唯一标识符,在场景中唯一的数字标识符 + pub id: u32, + + /// 更新间隔,控制实体更新的频率,值越大更新越不频繁 + pub update_interval: u32, + + /// 私有字段,通过getter/setter访问 + active: bool, + enabled: bool, + is_destroyed: bool, + tag: u32, + update_order: i32, + + /// 父实体ID + parent_id: Option, + + /// 子实体ID集合 + children_ids: Vec, + + /// 组件位掩码,用于快速查询实体拥有的组件类型 + component_mask: u64, + + /// 组件实例存储 (TypeId -> 组件数据) + components: FxHashMap>, + + /// 组件类型到索引的映射,用于快速定位组件在数组中的位置 + component_type_to_index: FxHashMap, + + /// 组件列表(用于保持插入顺序和索引访问) + component_list: Vec>>, +} + + +impl Entity { + /** + * 构造函数 + */ + pub fn new(id: u32) -> Self { + Self { + name: String::new(), + id, + update_interval: 1, + active: true, + enabled: true, + is_destroyed: false, + tag: 0, + update_order: 0, + parent_id: None, + children_ids: Vec::new(), + component_mask: 0, + components: FxHashMap::default(), + component_type_to_index: FxHashMap::default(), + component_list: Vec::new(), + } + } + + /** + * 构造函数(带名称) + */ + pub fn new_with_name(name: String, id: u32) -> Self { + Self { + name, + id, + update_interval: 1, + active: true, + enabled: true, + is_destroyed: false, + tag: 0, + update_order: 0, + parent_id: None, + children_ids: Vec::new(), + component_mask: 0, + components: FxHashMap::default(), + component_type_to_index: FxHashMap::default(), + component_list: Vec::new(), + } + } + + // ========== 属性访问器 ========== + + /** + * 获取实体ID + */ + pub fn id(&self) -> u32 { + self.id + } + + /** + * 设置实体ID + */ + pub fn set_id(&mut self, id: u32) { + self.id = id; + } + + /** + * 获取实体名称 + */ + pub fn name(&self) -> Option { + if self.name.is_empty() { + None + } else { + Some(self.name.clone()) + } + } + + /** + * 设置实体名称 + */ + pub fn set_name(&mut self, name: String) { + self.name = name; + } + + /** + * 获取标签集合(暂时返回单个标签作为集合) + */ + pub fn tags(&self) -> std::collections::HashSet { + let mut tags = std::collections::HashSet::new(); + if self.tag != 0 { + tags.insert(self.tag); + } + tags + } + + /** + * 检查是否有指定标签 + */ + pub fn has_tag(&self, tag: u32) -> bool { + self.tag == tag + } + + /** + * 添加标签 + */ + pub fn add_tag(&mut self, tag: u32) { + self.tag = tag; // 简化版本,只支持单个标签 + } + + /** + * 移除标签 + */ + pub fn remove_tag(&mut self, tag: u32) { + if self.tag == tag { + self.tag = 0; + } + } + + pub fn active(&self) -> bool { + self.active + } + + pub fn set_active(&mut self, value: bool) { + if self.active != value { + self.active = value; + self.on_active_changed(); + } + } + + pub fn enabled(&self) -> bool { + self.enabled + } + + pub fn set_enabled(&mut self, value: bool) { + self.enabled = value; + } + + pub fn tag(&self) -> u32 { + self.tag + } + + pub fn set_tag(&mut self, value: u32) { + self.tag = value; + } + + pub fn update_order(&self) -> i32 { + self.update_order + } + + pub fn set_update_order(&mut self, value: i32) { + self.update_order = value; + } + + pub fn is_destroyed(&self) -> bool { + self.is_destroyed + } + + pub fn get_parent_id(&self) -> Option { + self.parent_id + } + + pub fn child_count(&self) -> usize { + self.children_ids.len() + } + + pub fn get_component_mask(&self) -> u64 { + self.component_mask + } + + pub fn get_children_ids(&self) -> Vec { + self.children_ids.clone() + } + + // ========== 内部访问方法 ========== + + /** + * 获取子实体ID的切片引用(内部使用) + */ + pub fn children_ids(&self) -> &[u32] { + &self.children_ids + } + + /** + * 获取父实体ID(内部使用) + */ + pub fn parent_id(&self) -> Option { + self.parent_id + } + + /** + * 设置组件位掩码(内部使用) + */ + pub fn set_component_mask(&mut self, mask: u64) { + self.component_mask = mask; + } + + /** + * 获取调试信息字符串 + */ + pub fn get_debug_info(&self) -> String { + format!( + "{{\"name\":\"{}\",\"id\":{},\"enabled\":{},\"active\":{},\"destroyed\":{},\"component_count\":{},\"tag\":{},\"update_order\":{},\"child_count\":{}}}", + self.name, + self.id, + self.enabled, + self.active, + self.is_destroyed, + self.components.len(), + self.tag, + self.update_order, + self.children_ids.len() + ) + } + + /** + * 获取调试信息结构体(内部使用) + */ + pub fn get_debug_info_struct(&self) -> EntityDebugInfo { + EntityDebugInfo { + name: self.name.clone(), + id: self.id, + enabled: self.enabled, + active: self.active, + destroyed: self.is_destroyed, + component_count: self.components.len(), + component_mask: format!("{:b}", self.component_mask), + parent_id: self.parent_id, + child_count: self.children_ids.len(), + child_ids: self.children_ids.clone(), + tag: self.tag, + update_order: self.update_order, + index_mapping_size: self.component_type_to_index.len(), + } + } + + // ========== 组件管理 ========== + + /** + * 内部添加组件方法(不进行重复检查,用于初始化) + */ + fn add_component_internal(&mut self, component: T) -> &T { + let type_id = TypeId::of::(); + let boxed_component = Box::new(component); + + // 添加到组件列表并建立索引映射 + let index = self.component_list.len(); + self.component_list.push(Some(boxed_component.clone_box())); + self.component_type_to_index.insert(type_id, index); + + // 添加到类型映射 + self.components.insert(type_id, boxed_component); + + // 这里应该更新位掩码,但需要ComponentRegistry + // 暂时使用简单的类型ID哈希作为掩码 + self.component_mask |= 1u64.wrapping_shl(type_id_to_u64(type_id) as u32 % 64); + + // 返回引用(这里简化处理) + self.components.get(&type_id).unwrap().as_any().downcast_ref::().unwrap() + } + + /** + * 添加组件到实体 + */ + pub fn add_component(&mut self, component: T) -> Result<&T, String> { + let type_id = TypeId::of::(); + + // 检查是否已有此类型的组件 + if self.has_component::() { + return Err(format!("Entity {} already has component of type {:?}", self.name, type_id)); + } + + // 使用内部方法添加组件 + Ok(self.add_component_internal(component)) + } + + /** + * 获取指定类型的组件 + */ + pub fn get_component(&self) -> Option<&T> { + let type_id = TypeId::of::(); + + // 首先检查位掩码,快速排除(简化版本) + let type_mask = 1u64.wrapping_shl(type_id_to_u64(type_id) as u32 % 64); + if (self.component_mask & type_mask) == 0 { + return None; + } + + // 从类型映射获取 + self.components.get(&type_id).and_then(|component| { + component.as_any().downcast_ref::() + }) + } + + /** + * 获取指定类型的可变组件 + */ + pub fn get_component_mut(&mut self) -> Option<&mut T> { + let type_id = TypeId::of::(); + + // 首先检查位掩码,快速排除 + let type_mask = 1u64.wrapping_shl(type_id_to_u64(type_id) as u32 % 64); + if (self.component_mask & type_mask) == 0 { + return None; + } + + // 从类型映射获取可变引用 + self.components.get_mut(&type_id).and_then(|component| { + component.as_any_mut().downcast_mut::() + }) + } + + /** + * 检查实体是否有指定类型的组件 + */ + pub fn has_component(&self) -> bool { + let type_id = TypeId::of::(); + let type_mask = 1u64.wrapping_shl(type_id_to_u64(type_id) as u32 % 64); + (self.component_mask & type_mask) != 0 + } + + /** + * 获取或创建指定类型的组件 + */ + pub fn get_or_create_component(&mut self) -> &T { + if self.has_component::() { + self.get_component::().unwrap() + } else { + let component = T::default(); + self.add_component_internal(component) + } + } + + /** + * 移除指定类型的组件 + */ + pub fn remove_component(&mut self) -> Option> { + let type_id = TypeId::of::(); + + if let Some(component) = self.components.remove(&type_id) { + // 更新位掩码 + let type_mask = 1u64.wrapping_shl(type_id_to_u64(type_id) as u32 % 64); + self.component_mask &= !type_mask; + + // 从索引映射中移除并重建索引 + if let Some(index) = self.component_type_to_index.remove(&type_id) { + if index < self.component_list.len() { + self.component_list[index] = None; + } + self.rebuild_component_index(); + } + + Some(component) + } else { + None + } + } + + /** + * 移除所有组件 + */ + pub fn remove_all_components(&mut self) { + self.component_type_to_index.clear(); + self.component_mask = 0; + self.components.clear(); + self.component_list.clear(); + } + + /** + * 获取组件数量 + */ + pub fn component_count(&self) -> usize { + self.components.len() + } + + /** + * 重建组件索引映射 + */ + fn rebuild_component_index(&mut self) { + self.component_type_to_index.clear(); + + let mut new_list = Vec::new(); + for (_i, component_opt) in self.component_list.iter().enumerate() { + if let Some(component) = component_opt { + let type_id = component.type_id(); + self.component_type_to_index.insert(type_id, new_list.len()); + new_list.push(Some(component.clone_box())); + } + } + self.component_list = new_list; + } + + // ========== 层次结构管理 ========== + + /** + * 添加子实体ID + */ + pub fn add_child_id(&mut self, child_id: u32) -> Result<(), String> { + if child_id == self.id { + return Err("Entity cannot be its own child".to_string()); + } + + if self.children_ids.contains(&child_id) { + return Ok(()); // 已经是子实体 + } + + self.children_ids.push(child_id); + Ok(()) + } + + /** + * 移除子实体ID + */ + pub fn remove_child_id(&mut self, child_id: u32) -> bool { + if let Some(pos) = self.children_ids.iter().position(|&id| id == child_id) { + self.children_ids.remove(pos); + true + } else { + false + } + } + + /** + * 设置父实体ID + */ + pub fn set_parent_id(&mut self, parent_id: Option) { + self.parent_id = parent_id; + } + + /** + * 移除所有子实体ID + */ + pub fn remove_all_children_ids(&mut self) { + self.children_ids.clear(); + } + + // ========== 生命周期方法 ========== + + /** + * 激活状态改变时的回调 + */ + fn on_active_changed(&mut self) { + // 通知所有组件激活状态改变 + for component in self.components.values_mut() { + component.on_active_changed(); + } + } + + /** + * 更新实体 + */ + pub fn update(&mut self) { + if !self.active || self.is_destroyed { + return; + } + + // 更新所有组件 + for component in self.components.values_mut() { + if component.enabled() { + component.update(); + } + } + } + + /** + * 销毁实体 + */ + pub fn destroy(&mut self) { + if self.is_destroyed { + return; + } + + self.is_destroyed = true; + + // 移除所有组件 + self.remove_all_components(); + + // 清空子实体ID(实际的子实体销毁由EntityManager处理) + self.children_ids.clear(); + + // 清空父实体引用 + self.parent_id = None; + } + + /** + * 比较实体 + */ + pub fn compare_to(&self, other: &Entity) -> i32 { + EntityComparer::compare(self, other) + } + + /** + * 获取实体的字符串表示 + */ + pub fn to_string(&self) -> String { + format!("Entity[{}:{}]", self.name, self.id) + } + + /** + * 获取实体的调试信息结构体 + */ + pub fn get_debug_info_detailed(&self) -> EntityDebugInfo { + EntityDebugInfo { + name: self.name.clone(), + id: self.id, + enabled: self.enabled, + active: self.active, + destroyed: self.is_destroyed, + component_count: self.components.len(), + component_mask: format!("{:b}", self.component_mask), + parent_id: self.parent_id, + child_count: self.children_ids.len(), + child_ids: self.children_ids.clone(), + tag: self.tag, + update_order: self.update_order, + index_mapping_size: self.component_type_to_index.len(), + } + } +} + +/** + * 实体调试信息 + */ +#[derive(serde::Serialize, serde::Deserialize)] +pub struct EntityDebugInfo { + pub name: String, + pub id: u32, + pub enabled: bool, + pub active: bool, + pub destroyed: bool, + pub component_count: usize, + pub component_mask: String, + pub parent_id: Option, + pub child_count: usize, + pub child_ids: Vec, + pub tag: u32, + pub update_order: i32, + pub index_mapping_size: usize, +} + +impl std::fmt::Display for Entity { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Entity[{}:{}]", self.name, self.id) + } +} + +impl std::fmt::Debug for Entity { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Entity") + .field("name", &self.name) + .field("id", &self.id) + .field("active", &self.active) + .field("enabled", &self.enabled) + .field("is_destroyed", &self.is_destroyed) + .field("tag", &self.tag) + .field("update_order", &self.update_order) + .field("parent_id", &self.parent_id) + .field("children_count", &self.children_ids.len()) + .field("component_count", &self.components.len()) + .finish() + } +} \ No newline at end of file diff --git a/packages/core-rust/src/core/entity_batch_operator.rs b/packages/core-rust/src/core/entity_batch_operator.rs new file mode 100644 index 00000000..44664bfb --- /dev/null +++ b/packages/core-rust/src/core/entity_batch_operator.rs @@ -0,0 +1,630 @@ +use std::collections::HashMap; +use crate::core::{Entity, ComponentRegistry}; + +/** + * 实体批量操作器 + * 提供对多个实体的批量操作功能 + */ +pub struct EntityBatchOperator { + entities: Vec, + component_registry: ComponentRegistry, +} + +impl EntityBatchOperator { + /** + * 创建批量操作器 + */ + pub fn new(entities: Vec) -> Self { + Self { + entities, + component_registry: ComponentRegistry::new(), + } + } + + /** + * 从实体ID创建批量操作器 + */ + pub fn from_ids(entity_ids: Vec) -> Self { + let entities: Vec = entity_ids + .into_iter() + .map(|id| { + let mut entity = Entity::new(id); + entity.set_id(id); + entity + }) + .collect(); + Self::new(entities) + } + + /** + * 批量设置活跃状态 + */ + pub fn set_enabled(&mut self, enabled: bool) -> &mut Self { + for entity in &mut self.entities { + entity.set_enabled(enabled); + } + self + } + + /** + * 批量设置名称 + */ + pub fn set_name(&mut self, name: &str) -> &mut Self { + for entity in &mut self.entities { + entity.set_name(name.to_string()); + } + self + } + + /** + * 批量设置标签 + */ + pub fn set_tag(&mut self, tag: u32) -> &mut Self { + for entity in &mut self.entities { + entity.set_tag(tag); + } + self + } + + /** + * 批量添加标签 + */ + pub fn add_tag(&mut self, tag: u32) -> &mut Self { + for entity in &mut self.entities { + entity.add_tag(tag); + } + self + } + + /** + * 批量移除标签 + */ + pub fn remove_tag(&mut self, tag: u32) -> &mut Self { + for entity in &mut self.entities { + entity.remove_tag(tag); + } + self + } + + /** + * 批量执行操作 + */ + pub fn for_each(&mut self, mut operation: F) -> &mut Self + where + F: FnMut(&mut Entity, usize), + { + for (index, entity) in self.entities.iter_mut().enumerate() { + operation(entity, index); + } + self + } + + /** + * 批量执行只读操作 + */ + pub fn for_each_readonly(&self, mut operation: F) -> &Self + where + F: FnMut(&Entity, usize), + { + for (index, entity) in self.entities.iter().enumerate() { + operation(entity, index); + } + self + } + + /** + * 过滤实体 + */ + pub fn filter(self, predicate: F) -> Self + where + F: Fn(&Entity) -> bool, + { + let filtered_entities: Vec = self.entities + .into_iter() + .filter(|entity| predicate(entity)) + .collect(); + + Self::new(filtered_entities) + } + + /** + * 按条件分组 + */ + pub fn group_by(self, key_fn: F) -> HashMap + where + F: Fn(&Entity) -> K, + K: Eq + std::hash::Hash, + { + let mut groups: HashMap> = HashMap::new(); + + for entity in self.entities { + let key = key_fn(&entity); + groups.entry(key).or_insert_with(Vec::new).push(entity); + } + + groups.into_iter() + .map(|(key, entities)| (key, EntityBatchOperator::new(entities))) + .collect() + } + + /** + * 获取实体数量 + */ + pub fn count(&self) -> usize { + self.entities.len() + } + + /** + * 检查是否为空 + */ + pub fn is_empty(&self) -> bool { + self.entities.is_empty() + } + + /** + * 获取第一个实体的只读引用 + */ + pub fn first(&self) -> Option<&Entity> { + self.entities.first() + } + + /** + * 获取第一个实体的可变引用 + */ + pub fn first_mut(&mut self) -> Option<&mut Entity> { + self.entities.first_mut() + } + + /** + * 获取最后一个实体的只读引用 + */ + pub fn last(&self) -> Option<&Entity> { + self.entities.last() + } + + /** + * 获取最后一个实体的可变引用 + */ + pub fn last_mut(&mut self) -> Option<&mut Entity> { + self.entities.last_mut() + } + + /** + * 获取指定索引的实体 + */ + pub fn get(&self, index: usize) -> Option<&Entity> { + self.entities.get(index) + } + + /** + * 获取指定索引的可变实体 + */ + pub fn get_mut(&mut self, index: usize) -> Option<&mut Entity> { + self.entities.get_mut(index) + } + + /** + * 清空所有实体 + */ + pub fn clear(&mut self) -> &mut Self { + self.entities.clear(); + self + } + + /** + * 添加实体 + */ + pub fn add_entity(&mut self, entity: Entity) -> &mut Self { + self.entities.push(entity); + self + } + + /** + * 添加多个实体 + */ + pub fn add_entities(&mut self, mut entities: Vec) -> &mut Self { + self.entities.append(&mut entities); + self + } + + /** + * 移除指定索引的实体 + */ + pub fn remove_at(&mut self, index: usize) -> Option { + if index < self.entities.len() { + Some(self.entities.remove(index)) + } else { + None + } + } + + /** + * 移除满足条件的实体 + */ + pub fn remove_if(&mut self, predicate: F) -> &mut Self + where + F: Fn(&Entity) -> bool, + { + self.entities.retain(|entity| !predicate(entity)); + self + } + + /** + * 获取所有实体ID + */ + pub fn get_entity_ids(&self) -> Vec { + self.entities.iter().map(|entity| entity.id()).collect() + } + + /** + * 检查是否包含指定ID的实体 + */ + pub fn contains_entity(&self, entity_id: u32) -> bool { + self.entities.iter().any(|entity| entity.id() == entity_id) + } + + /** + * 按ID查找实体 + */ + pub fn find_by_id(&self, entity_id: u32) -> Option<&Entity> { + self.entities.iter().find(|entity| entity.id() == entity_id) + } + + /** + * 按ID查找可变实体 + */ + pub fn find_by_id_mut(&mut self, entity_id: u32) -> Option<&mut Entity> { + self.entities.iter_mut().find(|entity| entity.id() == entity_id) + } + + /** + * 按名称查找实体 + */ + pub fn find_by_name(&self, name: &str) -> Vec<&Entity> { + self.entities + .iter() + .filter(|entity| entity.name().as_deref() == Some(name)) + .collect() + } + + /** + * 按标签查找实体 + */ + pub fn find_by_tag(&self, tag: u32) -> Vec<&Entity> { + self.entities + .iter() + .filter(|entity| entity.has_tag(tag)) + .collect() + } + + /** + * 获取启用的实体 + */ + pub fn get_enabled(&self) -> Vec<&Entity> { + self.entities + .iter() + .filter(|entity| entity.enabled()) + .collect() + } + + /** + * 获取禁用的实体 + */ + pub fn get_disabled(&self) -> Vec<&Entity> { + self.entities + .iter() + .filter(|entity| !entity.enabled()) + .collect() + } + + /** + * 排序实体 + */ + pub fn sort_by(&mut self, compare: F) -> &mut Self + where + F: FnMut(&Entity, &Entity) -> std::cmp::Ordering, + { + self.entities.sort_by(compare); + self + } + + /** + * 按ID排序 + */ + pub fn sort_by_id(&mut self) -> &mut Self { + self.entities.sort_by(|a, b| a.id().cmp(&b.id())); + self + } + + /** + * 按名称排序 + */ + pub fn sort_by_name(&mut self) -> &mut Self { + self.entities.sort_by(|a, b| a.name().cmp(&b.name())); + self + } + + /** + * 转换为实体数组 + */ + pub fn to_vec(self) -> Vec { + self.entities + } + + /** + * 转换为实体ID数组 + */ + pub fn to_id_vec(&self) -> Vec { + self.get_entity_ids() + } + + /** + * 克隆实体数组 + */ + pub fn clone_entities(&self) -> Vec { + self.entities.clone() + } +} + +/** + * 批量操作统计信息 + */ +#[derive(Debug, Clone)] +pub struct BatchOperatorStats { + pub total_operations: u64, + pub entities_processed: u64, + pub filters_applied: u64, + pub groups_created: u64, + pub sorts_performed: u64, +} + +impl BatchOperatorStats { + pub fn new() -> Self { + Self { + total_operations: 0, + entities_processed: 0, + filters_applied: 0, + groups_created: 0, + sorts_performed: 0, + } + } + + /** + * 重置统计信息 + */ + pub fn reset(&mut self) { + self.total_operations = 0; + self.entities_processed = 0; + self.filters_applied = 0; + self.groups_created = 0; + self.sorts_performed = 0; + } + + /** + * 记录操作 + */ + pub fn record_operation(&mut self, entities_count: usize) { + self.total_operations += 1; + self.entities_processed += entities_count as u64; + } + + /** + * 记录过滤操作 + */ + pub fn record_filter(&mut self) { + self.filters_applied += 1; + } + + /** + * 记录分组操作 + */ + pub fn record_group(&mut self) { + self.groups_created += 1; + } + + /** + * 记录排序操作 + */ + pub fn record_sort(&mut self) { + self.sorts_performed += 1; + } + + /** + * 获取平均处理实体数 + */ + pub fn average_entities_per_operation(&self) -> f64 { + if self.total_operations == 0 { + 0.0 + } else { + self.entities_processed as f64 / self.total_operations as f64 + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn create_test_entities() -> Vec { + vec![ + { + let mut e = Entity::new(1); + e.set_name("Entity1".to_string()); + e.set_tag(100); + e + }, + { + let mut e = Entity::new(2); + e.set_name("Entity2".to_string()); + e.set_tag(200); + e.set_enabled(false); + e + }, + { + let mut e = Entity::new(3); + e.set_name("Entity3".to_string()); + e.set_tag(100); + e + }, + ] + } + + #[test] + fn test_batch_operator_creation() { + let entities = create_test_entities(); + let operator = EntityBatchOperator::new(entities); + assert_eq!(operator.count(), 3); + assert!(!operator.is_empty()); + } + + #[test] + fn test_batch_operator_from_ids() { + let ids = vec![1, 2, 3]; + let operator = EntityBatchOperator::from_ids(ids); + assert_eq!(operator.count(), 3); + assert_eq!(operator.get_entity_ids(), vec![1, 2, 3]); + } + + #[test] + fn test_batch_set_enabled() { + let entities = create_test_entities(); + let mut operator = EntityBatchOperator::new(entities); + + operator.set_enabled(false); + assert_eq!(operator.get_enabled().len(), 0); + assert_eq!(operator.get_disabled().len(), 3); + } + + #[test] + fn test_batch_set_name() { + let entities = create_test_entities(); + let mut operator = EntityBatchOperator::new(entities); + + operator.set_name("NewName"); + for entity in operator.entities.iter() { + assert_eq!(entity.name().as_deref(), Some("NewName")); + } + } + + #[test] + fn test_batch_tags() { + let entities = create_test_entities(); + let mut operator = EntityBatchOperator::new(entities); + + operator.add_tag(999); + for entity in operator.entities.iter() { + assert!(entity.has_tag(999)); + } + + operator.remove_tag(999); + for entity in operator.entities.iter() { + assert!(!entity.has_tag(999)); + } + } + + #[test] + fn test_batch_for_each() { + let entities = create_test_entities(); + let mut operator = EntityBatchOperator::new(entities); + + let mut count = 0; + operator.for_each(|_, index| { + count += index + 1; + }); + assert_eq!(count, 6); // 1 + 2 + 3 + } + + #[test] + fn test_batch_filter() { + let entities = create_test_entities(); + let operator = EntityBatchOperator::new(entities); + + let filtered = operator.filter(|entity| entity.has_tag(100)); + assert_eq!(filtered.count(), 2); + } + + #[test] + fn test_batch_group_by() { + let entities = create_test_entities(); + let operator = EntityBatchOperator::new(entities); + + let groups = operator.group_by(|entity| entity.enabled()); + assert_eq!(groups.len(), 2); + assert!(groups.contains_key(&true)); + assert!(groups.contains_key(&false)); + } + + #[test] + fn test_batch_first_last() { + let entities = create_test_entities(); + let mut operator = EntityBatchOperator::new(entities); + + assert_eq!(operator.first().unwrap().id(), 1); + assert_eq!(operator.last().unwrap().id(), 3); + + operator.first_mut().unwrap().set_name("Modified".to_string()); + assert_eq!(operator.first().unwrap().name().as_deref(), Some("Modified")); + } + + #[test] + fn test_batch_find_operations() { + let entities = create_test_entities(); + let operator = EntityBatchOperator::new(entities); + + assert!(operator.find_by_id(2).is_some()); + assert!(operator.find_by_id(999).is_none()); + + let found_by_name = operator.find_by_name("Entity2"); + assert_eq!(found_by_name.len(), 1); + + let found_by_tag = operator.find_by_tag(100); + assert_eq!(found_by_tag.len(), 2); + } + + #[test] + fn test_batch_sort() { + let entities = create_test_entities(); + let mut operator = EntityBatchOperator::new(entities); + + // 按ID降序排序 + operator.sort_by(|a, b| b.id().cmp(&a.id())); + assert_eq!(operator.get(0).unwrap().id(), 3); + assert_eq!(operator.get(2).unwrap().id(), 1); + + // 按ID升序排序 + operator.sort_by_id(); + assert_eq!(operator.get(0).unwrap().id(), 1); + assert_eq!(operator.get(2).unwrap().id(), 3); + } + + #[test] + fn test_batch_stats() { + let mut stats = BatchOperatorStats::new(); + + stats.record_operation(5); + stats.record_filter(); + stats.record_group(); + stats.record_sort(); + + assert_eq!(stats.total_operations, 1); + assert_eq!(stats.entities_processed, 5); + assert_eq!(stats.filters_applied, 1); + assert_eq!(stats.groups_created, 1); + assert_eq!(stats.sorts_performed, 1); + assert_eq!(stats.average_entities_per_operation(), 5.0); + } + + #[test] + fn test_batch_remove_operations() { + let entities = create_test_entities(); + let mut operator = EntityBatchOperator::new(entities); + + let removed = operator.remove_at(1); + assert!(removed.is_some()); + assert_eq!(removed.unwrap().id(), 2); + assert_eq!(operator.count(), 2); + + operator.remove_if(|entity| entity.has_tag(100)); + assert_eq!(operator.count(), 0); + } +} \ No newline at end of file diff --git a/packages/core-rust/src/core/entity_manager.rs b/packages/core-rust/src/core/entity_manager.rs new file mode 100644 index 00000000..b66ad6af --- /dev/null +++ b/packages/core-rust/src/core/entity_manager.rs @@ -0,0 +1,405 @@ +use crate::core::entity::Entity; +use crate::storage::component_storage::ComponentStorageManager; +use crate::core::component::Component; +use crate::utils::IdentifierPool; +use rustc_hash::FxHashMap; + +/** + * 实体管理器 + * 提供统一的实体管理和查询机制,支持高效的实体操作 + * 使用IdentifierPool进行世代式ID管理,防止悬空引用 + */ +pub struct EntityManager { + entities: FxHashMap, + entities_by_name: FxHashMap>, + entities_by_tag: FxHashMap>, + id_pool: IdentifierPool, + destroyed_entities: std::collections::HashSet, + component_storage_manager: ComponentStorageManager, +} + +impl EntityManager { + /** + * 创建实体管理器实例 + */ + pub fn new() -> Self { + Self { + entities: FxHashMap::default(), + entities_by_name: FxHashMap::default(), + entities_by_tag: FxHashMap::default(), + id_pool: IdentifierPool::with_defaults(), + destroyed_entities: std::collections::HashSet::new(), + component_storage_manager: ComponentStorageManager::new(), + } + } + + /** + * 获取实体总数 + */ + pub fn entity_count(&self) -> usize { + self.entities.len() + } + + /** + * 获取激活状态的实体数量 + */ + pub fn active_entity_count(&self) -> usize { + self.entities + .values() + .filter(|entity| entity.active() && !entity.is_destroyed()) + .count() + } + + /** + * 创建新实体 + * @param name 实体名称,如果未指定则使用实体ID生成默认名称 + * @returns 创建的实体ID(世代式ID) + */ + pub fn create_entity(&mut self, name: Option) -> u32 { + let id = match self.id_pool.check_out() { + Ok(id) => id, + Err(e) => { + // ID池已满,记录错误并返回一个无效ID + eprintln!("Failed to create entity: {}", e); + return u32::MAX; // 返回无效ID作为错误标识 + } + }; + + let entity_name = name.unwrap_or_else(|| format!("Entity_{}", id)); + let mut entity = Entity::new(id); + entity.set_name(entity_name.clone()); + + self.entities.insert(id, entity); + self.update_name_index(id, &entity_name, true); + self.update_tag_index(id, 0, true); + + id + } + + /** + * 批量创建实体 + * @param count 要创建的实体数量 + * @param name_prefix 实体名称前缀,默认为 Entity + * @returns 创建的实体ID数组 + */ + pub fn create_entities_batch(&mut self, count: u32, name_prefix: Option) -> Vec { + if count == 0 { + return Vec::new(); + } + + let prefix = name_prefix.unwrap_or_else(|| "Entity".to_string()); + let mut entity_ids = Vec::with_capacity(count as usize); + + for _ in 0..count { + let id = match self.id_pool.check_out() { + Ok(id) => id, + Err(e) => { + eprintln!("Failed to create entity in batch: {}", e); + break; // 停止创建更多实体 + } + }; + + let entity_name = format!("{}_{}", prefix, id); + let mut entity = Entity::new(id); + entity.set_name(entity_name.clone()); + + entity_ids.push(id); + self.entities.insert(id, entity); + } + + for &id in &entity_ids { + if let Some(entity) = self.entities.get(&id) { + let name = entity.name.clone(); + let tag = entity.tag(); + self.update_name_index(id, &name, true); + self.update_tag_index(id, tag, true); + } + } + + entity_ids + } + + /** + * 销毁实体 + * @param entity_id 要销毁的实体ID + * @returns 是否成功销毁实体 + */ + pub fn destroy_entity(&mut self, entity_id: u32) -> bool { + // 首先验证ID是否有效 + if !self.id_pool.is_valid(entity_id) { + return false; + } + + if let Some(mut entity) = self.entities.remove(&entity_id) { + self.destroyed_entities.insert(entity_id); + self.update_name_index(entity_id, &entity.name, false); + self.update_tag_index(entity_id, entity.tag(), false); + + self.component_storage_manager.remove_all_components(entity_id); + + entity.destroy(); + + // 回收ID到池中 + self.id_pool.check_in(entity_id); + + true + } else { + false + } + } + + /** + * 获取所有实体ID + */ + pub fn get_all_entity_ids(&self) -> Vec { + self.entities.keys().copied().collect() + } + + /** + * 根据ID获取实体 + * @param id 实体ID + * @returns 对应的实体引用,如果不存在则返回None + */ + pub fn get_entity(&self, id: u32) -> Option<&Entity> { + self.entities.get(&id) + } + + /** + * 根据ID获取可变实体 + * @param id 实体ID + * @returns 对应的可变实体引用,如果不存在则返回None + */ + pub fn get_entity_mut(&mut self, id: u32) -> Option<&mut Entity> { + self.entities.get_mut(&id) + } + + /** + * 根据名称获取实体 + * @param name 实体名称 + * @returns 匹配的实体ID,如果不存在则返回None + */ + pub fn get_entity_by_name(&self, name: &str) -> Option { + self.entities_by_name + .get(name) + .and_then(|entities| entities.first()) + .copied() + } + + /** + * 根据标签获取实体列表 + * @param tag 标签值 + * @returns 具有指定标签的实体ID数组 + */ + pub fn get_entities_by_tag(&self, tag: u32) -> Vec { + self.entities_by_tag + .get(&tag) + .cloned() + .unwrap_or_else(Vec::new) + } + + /** + * 为实体添加组件 + * @param entity_id 实体ID + * @param component 组件实例 + */ + pub fn add_component(&mut self, entity_id: u32, component: T) -> Result<(), String> { + if !self.entities.contains_key(&entity_id) { + return Err(format!("Entity {} does not exist", entity_id)); + } + + self.component_storage_manager.add_component(entity_id, component)?; + + if let Some(entity) = self.entities.get_mut(&entity_id) { + let mask = self.component_storage_manager.get_component_mask(entity_id); + entity.set_component_mask(mask); + } + + Ok(()) + } + + /** + * 获取实体的组件位掩码 + * @param entity_id 实体ID + * @returns 组件位掩码 + */ + pub fn get_component_mask(&self, entity_id: u32) -> u64 { + self.component_storage_manager.get_component_mask(entity_id) + } + + /** + * 获取组件存储管理器 + */ + pub fn get_component_storage_manager(&self) -> &ComponentStorageManager { + &self.component_storage_manager + } + + /** + * 获取可变组件存储管理器 + */ + pub fn get_component_storage_manager_mut(&mut self) -> &mut ComponentStorageManager { + &mut self.component_storage_manager + } + + /** + * 更新名称索引 + * @param entity_id 实体ID + * @param name 实体名称 + * @param is_add true表示添加到索引,false表示从索引中移除 + */ + fn update_name_index(&mut self, entity_id: u32, name: &str, is_add: bool) { + if is_add { + self.entities_by_name + .entry(name.to_string()) + .or_insert_with(Vec::new) + .push(entity_id); + } else { + if let Some(entities) = self.entities_by_name.get_mut(name) { + entities.retain(|&id| id != entity_id); + if entities.is_empty() { + self.entities_by_name.remove(name); + } + } + } + } + + /** + * 更新标签索引 + * @param entity_id 实体ID + * @param tag 标签值 + * @param is_add true表示添加到索引,false表示从索引中移除 + */ + fn update_tag_index(&mut self, entity_id: u32, tag: u32, is_add: bool) { + if is_add { + self.entities_by_tag + .entry(tag) + .or_insert_with(Vec::new) + .push(entity_id); + } else { + if let Some(entities) = self.entities_by_tag.get_mut(&tag) { + entities.retain(|&id| id != entity_id); + if entities.is_empty() { + self.entities_by_tag.remove(&tag); + } + } + } + } + + // ========== IdentifierPool相关方法 ========== + + /** + * 验证实体ID是否有效(考虑世代版本) + * @param entity_id 要验证的实体ID + * @returns 是否为有效的ID + */ + pub fn is_entity_id_valid(&self, entity_id: u32) -> bool { + self.id_pool.is_valid(entity_id) + } + + /** + * 强制处理延迟回收的ID + * 在某些情况下可能需要立即处理延迟回收队列 + */ + pub fn force_process_delayed_recycle(&mut self) { + self.id_pool.force_process_delayed_recycle(); + } + + /** + * 获取IdentifierPool统计信息 + * 用于调试和性能监控 + */ + pub fn get_id_pool_stats(&self) -> crate::utils::IdentifierPoolStats { + self.id_pool.get_stats() + } + + /** + * 检查实体是否存在且有效 + * 结合ID有效性检查和实际存在性检查 + */ + pub fn entity_exists_and_valid(&self, entity_id: u32) -> bool { + self.id_pool.is_valid(entity_id) && self.entities.contains_key(&entity_id) + } + + /** + * 获取有效实体的数量 + * 只计算ID有效且实际存在的实体 + */ + pub fn valid_entity_count(&self) -> usize { + self.entities.iter() + .filter(|(&id, _)| self.id_pool.is_valid(id)) + .count() + } + + /** + * 清理所有无效的实体引用 + * 清理那些ID已经无效的实体记录 + */ + pub fn cleanup_invalid_entities(&mut self) { + let invalid_ids: Vec = self.entities.keys() + .filter(|&&id| !self.id_pool.is_valid(id)) + .copied() + .collect(); + + for id in invalid_ids { + if let Some(entity) = self.entities.remove(&id) { + // 从索引中清理 + self.update_name_index(id, &entity.name, false); + self.update_tag_index(id, entity.tag(), false); + // 从销毁实体集合中清理 + self.destroyed_entities.remove(&id); + } + } + } + + /** + * 获取调试信息(包含ID池统计) + */ + pub fn get_debug_info(&self) -> String { + let id_stats = self.id_pool.get_stats(); + format!( + "{{\"entities\":{},\"active_entities\":{},\"valid_entities\":{},\"destroyed_entities\":{},\"id_pool\":{{\"total_allocated\":{},\"current_active\":{},\"pending_recycle\":{},\"memory_usage\":{}}}}}", + self.entity_count(), + self.active_entity_count(), + self.valid_entity_count(), + self.destroyed_entities.len(), + id_stats.total_allocated, + id_stats.current_active, + id_stats.pending_recycle, + id_stats.memory_usage + ) + } + + /** + * 添加实体到管理器 + */ + pub fn add_entity(&mut self, mut entity: Entity) { + let entity_id = if entity.id() == 0 { + // 如果实体ID为0,分配新ID + let new_id = self.id_pool.check_out().unwrap_or(0); + entity.set_id(new_id); + new_id + } else { + entity.id() + }; + + // 如果实体有名称,添加到名称索引 + if let Some(name) = entity.name() { + self.entities_by_name.entry(name.clone()).or_insert_with(Vec::new).push(entity_id); + } + + // 如果实体有标签,添加到标签索引 + for tag in &entity.tags() { + self.entities_by_tag.entry(*tag).or_insert_with(Vec::new).push(entity_id); + } + + self.entities.insert(entity_id, entity); + } + + /** + * 预留容量 + */ + pub fn reserve_capacity(&mut self, capacity: usize) { + self.entities.reserve(capacity); + self.entities_by_name.reserve(capacity / 10); // 假设10%的实体有名称 + self.entities_by_tag.reserve(capacity / 5); // 假设20%的实体有标签 + } +} \ No newline at end of file diff --git a/packages/core-rust/src/core/events.rs b/packages/core-rust/src/core/events.rs new file mode 100644 index 00000000..d0f411ad --- /dev/null +++ b/packages/core-rust/src/core/events.rs @@ -0,0 +1,574 @@ +use std::collections::HashMap; +use std::any::Any; + +/** + * ECS事件类型 + * 定义实体组件系统中的核心事件类型 + */ +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum ECSEventType { + // 实体相关事件 + EntityCreated, + EntityDestroyed, + EntityEnabled, + EntityDisabled, + EntityTagChanged, + EntityNameChanged, + + // 组件相关事件 + ComponentAdded, + ComponentRemoved, + ComponentModified, + ComponentEnabled, + ComponentDisabled, + + // 系统相关事件 + SystemAdded, + SystemRemoved, + SystemEnabled, + SystemDisabled, + SystemProcessingStart, + SystemProcessingEnd, + SystemError, + + // 场景相关事件 + SceneCreated, + SceneDestroyed, + SceneActivated, + SceneDeactivated, + + // 性能相关事件 + PerformanceWarning, + PerformanceCritical, + MemoryUsageHigh, + + // 查询相关事件 + QueryExecuted, + QueryCacheHit, + QueryCacheMiss, +} + +impl ECSEventType { + /** + * 转换为字符串表示 + */ + pub fn as_str(&self) -> &'static str { + match self { + ECSEventType::EntityCreated => "entity:created", + ECSEventType::EntityDestroyed => "entity:destroyed", + ECSEventType::EntityEnabled => "entity:enabled", + ECSEventType::EntityDisabled => "entity:disabled", + ECSEventType::EntityTagChanged => "entity:tag:changed", + ECSEventType::EntityNameChanged => "entity:name:changed", + ECSEventType::ComponentAdded => "component:added", + ECSEventType::ComponentRemoved => "component:removed", + ECSEventType::ComponentModified => "component:modified", + ECSEventType::ComponentEnabled => "component:enabled", + ECSEventType::ComponentDisabled => "component:disabled", + ECSEventType::SystemAdded => "system:added", + ECSEventType::SystemRemoved => "system:removed", + ECSEventType::SystemEnabled => "system:enabled", + ECSEventType::SystemDisabled => "system:disabled", + ECSEventType::SystemProcessingStart => "system:processing:start", + ECSEventType::SystemProcessingEnd => "system:processing:end", + ECSEventType::SystemError => "system:error", + ECSEventType::SceneCreated => "scene:created", + ECSEventType::SceneDestroyed => "scene:destroyed", + ECSEventType::SceneActivated => "scene:activated", + ECSEventType::SceneDeactivated => "scene:deactivated", + ECSEventType::PerformanceWarning => "performance:warning", + ECSEventType::PerformanceCritical => "performance:critical", + ECSEventType::MemoryUsageHigh => "memory:usage:high", + ECSEventType::QueryExecuted => "query:executed", + ECSEventType::QueryCacheHit => "query:cache:hit", + ECSEventType::QueryCacheMiss => "query:cache:miss", + } + } +} + +/** + * 事件优先级 + */ +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub enum EventPriority { + Lowest = 0, + Low = 25, + Normal = 50, + High = 75, + Highest = 100, + Critical = 200, +} + +/** + * 事件数据 + * 包含事件的所有信息 + */ +#[derive(Debug)] +pub struct Event { + pub event_type: ECSEventType, + pub priority: EventPriority, + pub timestamp: u64, + pub entity_id: Option, + pub data: Option>, + pub metadata: HashMap, +} + +impl Event { + /** + * 创建新事件 + */ + pub fn new(event_type: ECSEventType, priority: EventPriority) -> Self { + Self { + event_type, + priority, + timestamp: current_timestamp(), + entity_id: None, + data: None, + metadata: HashMap::new(), + } + } + + /** + * 设置实体ID + */ + pub fn with_entity_id(mut self, entity_id: u32) -> Self { + self.entity_id = Some(entity_id); + self + } + + /** + * 设置事件数据 + */ + pub fn with_data(mut self, data: T) -> Self { + self.data = Some(Box::new(data)); + self + } + + /** + * 添加元数据 + */ + pub fn with_metadata, V: Into>(mut self, key: K, value: V) -> Self { + self.metadata.insert(key.into(), value.into()); + self + } + + /** + * 获取类型化的数据 + */ + pub fn get_data(&self) -> Option<&T> { + self.data.as_ref()?.downcast_ref::() + } + + /** + * 获取元数据 + */ + pub fn get_metadata(&self, key: &str) -> Option<&String> { + self.metadata.get(key) + } +} + +/** + * 事件监听器trait + */ +pub trait EventListener: Send + Sync { + /** + * 处理事件 + */ + fn handle_event(&mut self, event: &Event); + + /** + * 获取监听器感兴趣的事件类型 + */ + fn get_interested_events(&self) -> Vec; + + /** + * 获取监听器优先级 + */ + fn get_priority(&self) -> EventPriority { + EventPriority::Normal + } + + /** + * 检查是否应该处理此事件 + */ + fn should_handle(&self, event: &Event) -> bool { + self.get_interested_events().contains(&event.event_type) + } +} + +/** + * 事件回调函数类型 + */ +pub type EventCallback = Box; + +/** + * 监听器注册信息 + */ +struct ListenerRegistration { + callback: EventCallback, + id: u32, + priority: EventPriority, +} + +/** + * 事件总线 + * 负责事件的分发和监听器管理 + */ +pub struct EventBus { + listeners: HashMap>, + next_listener_id: u32, + event_queue: Vec, + stats: EventBusStats, +} + +/** + * 事件总线统计信息 + */ +#[derive(Debug, Default)] +pub struct EventBusStats { + pub total_events_fired: u64, + pub total_listeners_notified: u64, + pub events_by_type: HashMap, + pub listener_count: u32, + pub queue_size: usize, +} + +impl EventBus { + /** + * 创建新的事件总线 + */ + pub fn new() -> Self { + Self { + listeners: HashMap::new(), + next_listener_id: 1, + event_queue: Vec::new(), + stats: EventBusStats::default(), + } + } + + /** + * 注册事件回调函数 + */ + pub fn register_callback(&mut self, event_type: ECSEventType, callback: F, priority: EventPriority) -> u32 + where + F: Fn(&Event) + Send + Sync + 'static, + { + let id = self.next_listener_id; + self.next_listener_id += 1; + + let registration = ListenerRegistration { + callback: Box::new(callback), + id, + priority, + }; + + let listeners = self.listeners.entry(event_type).or_insert_with(Vec::new); + listeners.push(registration); + + // 按优先级排序 + listeners.sort_by(|a, b| b.priority.cmp(&a.priority)); + + self.stats.listener_count += 1; + id + } + + /** + * 注册多个事件类型的回调 + */ + pub fn register_callback_multi(&mut self, event_types: Vec, callback: F, priority: EventPriority) -> Vec + where + F: Fn(&Event) + Send + Sync + Clone + 'static, + { + let mut ids = Vec::new(); + for event_type in event_types { + let id = self.register_callback(event_type, callback.clone(), priority); + ids.push(id); + } + ids + } + + /** + * 注销事件监听器 + */ + pub fn unregister_callback(&mut self, listener_id: u32) -> bool { + let mut found = false; + + for listeners in self.listeners.values_mut() { + listeners.retain(|reg| { + if reg.id == listener_id { + found = true; + false + } else { + true + } + }); + } + + if found { + self.stats.listener_count -= 1; + } + + found + } + + /** + * 立即触发事件 + */ + pub fn fire_event(&mut self, event: Event) { + self.stats.total_events_fired += 1; + *self.stats.events_by_type.entry(event.event_type).or_insert(0) += 1; + + if let Some(listeners) = self.listeners.get(&event.event_type) { + for registration in listeners { + (registration.callback)(&event); + self.stats.total_listeners_notified += 1; + } + } + } + + /** + * 将事件添加到队列(延迟处理) + */ + pub fn queue_event(&mut self, event: Event) { + self.event_queue.push(event); + self.stats.queue_size = self.event_queue.len(); + } + + /** + * 处理队列中的所有事件 + */ + pub fn process_queued_events(&mut self) { + let events = std::mem::take(&mut self.event_queue); + for event in events { + self.fire_event(event); + } + self.stats.queue_size = 0; + } + + /** + * 清空事件队列 + */ + pub fn clear_queue(&mut self) { + self.event_queue.clear(); + self.stats.queue_size = 0; + } + + /** + * 获取统计信息 + */ + pub fn get_stats(&self) -> &EventBusStats { + &self.stats + } + + /** + * 检查是否有指定类型的监听器 + */ + pub fn has_listeners(&self, event_type: ECSEventType) -> bool { + self.listeners.get(&event_type).map_or(false, |listeners| !listeners.is_empty()) + } + + /** + * 获取指定事件类型的监听器数量 + */ + pub fn get_listener_count(&self, event_type: ECSEventType) -> usize { + self.listeners.get(&event_type).map_or(0, |listeners| listeners.len()) + } +} + +impl Default for EventBus { + fn default() -> Self { + Self::new() + } +} + +/** + * 简单的事件监听器实现 + */ +pub struct SimpleEventListener +where + F: Fn(&Event) + Send + Sync, +{ + handler: F, + interested_events: Vec, + priority: EventPriority, +} + +impl SimpleEventListener +where + F: Fn(&Event) + Send + Sync, +{ + /** + * 创建简单的事件监听器 + */ + pub fn new(handler: F, interested_events: Vec) -> Self { + Self { + handler, + interested_events, + priority: EventPriority::Normal, + } + } + + /** + * 设置优先级 + */ + pub fn with_priority(mut self, priority: EventPriority) -> Self { + self.priority = priority; + self + } +} + +impl EventListener for SimpleEventListener +where + F: Fn(&Event) + Send + Sync, +{ + fn handle_event(&mut self, event: &Event) { + (self.handler)(event); + } + + fn get_interested_events(&self) -> Vec { + self.interested_events.clone() + } + + fn get_priority(&self) -> EventPriority { + self.priority + } +} + +/** + * 获取当前时间戳(毫秒) + */ +fn current_timestamp() -> u64 { + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap_or_default() + .as_millis() as u64 +} + +#[cfg(test)] +mod tests { + use super::*; + use std::sync::{Arc, Mutex}; + + #[test] + fn test_event_creation() { + let event = Event::new(ECSEventType::EntityCreated, EventPriority::Normal) + .with_entity_id(42) + .with_data("test data".to_string()) + .with_metadata("key", "value"); + + assert_eq!(event.event_type, ECSEventType::EntityCreated); + assert_eq!(event.priority, EventPriority::Normal); + assert_eq!(event.entity_id, Some(42)); + assert_eq!(event.get_data::(), Some(&"test data".to_string())); + assert_eq!(event.get_metadata("key"), Some(&"value".to_string())); + } + + #[test] + fn test_event_bus_basic() { + let mut event_bus = EventBus::new(); + let events_received = Arc::new(Mutex::new(Vec::new())); + let events_clone = events_received.clone(); + + // 注册回调 + let listener_id = event_bus.register_callback( + ECSEventType::EntityCreated, + move |event: &Event| { + if let Ok(mut events) = events_clone.lock() { + events.push(event.event_type); + } + }, + EventPriority::Normal, + ); + + // 触发事件 + let event = Event::new(ECSEventType::EntityCreated, EventPriority::Normal) + .with_entity_id(123); + event_bus.fire_event(event); + + // 验证事件被接收 + let events = events_received.lock().unwrap(); + assert_eq!(events.len(), 1); + assert_eq!(events[0], ECSEventType::EntityCreated); + + // 验证统计信息 + let stats = event_bus.get_stats(); + assert_eq!(stats.total_events_fired, 1); + assert_eq!(stats.total_listeners_notified, 1); + + // 注销监听器 + assert!(event_bus.unregister_callback(listener_id)); + assert!(!event_bus.unregister_callback(listener_id)); // 重复注销应该失败 + } + + #[test] + fn test_event_queue() { + let mut event_bus = EventBus::new(); + let events_received = Arc::new(Mutex::new(Vec::new())); + let events_clone1 = events_received.clone(); + let events_clone2 = events_received.clone(); + + event_bus.register_callback( + ECSEventType::EntityCreated, + move |event: &Event| { + if let Ok(mut events) = events_clone1.lock() { + events.push(event.event_type); + } + }, + EventPriority::Normal, + ); + + event_bus.register_callback( + ECSEventType::EntityDestroyed, + move |event: &Event| { + if let Ok(mut events) = events_clone2.lock() { + events.push(event.event_type); + } + }, + EventPriority::Normal, + ); + + // 将事件加入队列 + let event1 = Event::new(ECSEventType::EntityCreated, EventPriority::Normal); + let event2 = Event::new(ECSEventType::EntityDestroyed, EventPriority::Normal); + + event_bus.queue_event(event1); + event_bus.queue_event(event2); + + // 此时事件还没有被处理 + let events = events_received.lock().unwrap(); + assert_eq!(events.len(), 0); + drop(events); + + // 处理队列中的事件 + event_bus.process_queued_events(); + + let events = events_received.lock().unwrap(); + assert_eq!(events.len(), 2); + assert_eq!(events[0], ECSEventType::EntityCreated); + assert_eq!(events[1], ECSEventType::EntityDestroyed); + } + + #[test] + fn test_simple_event_listener() { + let mut event_bus = EventBus::new(); + let received_events = Arc::new(Mutex::new(Vec::new())); + let events_clone = received_events.clone(); + + event_bus.register_callback( + ECSEventType::ComponentAdded, + move |event: &Event| { + if let Ok(mut events) = events_clone.lock() { + events.push(event.event_type); + } + }, + EventPriority::Normal, + ); + + let event = Event::new(ECSEventType::ComponentAdded, EventPriority::Normal); + event_bus.fire_event(event); + + let events = received_events.lock().unwrap(); + assert_eq!(events.len(), 1); + assert_eq!(events[0], ECSEventType::ComponentAdded); + } +} \ No newline at end of file diff --git a/packages/core-rust/src/core/fluent_api.rs b/packages/core-rust/src/core/fluent_api.rs new file mode 100644 index 00000000..808118ff --- /dev/null +++ b/packages/core-rust/src/core/fluent_api.rs @@ -0,0 +1,584 @@ +use crate::core::Entity; +use crate::utils::ComponentType; + +/** + * 实体构建器 + * 提供流式API创建和配置实体 + */ +pub struct EntityBuilder { + entity: Entity, + scene_id: Option, +} + +impl EntityBuilder { + /** + * 创建新的实体构建器 + */ + pub fn new(name: &str, entity_id: u32) -> Self { + let mut entity = Entity::new(entity_id); + entity.set_name(name.to_string()); + Self { + entity, + scene_id: None, + } + } + + /** + * 设置实体名称 + */ + pub fn named(mut self, name: &str) -> Self { + self.entity.name = name.to_string(); + self + } + + /** + * 设置实体标签 + */ + pub fn tagged(mut self, tag: u32) -> Self { + self.entity.set_tag(tag); + self + } + + /** + * 设置实体为启用状态 + */ + pub fn enabled(mut self, enabled: bool) -> Self { + self.entity.set_enabled(enabled); + self + } + + /** + * 设置实体为活跃状态 + */ + pub fn active(mut self, active: bool) -> Self { + self.entity.set_active(active); + self + } + + /** + * 设置更新顺序 + */ + pub fn with_update_order(mut self, order: i32) -> Self { + self.entity.set_update_order(order); + self + } + + /** + * 添加子实体ID + */ + pub fn with_child(mut self, child_id: u32) -> Self { + let _ = self.entity.add_child_id(child_id); + self + } + + /** + * 批量添加子实体ID + */ + pub fn with_children(mut self, child_ids: Vec) -> Self { + for child_id in child_ids { + let _ = self.entity.add_child_id(child_id); + } + self + } + + /** + * 条件性设置属性 + */ + pub fn with_if(self, condition: bool, func: F) -> Self + where + F: FnOnce(Self) -> Self, + { + if condition { + func(self) + } else { + self + } + } + + /** + * 获取构建的实体(消耗builder) + */ + pub fn build(self) -> Entity { + self.entity + } + + /** + * 获取实体的引用 + */ + pub fn get_entity(&self) -> &Entity { + &self.entity + } + + /** + * 获取实体的可变引用 + */ + pub fn get_entity_mut(&mut self) -> &mut Entity { + &mut self.entity + } + + /** + * 克隆构建器 + */ + pub fn clone_builder(&self, new_entity_id: u32) -> Self { + // 由于Entity没有实现Clone,我们创建一个新的Entity + let mut new_entity = Entity::new(new_entity_id); + if let Some(name) = self.entity.name() { + new_entity.set_name(name); + } + new_entity.set_tag(self.entity.tag()); + new_entity.set_active(self.entity.active()); + new_entity.set_enabled(self.entity.enabled()); + new_entity.set_update_order(self.entity.update_order()); + + Self { + entity: new_entity, + scene_id: self.scene_id, + } + } +} + +/** + * 查询构建器 + * 提供流式API构建复杂查询 + */ +pub struct QueryBuilder { + component_types: Vec, + any_component_types: Vec, + none_component_types: Vec, + tag_filter: Option, + name_filter: Option, + active_only: bool, + enabled_only: bool, +} + +impl QueryBuilder { + /** + * 创建新的查询构建器 + */ + pub fn new() -> Self { + Self { + component_types: Vec::new(), + any_component_types: Vec::new(), + none_component_types: Vec::new(), + tag_filter: None, + name_filter: None, + active_only: false, + enabled_only: false, + } + } + + /** + * 添加必须包含的组件类型 + */ + pub fn with_component(mut self, component_type: ComponentType) -> Self { + self.component_types.push(component_type); + self + } + + /** + * 添加多个必须包含的组件类型 + */ + pub fn with_components(mut self, component_types: Vec) -> Self { + self.component_types.extend(component_types); + self + } + + /** + * 添加任意一个包含的组件类型 + */ + pub fn with_any_component(mut self, component_type: ComponentType) -> Self { + self.any_component_types.push(component_type); + self + } + + /** + * 添加多个任意一个包含的组件类型 + */ + pub fn with_any_components(mut self, component_types: Vec) -> Self { + self.any_component_types.extend(component_types); + self + } + + /** + * 添加必须不包含的组件类型 + */ + pub fn without_component(mut self, component_type: ComponentType) -> Self { + self.none_component_types.push(component_type); + self + } + + /** + * 添加多个必须不包含的组件类型 + */ + pub fn without_components(mut self, component_types: Vec) -> Self { + self.none_component_types.extend(component_types); + self + } + + /** + * 按标签过滤 + */ + pub fn with_tag(mut self, tag: u32) -> Self { + self.tag_filter = Some(tag); + self + } + + /** + * 按名称过滤 + */ + pub fn with_name(mut self, name: &str) -> Self { + self.name_filter = Some(name.to_string()); + self + } + + /** + * 只查询活跃实体 + */ + pub fn active_only(mut self) -> Self { + self.active_only = true; + self + } + + /** + * 只查询启用实体 + */ + pub fn enabled_only(mut self) -> Self { + self.enabled_only = true; + self + } + + /** + * 获取所有查询条件 + */ + pub fn get_all_components(&self) -> &Vec { + &self.component_types + } + + /** + * 获取任意查询条件 + */ + pub fn get_any_components(&self) -> &Vec { + &self.any_component_types + } + + /** + * 获取排除查询条件 + */ + pub fn get_none_components(&self) -> &Vec { + &self.none_component_types + } + + /** + * 获取标签过滤器 + */ + pub fn get_tag_filter(&self) -> Option { + self.tag_filter + } + + /** + * 获取名称过滤器 + */ + pub fn get_name_filter(&self) -> Option<&String> { + self.name_filter.as_ref() + } + + /** + * 是否只查询活跃实体 + */ + pub fn is_active_only(&self) -> bool { + self.active_only + } + + /** + * 是否只查询启用实体 + */ + pub fn is_enabled_only(&self) -> bool { + self.enabled_only + } +} + +impl Default for QueryBuilder { + fn default() -> Self { + Self::new() + } +} + +/** + * 流式API统计信息 + */ +#[derive(Debug, Clone)] +pub struct FluentAPIStats { + /// 创建的实体构建器数量 + pub entity_builders_created: u32, + /// 创建的查询构建器数量 + pub query_builders_created: u32, + /// 执行的批量操作数量 + pub batch_operations_executed: u32, + /// 使用的工厂函数数量 + pub factory_functions_used: u32, + /// 条件操作执行次数 + pub conditional_operations: u32, +} + +impl Default for FluentAPIStats { + fn default() -> Self { + Self { + entity_builders_created: 0, + query_builders_created: 0, + batch_operations_executed: 0, + factory_functions_used: 0, + conditional_operations: 0, + } + } +} + +/** + * ECS流式API主入口 + * 提供统一的流式接口 + */ +pub struct ECSFluentAPI { + /// 统计信息 + stats: FluentAPIStats, +} + +impl ECSFluentAPI { + /** + * 创建新的流式API实例 + */ + pub fn new() -> Self { + Self { + stats: FluentAPIStats::default(), + } + } + + /** + * 创建实体构建器 + */ + pub fn create_entity(&mut self, name: &str, entity_id: u32) -> EntityBuilder { + self.stats.entity_builders_created += 1; + EntityBuilder::new(name, entity_id) + } + + /** + * 创建查询构建器 + */ + pub fn query(&mut self) -> QueryBuilder { + self.stats.query_builders_created += 1; + QueryBuilder::new() + } + + /** + * 条件性执行操作 + */ + pub fn when(&mut self, condition: bool, operation: F) -> Option + where + F: FnOnce() -> T, + { + self.stats.conditional_operations += 1; + if condition { + Some(operation()) + } else { + None + } + } + + /** + * 批量创建实体 + */ + pub fn create_entities_batch( + &mut self, + count: u32, + name_prefix: &str, + start_id: u32, + ) -> Vec { + self.stats.batch_operations_executed += 1; + + let mut builders = Vec::with_capacity(count as usize); + for i in 0..count { + let name = format!("{}_{}", name_prefix, i); + let builder = EntityBuilder::new(&name, start_id + i); + builders.push(builder); + } + + self.stats.entity_builders_created += count; + builders + } + + /** + * 使用工厂函数创建实体 + */ + pub fn create_entity_with_factory( + &mut self, + name: &str, + entity_id: u32, + factory: F, + ) -> EntityBuilder + where + F: FnOnce(EntityBuilder) -> EntityBuilder, + { + self.stats.factory_functions_used += 1; + self.stats.entity_builders_created += 1; + + let builder = EntityBuilder::new(name, entity_id); + factory(builder) + } + + /** + * 获取统计信息 + */ + pub fn get_stats(&self) -> FluentAPIStats { + self.stats.clone() + } + + /** + * 重置统计信息 + */ + pub fn reset_stats(&mut self) { + self.stats = FluentAPIStats::default(); + } + + /** + * 清空所有状态 + */ + pub fn clear(&mut self) { + self.reset_stats(); + } +} + +impl Default for ECSFluentAPI { + fn default() -> Self { + Self::new() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::any::TypeId; + + // 测试用的示例组件类型 + struct TestComponentA; + struct TestComponentB; + struct TestComponentC; + + #[test] + fn test_entity_builder_basic() { + let builder = EntityBuilder::new("test_entity", 1); + let entity = builder + .named("my_entity") + .tagged(42) + .enabled(true) + .active(true) + .with_update_order(10) + .build(); + + assert_eq!(entity.name, "my_entity"); + assert_eq!(entity.tag(), 42); + assert_eq!(entity.enabled(), true); + assert_eq!(entity.active(), true); + assert_eq!(entity.update_order(), 10); + } + + #[test] + fn test_entity_builder_children() { + let builder = EntityBuilder::new("parent", 1); + let entity = builder + .with_child(2) + .with_children(vec![3, 4, 5]) + .build(); + + assert_eq!(entity.children_ids().len(), 4); + assert_eq!(entity.children_ids(), &[2, 3, 4, 5]); + } + + #[test] + fn test_entity_builder_conditional() { + let builder = EntityBuilder::new("test", 1); + let entity = builder + .with_if(true, |b| b.tagged(100)) + .with_if(false, |b| b.tagged(200)) + .build(); + + assert_eq!(entity.tag(), 100); + } + + #[test] + fn test_query_builder() { + let query = QueryBuilder::new() + .with_component(TypeId::of::()) + .with_components(vec![ + TypeId::of::(), + TypeId::of::(), + ]) + .with_any_component(TypeId::of::()) + .without_component(TypeId::of::()) + .with_tag(42) + .with_name("test") + .active_only() + .enabled_only(); + + assert_eq!(query.get_all_components().len(), 3); + assert_eq!(query.get_any_components().len(), 1); + assert_eq!(query.get_none_components().len(), 1); + assert_eq!(query.get_tag_filter(), Some(42)); + assert_eq!(query.get_name_filter(), Some(&"test".to_string())); + assert!(query.is_active_only()); + assert!(query.is_enabled_only()); + } + + #[test] + fn test_fluent_api_basic() { + let mut api = ECSFluentAPI::new(); + + let _builder = api.create_entity("test", 1); + let _query = api.query(); + + let stats = api.get_stats(); + assert_eq!(stats.entity_builders_created, 1); + assert_eq!(stats.query_builders_created, 1); + } + + #[test] + fn test_fluent_api_batch() { + let mut api = ECSFluentAPI::new(); + + let builders = api.create_entities_batch(5, "entity", 100); + assert_eq!(builders.len(), 5); + + let stats = api.get_stats(); + assert_eq!(stats.entity_builders_created, 5); + assert_eq!(stats.batch_operations_executed, 1); + } + + #[test] + fn test_fluent_api_factory() { + let mut api = ECSFluentAPI::new(); + + let entity = api + .create_entity_with_factory("test", 1, |builder| { + builder.tagged(42).enabled(true) + }) + .build(); + + assert_eq!(entity.tag(), 42); + assert_eq!(entity.enabled(), true); + + let stats = api.get_stats(); + assert_eq!(stats.factory_functions_used, 1); + assert_eq!(stats.entity_builders_created, 1); + } + + #[test] + fn test_fluent_api_conditional() { + let mut api = ECSFluentAPI::new(); + + let result1 = api.when(true, || "executed"); + let result2 = api.when(false, || "not executed"); + + assert_eq!(result1, Some("executed")); + assert_eq!(result2, None); + + let stats = api.get_stats(); + assert_eq!(stats.conditional_operations, 2); + } +} \ No newline at end of file diff --git a/packages/core-rust/src/core/mod.rs b/packages/core-rust/src/core/mod.rs new file mode 100644 index 00000000..2d885dfe --- /dev/null +++ b/packages/core-rust/src/core/mod.rs @@ -0,0 +1,27 @@ +pub mod entity; +pub mod component; +pub mod entity_manager; +pub mod query_system; +pub mod scene; +pub mod systems; +pub mod events; +pub mod archetype_system; +pub mod fluent_api; +pub mod passive_system; +pub mod component_builder; +pub mod entity_batch_operator; +pub mod scene_builder; + +pub use entity::Entity; +pub use component::{Component, ComponentRegistry, BaseComponent}; +pub use entity_manager::EntityManager; +pub use query_system::{QuerySystem, QueryResult}; +pub use scene::Scene; +pub use systems::{System, EntitySystem, ProcessingSystem, IntervalSystem, SystemManager}; +pub use events::{ECSEventType, EventPriority, Event, EventListener, EventBus, EventBusStats, SimpleEventListener}; +pub use archetype_system::{ArchetypeSystem, Archetype, ArchetypeId, ArchetypeQueryResult, ArchetypeSystemStats}; +pub use fluent_api::{EntityBuilder, QueryBuilder, ECSFluentAPI, FluentAPIStats}; +pub use passive_system::{PassiveSystem, PassiveSystemBuilder}; +pub use component_builder::{ComponentBuilder, BaseComponentBuilder, ComponentBuilderFactory, ComponentBuilderStats}; +pub use entity_batch_operator::{EntityBatchOperator, BatchOperatorStats}; +pub use scene_builder::{SceneBuilder, SceneTemplate, SceneBuilderStats, SceneBuilderFactory, SceneBuilderManager}; \ No newline at end of file diff --git a/packages/core-rust/src/core/passive_system.rs b/packages/core-rust/src/core/passive_system.rs new file mode 100644 index 00000000..91e44e4b --- /dev/null +++ b/packages/core-rust/src/core/passive_system.rs @@ -0,0 +1,351 @@ +use crate::core::Entity; +use crate::core::systems::{System, SystemContext}; +use crate::utils::{Matcher, Time}; + +/** + * 被动实体系统 + * + * 定义一个被动的实体系统,继承自EntitySystem类。 + * 被动的实体系统不会对实体进行任何修改,只会被动地接收实体的变化事件。 + * 主要用于监听、记录或收集数据的场景。 + */ +pub struct PassiveSystem { + pub matcher: Option, + pub priority: i32, + pub enabled: bool, + pub name: String, +} + +impl PassiveSystem { + /** + * 创建新的被动系统 + */ + pub fn new(name: String, matcher: Option) -> Self { + Self { + matcher, + priority: 0, + enabled: true, + name, + } + } + + /** + * 设置系统优先级 + */ + pub fn with_priority(mut self, priority: i32) -> Self { + self.priority = priority; + self + } + + /** + * 设置系统启用状态 + */ + pub fn with_enabled(mut self, enabled: bool) -> Self { + self.enabled = enabled; + self + } + + /** + * 获取系统名称 + */ + pub fn get_name(&self) -> &str { + &self.name + } + + /** + * 获取匹配器 + */ + pub fn get_matcher(&self) -> Option<&Matcher> { + self.matcher.as_ref() + } + + /** + * 检查是否启用 + */ + pub fn is_enabled(&self) -> bool { + self.enabled + } + + /** + * 设置启用状态 + */ + pub fn set_enabled(&mut self, enabled: bool) { + self.enabled = enabled; + } + + /** + * 获取优先级 + */ + pub fn get_priority(&self) -> i32 { + self.priority + } + + /** + * 设置优先级 + */ + pub fn set_priority(&mut self, priority: i32) { + self.priority = priority; + } + + /** + * 系统初始化 + * 子类可以重写此方法进行自定义初始化 + */ + pub fn initialize(&mut self) { + // 默认空实现,子类可以重写 + } + + /** + * 系统更新前调用 + * 子类可以重写此方法进行预处理 + */ + pub fn before_update(&mut self, _time: &Time) { + // 默认空实现,子类可以重写 + } + + /** + * 系统更新后调用 + * 子类可以重写此方法进行后处理 + */ + pub fn after_update(&mut self, _time: &Time) { + // 默认空实现,子类可以重写 + } + + /** + * 系统清理 + * 子类可以重写此方法进行清理工作 + */ + pub fn cleanup(&mut self) { + // 默认空实现,子类可以重写 + } + + /** + * 实体添加通知 + * 当匹配的实体被添加到系统时调用 + */ + pub fn on_entity_added(&mut self, _entity: &Entity) { + // 默认空实现,子类可以重写进行处理 + } + + /** + * 实体移除通知 + * 当匹配的实体从系统中移除时调用 + */ + pub fn on_entity_removed(&mut self, _entity: &Entity) { + // 默认空实现,子类可以重写进行处理 + } + + /** + * 组件添加通知 + * 当实体添加组件时调用 + */ + pub fn on_component_added(&mut self, _entity: &Entity, _component_type: std::any::TypeId) { + // 默认空实现,子类可以重写进行处理 + } + + /** + * 组件移除通知 + * 当实体移除组件时调用 + */ + pub fn on_component_removed(&mut self, _entity: &Entity, _component_type: std::any::TypeId) { + // 默认空实现,子类可以重写进行处理 + } +} + +impl System for PassiveSystem { + fn update(&mut self, _context: &mut SystemContext) { + // 被动系统不进行任何处理 + // 所有的业务逻辑都应该在事件处理方法中实现 + } + + fn set_enabled(&mut self, enabled: bool) { + self.enabled = enabled; + } + + fn set_update_order(&mut self, order: i32) { + self.priority = order; + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self + } +} + +/** + * 被动系统构建器 + * 提供链式调用构建被动系统 + */ +pub struct PassiveSystemBuilder { + name: String, + matcher: Option, + priority: i32, + enabled: bool, +} + +impl PassiveSystemBuilder { + /** + * 创建新的被动系统构建器 + */ + pub fn new(name: String) -> Self { + Self { + name, + matcher: None, + priority: 0, + enabled: true, + } + } + + /** + * 设置匹配器 + */ + pub fn with_matcher(mut self, matcher: Matcher) -> Self { + self.matcher = Some(matcher); + self + } + + /** + * 设置优先级 + */ + pub fn with_priority(mut self, priority: i32) -> Self { + self.priority = priority; + self + } + + /** + * 设置启用状态 + */ + pub fn with_enabled(mut self, enabled: bool) -> Self { + self.enabled = enabled; + self + } + + /** + * 构建被动系统 + */ + pub fn build(self) -> PassiveSystem { + PassiveSystem { + name: self.name, + matcher: self.matcher, + priority: self.priority, + enabled: self.enabled, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::core::{Entity, ComponentRegistry}; + + #[test] + fn test_passive_system_creation() { + let system = PassiveSystem::new("TestPassive".to_string(), None); + + assert_eq!(system.get_name(), "TestPassive"); + assert!(system.enabled()); + assert_eq!(system.get_priority(), 0); + assert!(system.get_matcher().is_none()); + } + + #[test] + fn test_passive_system_builder() { + let system = PassiveSystemBuilder::new("TestPassive".to_string()) + .with_priority(10) + .with_enabled(false) + .build(); + + assert_eq!(system.get_name(), "TestPassive"); + assert!(!system.enabled()); + assert_eq!(system.get_priority(), 10); + } + + #[test] + fn test_passive_system_with_matcher() { + let matcher = Matcher::new(); + let system = PassiveSystemBuilder::new("TestPassive".to_string()) + .with_matcher(matcher) + .build(); + + assert!(system.get_matcher().is_some()); + } + + #[test] + fn test_passive_system_update_does_nothing() { + use crate::core::systems::{System, SystemContext}; + use crate::core::EntityManager; + use crate::storage::ComponentStorageManager; + + let mut system = PassiveSystem::new("TestPassive".to_string(), None); + let mut entity_manager = EntityManager::new(); + let mut component_storage_manager = ComponentStorageManager::new(); + let mut context = SystemContext { + entity_manager: &mut entity_manager, + component_storage_manager: &mut component_storage_manager, + }; + + // update方法不应该做任何事情 + system.update(&mut context); + + // 如果没有panic,说明update方法正确地什么都没做 + } + + #[test] + fn test_passive_system_properties() { + let mut system = PassiveSystem::new("TestPassive".to_string(), None); + + // 测试系统属性 + assert!(system.enabled()); + + system.set_enabled(false); + assert!(!system.enabled()); + + assert_eq!(system.get_name(), "TestPassive"); + assert_eq!(system.get_priority(), 0); + } + + #[test] + fn test_passive_system_lifecycle() { + let mut system = PassiveSystem::new("TestPassive".to_string(), None); + let time = Time::new(); + + // 测试生命周期方法(都应该是安全的空操作) + system.initialize(); + system.before_update(&time); + system.after_update(&time); + system.cleanup(); + + // 如果没有panic,说明所有生命周期方法都正确工作 + } + + #[test] + fn test_passive_system_entity_events() { + let mut system = PassiveSystem::new("TestPassive".to_string(), None); + let mut registry = ComponentRegistry::new(); + let entity = Entity::new("test_entity".to_string(), 1); + + // 测试实体事件方法(都应该是安全的空操作) + system.on_entity_added(&entity); + system.on_entity_removed(&entity); + system.on_component_added(&entity, std::any::TypeId::of::()); + system.on_component_removed(&entity, std::any::TypeId::of::()); + + // 如果没有panic,说明所有事件处理方法都正确工作 + } + + #[test] + fn test_passive_system_priority_modification() { + let mut system = PassiveSystem::new("TestPassive".to_string(), None); + + assert_eq!(system.get_priority(), 0); + + system.set_priority(100); + assert_eq!(system.get_priority(), 100); + + system.set_priority(-50); + assert_eq!(system.get_priority(), -50); + } +} \ No newline at end of file diff --git a/packages/core-rust/src/core/query_system.rs b/packages/core-rust/src/core/query_system.rs new file mode 100644 index 00000000..f0f8debc --- /dev/null +++ b/packages/core-rust/src/core/query_system.rs @@ -0,0 +1,577 @@ +use crate::core::entity_manager::EntityManager; +use crate::utils::{Matcher, QueryCondition, ComponentType}; +use rustc_hash::FxHashMap; + +/** + * 查询结果 + */ +#[derive(serde::Serialize, serde::Deserialize)] +pub struct QueryResult { + pub entities: Vec, + pub count: usize, + pub execution_time: f64, + pub from_cache: bool, +} + +/** + * 查询缓存条目 + */ +struct QueryCacheEntry { + entities: Vec, + timestamp: f64, + hit_count: u32, +} + +/** + * 高性能实体查询系统 + * 提供快速的实体查询功能,支持按组件类型等多种方式查询实体 + */ +pub struct QuerySystem { + entity_index: EntityIndex, + #[allow(dead_code)] + index_dirty: bool, + query_cache: FxHashMap, + cache_max_size: usize, + cache_timeout: f64, + query_stats: QueryStats, +} + +/** + * 实体索引结构 + */ +struct EntityIndex { + by_mask: FxHashMap>, + by_tag: FxHashMap>, + by_name: FxHashMap>, +} + +/** + * 性能统计 + */ +struct QueryStats { + total_queries: u32, + cache_hits: u32, + index_hits: u32, + linear_scans: u32, +} + +impl QuerySystem { + pub fn new() -> Self { + Self { + entity_index: EntityIndex { + by_mask: FxHashMap::default(), + by_tag: FxHashMap::default(), + by_name: FxHashMap::default(), + }, + index_dirty: true, + query_cache: FxHashMap::default(), + cache_max_size: 1000, + cache_timeout: 5000.0, // 5秒 + query_stats: QueryStats { + total_queries: 0, + cache_hits: 0, + index_hits: 0, + linear_scans: 0, + }, + } + } + + /** + * 添加实体到查询系统 + * @param entity_id 实体ID + * @param entity_manager 实体管理器引用 + */ + pub fn add_entity(&mut self, entity_id: u32, entity_manager: &EntityManager) { + if let Some(_entity) = entity_manager.get_entity(entity_id) { + self.add_entity_to_indexes(entity_id, entity_manager); + self.clear_query_cache(); + } + } + + /** + * 从查询系统移除实体 + * @param entity_id 实体ID + * @param entity_manager 实体管理器引用 + */ + pub fn remove_entity(&mut self, entity_id: u32, entity_manager: &EntityManager) { + self.remove_entity_from_indexes(entity_id, entity_manager); + self.clear_query_cache(); + } + + /** + * 查询包含所有指定组件的实体 + * @param component_mask 组件位掩码 + * @param entity_manager 实体管理器引用 + * @returns 查询结果,包含匹配的实体和性能信息 + */ + pub fn query_all(&mut self, component_mask: u64, entity_manager: &EntityManager) -> QueryResult { + let start_time = self.get_current_time(); + self.query_stats.total_queries += 1; + + let cache_key = format!("all:{}", component_mask); + + // 检查缓存 + if let Some(cached_entities) = self.get_from_cache(&cache_key) { + self.query_stats.cache_hits += 1; + let entity_count = cached_entities.len(); + return QueryResult { + entities: cached_entities, + count: entity_count, + execution_time: self.get_current_time() - start_time, + from_cache: true, + }; + } + + // 执行查询 + let entities = self.execute_mask_query(component_mask, entity_manager); + + // 缓存结果 + self.add_to_cache(cache_key, &entities); + + let entity_count = entities.len(); + QueryResult { + entities, + count: entity_count, + execution_time: self.get_current_time() - start_time, + from_cache: false, + } + } + + /** + * 按标签查询实体 + * @param tag 要查询的标签值 + * @param entity_manager 实体管理器引用 + * @returns 查询结果 + */ + pub fn query_by_tag(&mut self, tag: u32, entity_manager: &EntityManager) -> QueryResult { + let start_time = self.get_current_time(); + self.query_stats.total_queries += 1; + + let cache_key = format!("tag:{}", tag); + + if let Some(cached_entities) = self.get_from_cache(&cache_key) { + self.query_stats.cache_hits += 1; + let entity_count = cached_entities.len(); + return QueryResult { + entities: cached_entities, + count: entity_count, + execution_time: self.get_current_time() - start_time, + from_cache: true, + }; + } + + let entities = entity_manager.get_entities_by_tag(tag); + self.add_to_cache(cache_key, &entities); + + let entity_count = entities.len(); + QueryResult { + entities, + count: entity_count, + execution_time: self.get_current_time() - start_time, + from_cache: false, + } + } + + /** + * 按名称查询实体 + * @param name 要查询的实体名称 + * @param entity_manager 实体管理器引用 + * @returns 查询结果 + */ + pub fn query_by_name(&mut self, name: &str, entity_manager: &EntityManager) -> QueryResult { + let start_time = self.get_current_time(); + self.query_stats.total_queries += 1; + + let cache_key = format!("name:{}", name); + + if let Some(cached_entities) = self.get_from_cache(&cache_key) { + self.query_stats.cache_hits += 1; + let entity_count = cached_entities.len(); + return QueryResult { + entities: cached_entities, + count: entity_count, + execution_time: self.get_current_time() - start_time, + from_cache: true, + }; + } + + let entities = if let Some(entity_id) = entity_manager.get_entity_by_name(name) { + vec![entity_id] + } else { + Vec::new() + }; + + self.add_to_cache(cache_key, &entities); + + let entity_count = entities.len(); + QueryResult { + entities, + count: entity_count, + execution_time: self.get_current_time() - start_time, + from_cache: false, + } + } + + /** + * 执行掩码查询 + */ + fn execute_mask_query(&mut self, component_mask: u64, entity_manager: &EntityManager) -> Vec { + let mut result = Vec::new(); + + for &entity_id in entity_manager.get_all_entity_ids().iter() { + let entity_mask = entity_manager.get_component_mask(entity_id); + if (entity_mask & component_mask) == component_mask { + result.push(entity_id); + } + } + + self.query_stats.linear_scans += 1; + result + } + + /** + * 将实体添加到各种索引中 + */ + fn add_entity_to_indexes(&mut self, entity_id: u32, entity_manager: &EntityManager) { + if let Some(entity) = entity_manager.get_entity(entity_id) { + let mask = entity_manager.get_component_mask(entity_id); + let mask_key = mask.to_string(); + + self.entity_index + .by_mask + .entry(mask_key) + .or_insert_with(std::collections::HashSet::new) + .insert(entity_id); + + self.entity_index + .by_tag + .entry(entity.tag()) + .or_insert_with(std::collections::HashSet::new) + .insert(entity_id); + + self.entity_index + .by_name + .entry(entity.name.clone()) + .or_insert_with(std::collections::HashSet::new) + .insert(entity_id); + } + } + + /** + * 从各种索引中移除实体 + */ + fn remove_entity_from_indexes(&mut self, entity_id: u32, entity_manager: &EntityManager) { + if let Some(entity) = entity_manager.get_entity(entity_id) { + let mask = entity_manager.get_component_mask(entity_id); + let mask_key = mask.to_string(); + + if let Some(mask_set) = self.entity_index.by_mask.get_mut(&mask_key) { + mask_set.remove(&entity_id); + if mask_set.is_empty() { + self.entity_index.by_mask.remove(&mask_key); + } + } + + if let Some(tag_set) = self.entity_index.by_tag.get_mut(&entity.tag()) { + tag_set.remove(&entity_id); + if tag_set.is_empty() { + self.entity_index.by_tag.remove(&entity.tag()); + } + } + + if let Some(name_set) = self.entity_index.by_name.get_mut(&entity.name) { + name_set.remove(&entity_id); + if name_set.is_empty() { + self.entity_index.by_name.remove(&entity.name); + } + } + } + } + + /** + * 从缓存获取查询结果 + */ + fn get_from_cache(&mut self, cache_key: &str) -> Option> { + let current_time = self.get_current_time(); + + if let Some(entry) = self.query_cache.get_mut(cache_key) { + if current_time - entry.timestamp <= self.cache_timeout { + entry.hit_count += 1; + return Some(entry.entities.clone()); + } else { + self.query_cache.remove(cache_key); + } + } + None + } + + /** + * 添加查询结果到缓存 + */ + fn add_to_cache(&mut self, cache_key: String, entities: &[u32]) { + if self.query_cache.len() >= self.cache_max_size { + self.cleanup_cache(); + } + + self.query_cache.insert(cache_key, QueryCacheEntry { + entities: entities.to_vec(), + timestamp: self.get_current_time(), + hit_count: 0, + }); + } + + /** + * 清理缓存 + */ + fn cleanup_cache(&mut self) { + let current_time = self.get_current_time(); + + // 移除过期的缓存条目 + self.query_cache.retain(|_, entry| { + current_time - entry.timestamp <= self.cache_timeout + }); + + // 如果还是太满,移除最少使用的条目 + if self.query_cache.len() >= self.cache_max_size { + let entries: Vec<_> = self.query_cache.iter().map(|(k, v)| (k.clone(), v.hit_count)).collect(); + let mut sorted_entries = entries; + sorted_entries.sort_by_key(|(_, hit_count)| *hit_count); + + let to_remove = (self.cache_max_size as f32 * 0.2) as usize; + for (key, _) in sorted_entries.into_iter().take(to_remove) { + self.query_cache.remove(&key); + } + } + } + + /** + * 清除所有查询缓存 + */ + fn clear_query_cache(&mut self) { + self.query_cache.clear(); + } + + /** + * 获取当前时间戳(毫秒) + */ + fn get_current_time(&self) -> f64 { + // 在WASM环境中,这将使用js-sys获取时间 + // 这里使用简化实现,转换为f64毫秒 + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap_or_default() + .as_millis() as f64 + } + + /** + * 获取系统统计信息 + */ + /** + * 清空查询缓存 + */ + pub fn clear_cache(&mut self) { + self.query_cache.clear(); + } + + /** + * 基于Matcher的高级查询 + * + * 使用Matcher描述复杂查询条件,支持all/any/none组合查询 + */ + pub fn query_with_matcher(&mut self, matcher: &Matcher, entity_manager: &EntityManager) -> QueryResult { + let start_time = self.get_current_time(); + + // 生成查询缓存键 + let cache_key = self.generate_matcher_cache_key(matcher); + + // 检查缓存 + if let Some(cached_result) = self.get_from_cache(&cache_key) { + let count = cached_result.len(); + return QueryResult { + entities: cached_result, + count, + execution_time: self.get_current_time() - start_time, + from_cache: true, + }; + } + + // 执行查询 + let entities = self.execute_matcher_query(matcher, entity_manager); + + // 添加到缓存 + self.add_to_cache(cache_key, &entities); + + let entity_count = entities.len(); + QueryResult { + entities, + count: entity_count, + execution_time: self.get_current_time() - start_time, + from_cache: false, + } + } + + /** + * 执行Matcher查询的核心逻辑 + */ + fn execute_matcher_query(&mut self, matcher: &Matcher, entity_manager: &EntityManager) -> Vec { + let condition = matcher.get_condition(); + let all_entity_ids = entity_manager.get_all_entity_ids(); + let mut matching_entities = Vec::new(); + + // 遍历所有实体进行匹配 + for &entity_id in &all_entity_ids { + if self.entity_matches_condition(entity_id, condition, entity_manager) { + matching_entities.push(entity_id); + } + } + + self.query_stats.linear_scans += 1; + matching_entities + } + + /** + * 检查实体是否匹配查询条件 + */ + fn entity_matches_condition(&self, entity_id: u32, condition: &QueryCondition, entity_manager: &EntityManager) -> bool { + let entity = match entity_manager.get_entity(entity_id) { + Some(entity) => entity, + None => return false, + }; + + // 检查名称条件 + if let Some(ref name) = condition.name { + if &entity.name != name { + return false; + } + } + + // 检查标签条件 + if let Some(tag) = condition.tag { + if entity.tag() != tag { + return false; + } + } + + // 检查单组件条件 + if let Some(component_type) = condition.component { + if !self.entity_has_component_type(entity_id, component_type, entity_manager) { + return false; + } + } + + // 检查all条件(必须包含所有指定组件) + if !condition.all.is_empty() { + for &component_type in &condition.all { + if !self.entity_has_component_type(entity_id, component_type, entity_manager) { + return false; + } + } + } + + // 检查any条件(必须包含至少一个指定组件) + if !condition.any.is_empty() { + let has_any = condition.any.iter() + .any(|&component_type| self.entity_has_component_type(entity_id, component_type, entity_manager)); + if !has_any { + return false; + } + } + + // 检查none条件(不能包含任何指定组件) + if !condition.none.is_empty() { + for &component_type in &condition.none { + if self.entity_has_component_type(entity_id, component_type, entity_manager) { + return false; + } + } + } + + true + } + + /** + * 检查实体是否有指定类型的组件 + * 这里需要EntityManager提供按TypeId查询组件的功能 + */ + fn entity_has_component_type(&self, entity_id: u32, component_type: ComponentType, _entity_manager: &EntityManager) -> bool { + // TODO: 这里需要EntityManager支持按TypeId查询组件 + // 目前先返回false作为占位实现 + // 实际实现需要EntityManager提供get_component_by_type_id方法 + let _ = (entity_id, component_type); + false + } + + /** + * 为Matcher生成缓存键 + */ + fn generate_matcher_cache_key(&self, matcher: &Matcher) -> String { + let condition = matcher.get_condition(); + let mut key_parts = Vec::new(); + + // 添加各种条件到键中 + if !condition.all.is_empty() { + let type_ids: Vec = condition.all.iter() + .map(|t| format!("{:?}", t)) + .collect(); + key_parts.push(format!("all:{}", type_ids.join(","))); + } + + if !condition.any.is_empty() { + let type_ids: Vec = condition.any.iter() + .map(|t| format!("{:?}", t)) + .collect(); + key_parts.push(format!("any:{}", type_ids.join(","))); + } + + if !condition.none.is_empty() { + let type_ids: Vec = condition.none.iter() + .map(|t| format!("{:?}", t)) + .collect(); + key_parts.push(format!("none:{}", type_ids.join(","))); + } + + if let Some(tag) = condition.tag { + key_parts.push(format!("tag:{}", tag)); + } + + if let Some(ref name) = condition.name { + key_parts.push(format!("name:{}", name)); + } + + if let Some(component) = condition.component { + key_parts.push(format!("comp:{:?}", component)); + } + + format!("matcher:{}", key_parts.join("|")) + } + + pub fn get_stats(&self) -> QuerySystemStats { + let cache_hit_rate = if self.query_stats.total_queries > 0 { + (self.query_stats.cache_hits as f32 / self.query_stats.total_queries as f32) * 100.0 + } else { + 0.0 + }; + + QuerySystemStats { + total_queries: self.query_stats.total_queries, + cache_hits: self.query_stats.cache_hits, + index_hits: self.query_stats.index_hits, + linear_scans: self.query_stats.linear_scans, + cache_hit_rate, + cache_size: self.query_cache.len(), + } + } +} + +/** + * 查询系统统计信息 + */ +#[derive(serde::Serialize, serde::Deserialize)] +pub struct QuerySystemStats { + pub total_queries: u32, + pub cache_hits: u32, + pub index_hits: u32, + pub linear_scans: u32, + pub cache_hit_rate: f32, + pub cache_size: usize, +} \ No newline at end of file diff --git a/packages/core-rust/src/core/scene.rs b/packages/core-rust/src/core/scene.rs new file mode 100644 index 00000000..ef754978 --- /dev/null +++ b/packages/core-rust/src/core/scene.rs @@ -0,0 +1,403 @@ +use crate::core::entity_manager::EntityManager; +use crate::core::query_system::QuerySystem; +use crate::core::systems::{System, SystemManager, SystemContext}; +use crate::storage::component_storage::ComponentStorageManager; +use crate::utils::time::Time; + +/** + * 场景管理器 + * + * Scene是ECS系统中的顶层容器,管理所有实体、组件和系统 + * 提供统一的实体管理、组件存储和查询功能 + */ +pub struct Scene { + /// 场景名称 + name: String, + + /// 是否激活状态 + active: bool, + + /// 实体管理器 + entity_manager: EntityManager, + + /// 组件存储管理器 + component_storage_manager: ComponentStorageManager, + + /// 查询系统 + query_system: QuerySystem, + + /// 系统管理器 + system_manager: SystemManager, + + /// 场景统计信息 + stats: SceneStats, +} + +impl Scene { + /** + * 创建新场景 + */ + pub fn new() -> Self { + Self { + name: String::new(), + active: true, + entity_manager: EntityManager::new(), + component_storage_manager: ComponentStorageManager::new(), + query_system: QuerySystem::new(), + system_manager: SystemManager::new(), + stats: SceneStats::default(), + } + } + + /** + * 创建带名称的新场景 + */ + pub fn new_with_name(name: String) -> Self { + Self { + name, + active: true, + entity_manager: EntityManager::new(), + component_storage_manager: ComponentStorageManager::new(), + query_system: QuerySystem::new(), + system_manager: SystemManager::new(), + stats: SceneStats::default(), + } + } + + // ========== 场景属性 ========== + + /** + * 获取场景名称 + */ + pub fn name(&self) -> &str { + &self.name + } + + /** + * 设置场景名称 + */ + pub fn set_name(&mut self, name: String) { + self.name = name; + } + + /** + * 获取激活状态 + */ + pub fn active(&self) -> bool { + self.active + } + + /** + * 设置激活状态 + */ + pub fn set_active(&mut self, active: bool) { + self.active = active; + } + + // ========== 实体管理 ========== + + /** + * 创建实体 + */ + pub fn create_entity(&mut self, name: Option) -> u32 { + let entity_id = self.entity_manager.create_entity(name); + self.stats.total_entities_created += 1; + entity_id + } + + /** + * 批量创建实体 + */ + pub fn create_entities_batch(&mut self, count: u32, name_prefix: Option) -> Vec { + let entities = self.entity_manager.create_entities_batch(count, name_prefix); + self.stats.total_entities_created += count as u64; + entities + } + + /** + * 销毁实体 + */ + pub fn destroy_entity(&mut self, entity_id: u32) -> bool { + if self.entity_manager.destroy_entity(entity_id) { + // 清理组件存储 + self.component_storage_manager.remove_all_components(entity_id); + self.stats.total_entities_destroyed += 1; + true + } else { + false + } + } + + /** + * 获取实体管理器引用 + */ + pub fn entity_manager(&self) -> &EntityManager { + &self.entity_manager + } + + /** + * 获取实体管理器可变引用 + */ + pub fn entity_manager_mut(&mut self) -> &mut EntityManager { + &mut self.entity_manager + } + + // ========== 组件管理 ========== + + /** + * 获取组件存储管理器引用 + */ + pub fn component_storage_manager(&self) -> &ComponentStorageManager { + &self.component_storage_manager + } + + /** + * 获取组件存储管理器可变引用 + */ + pub fn component_storage_manager_mut(&mut self) -> &mut ComponentStorageManager { + &mut self.component_storage_manager + } + + // ========== 查询系统 ========== + + /** + * 获取查询系统引用 + */ + pub fn query_system(&self) -> &QuerySystem { + &self.query_system + } + + /** + * 获取查询系统可变引用 + */ + pub fn query_system_mut(&mut self) -> &mut QuerySystem { + &mut self.query_system + } + + // ========== 系统管理 ========== + + /** + * 添加系统 + */ + pub fn add_system(&mut self, system: T) { + self.system_manager.add_system(system); + } + + /** + * 移除系统 + */ + pub fn remove_system(&mut self) -> bool { + self.system_manager.remove_system::() + } + + /** + * 获取系统 + */ + pub fn get_system(&self) -> Option<&T> { + self.system_manager.get_system::() + } + + /** + * 获取可变系统 + */ + pub fn get_system_mut(&mut self) -> Option<&mut T> { + self.system_manager.get_system_mut::() + } + + /** + * 获取系统管理器引用 + */ + pub fn system_manager(&self) -> &SystemManager { + &self.system_manager + } + + /** + * 获取系统管理器可变引用 + */ + pub fn system_manager_mut(&mut self) -> &mut SystemManager { + &mut self.system_manager + } + + // ========== 场景生命周期 ========== + + /** + * 初始化场景 + */ + pub fn initialize(&mut self) { + // 创建系统上下文并初始化系统管理器 + let mut context = SystemContext { + entity_manager: &mut self.entity_manager, + component_storage_manager: &mut self.component_storage_manager, + }; + self.system_manager.initialize(&mut context); + } + + /** + * 更新场景 + */ + pub fn update(&mut self, delta_time: f64) { + if !self.active { + return; + } + + // 更新时间 + Time::update(delta_time); + + // 创建系统上下文 + let mut context = SystemContext { + entity_manager: &mut self.entity_manager, + component_storage_manager: &mut self.component_storage_manager, + }; + + // 更新所有系统 + self.system_manager.update(&mut context); + + // 重新创建系统上下文(避免借用检查问题) + let mut context = SystemContext { + entity_manager: &mut self.entity_manager, + component_storage_manager: &mut self.component_storage_manager, + }; + + // 后更新系统 + self.system_manager.late_update(&mut context); + + // 更新所有激活的实体(在系统更新完成后) + let active_entities = self.entity_manager.get_all_entity_ids(); + for entity_id in active_entities { + if let Some(entity) = self.entity_manager.get_entity_mut(entity_id) { + entity.update(); + } + } + + self.stats.total_updates += 1; + } + + /** + * 清空场景 + */ + pub fn clear(&mut self) { + // 创建系统上下文并清理系统 + let mut context = SystemContext { + entity_manager: &mut self.entity_manager, + component_storage_manager: &mut self.component_storage_manager, + }; + self.system_manager.cleanup(&mut context); + + self.entity_manager = EntityManager::new(); + self.component_storage_manager.clear(); + self.query_system.clear_cache(); + self.system_manager = SystemManager::new(); + self.stats = SceneStats::default(); + } + + // ========== 统计信息 ========== + + /** + * 获取场景统计信息 + */ + pub fn get_stats(&self) -> &SceneStats { + &self.stats + } + + /** + * 获取实体数量 + */ + pub fn entity_count(&self) -> usize { + self.entity_manager.entity_count() + } + + /** + * 获取激活实体数量 + */ + pub fn active_entity_count(&self) -> usize { + self.entity_manager.active_entity_count() + } + + /** + * 获取调试信息 + */ + pub fn get_debug_info(&self) -> String { + format!( + "{{\"name\":\"{}\",\"active\":{},\"entity_count\":{},\"active_entity_count\":{},\"total_entities_created\":{},\"total_entities_destroyed\":{},\"total_updates\":{}}}", + self.name, + self.active, + self.entity_count(), + self.active_entity_count(), + self.stats.total_entities_created, + self.stats.total_entities_destroyed, + self.stats.total_updates + ) + } + + // ========== SceneBuilder支持方法 ========== + + /** + * 添加实体到场景 + */ + pub fn add_entity(&mut self, entity: crate::core::Entity) { + self.entity_manager.add_entity(entity); + self.stats.total_entities_created += 1; + } + + /** + * 添加系统到场景(Box版本) + */ + pub fn add_system_boxed(&mut self, system: Box) { + self.system_manager.add_system_boxed(system); + } + + /** + * 获取系统数量 + */ + pub fn system_count(&self) -> usize { + self.system_manager.system_count() + } + + /** + * 设置启用状态 + */ + pub fn set_enabled(&mut self, enabled: bool) { + self.active = enabled; + } + + /** + * 检查是否启用 + */ + pub fn is_enabled(&self) -> bool { + self.active + } + + /** + * 预留容量 + */ + pub fn reserve_capacity(&mut self, entity_capacity: usize, system_capacity: usize) { + self.entity_manager.reserve_capacity(entity_capacity); + self.system_manager.reserve_capacity(system_capacity); + } +} + +/** + * 场景统计信息 + */ +#[derive(Default)] +pub struct SceneStats { + /// 创建的实体总数 + pub total_entities_created: u64, + + /// 销毁的实体总数 + pub total_entities_destroyed: u64, + + /// 更新总次数 + pub total_updates: u64, +} + +impl std::fmt::Debug for Scene { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Scene") + .field("name", &self.name) + .field("active", &self.active) + .field("entity_count", &self.entity_count()) + .field("active_entity_count", &self.active_entity_count()) + .finish() + } +} \ No newline at end of file diff --git a/packages/core-rust/src/core/scene_builder.rs b/packages/core-rust/src/core/scene_builder.rs new file mode 100644 index 00000000..dea7949c --- /dev/null +++ b/packages/core-rust/src/core/scene_builder.rs @@ -0,0 +1,598 @@ +use crate::core::{Scene, Entity, System}; +use crate::core::fluent_api::EntityBuilder; + +/** + * 场景构建器 + * 提供流式API创建和配置场景 + */ +pub struct SceneBuilder { + scene: Scene, +} + +impl SceneBuilder { + /** + * 创建场景构建器 + */ + pub fn new() -> Self { + Self { + scene: Scene::new(), + } + } + + /** + * 设置场景名称 + */ + pub fn named(mut self, name: &str) -> Self { + self.scene.set_name(name.to_string()); + self + } + + /** + * 设置场景是否启用 + */ + pub fn enabled(mut self, enabled: bool) -> Self { + self.scene.set_enabled(enabled); + self + } + + /** + * 添加实体 + */ + pub fn with_entity(mut self, entity: Entity) -> Self { + self.scene.add_entity(entity); + self + } + + /** + * 批量添加实体 + */ + pub fn with_entities(mut self, entities: Vec) -> Self { + for entity in entities { + self.scene.add_entity(entity); + } + self + } + + /** + * 使用实体构建器添加实体 + */ + pub fn with_entity_builder(mut self, builder_fn: F) -> Self + where + F: FnOnce(EntityBuilder) -> EntityBuilder, + { + let builder = EntityBuilder::new("", 0); + let configured_builder = builder_fn(builder); + let entity = configured_builder.build(); + self.scene.add_entity(entity); + self + } + + /** + * 批量使用实体构建器添加实体 + */ + pub fn with_entity_builders(mut self, count: usize, builder_fn: F) -> Self + where + F: Fn(usize, EntityBuilder) -> EntityBuilder, + { + for i in 0..count { + let builder = EntityBuilder::new("", 0); + let configured_builder = builder_fn(i, builder); + let entity = configured_builder.build(); + self.scene.add_entity(entity); + } + self + } + + /** + * 添加系统 + */ + pub fn with_system(mut self, system: Box) -> Self { + self.scene.add_system_boxed(system); + self + } + + /** + * 批量添加系统 + */ + pub fn with_systems(mut self, systems: Vec>) -> Self { + for system in systems { + self.scene.add_system_boxed(system); + } + self + } + + /** + * 条件性添加实体 + */ + pub fn with_entity_if(mut self, condition: bool, entity: Entity) -> Self { + if condition { + self.scene.add_entity(entity); + } + self + } + + /** + * 条件性添加系统 + */ + pub fn with_system_if(mut self, condition: bool, system: Box) -> Self { + if condition { + self.scene.add_system_boxed(system); + } + self + } + + /** + * 使用配置函数配置场景 + */ + pub fn configure(mut self, configurator: F) -> Self + where + F: FnOnce(&mut Scene), + { + configurator(&mut self.scene); + self + } + + /** + * 条件性配置场景 + */ + pub fn configure_if(mut self, condition: bool, configurator: F) -> Self + where + F: FnOnce(&mut Scene), + { + if condition { + configurator(&mut self.scene); + } + self + } + + /** + * 批量创建简单实体 + */ + pub fn with_simple_entities(mut self, count: usize, name_prefix: &str) -> Self { + for i in 0..count { + let mut entity = Entity::new(0); // ID将由EntityManager分配 + entity.set_name(format!("{}{}", name_prefix, i)); + self.scene.add_entity(entity); + } + self + } + + /** + * 使用预定义场景模板 + */ + pub fn from_template(self, template: SceneTemplate) -> Self { + match template { + SceneTemplate::Empty => self, + SceneTemplate::Basic => { + self.named("Basic Scene") + .enabled(true) + .with_simple_entities(10, "Entity_") + }, + SceneTemplate::Testing => { + self.named("Test Scene") + .enabled(true) + .with_simple_entities(5, "TestEntity_") + }, + } + } + + /** + * 设置场景容量预估 + */ + pub fn with_capacity(mut self, entity_capacity: usize, system_capacity: usize) -> Self { + self.scene.reserve_capacity(entity_capacity, system_capacity); + self + } + + /** + * 验证场景配置 + */ + pub fn validate(self) -> Result { + // 基本验证 + if self.scene.name().is_empty() { + return Err("Scene name cannot be empty".to_string()); + } + + if self.scene.entity_count() == 0 { + return Err("Scene must have at least one entity".to_string()); + } + + Ok(self) + } + + /** + * 构建并返回场景 + */ + pub fn build(self) -> Scene { + self.scene + } + + /** + * 验证并构建场景 + */ + pub fn validate_and_build(self) -> Result { + self.validate().map(|builder| builder.build()) + } + + /** + * 获取当前场景的统计信息 + */ + pub fn get_stats(&self) -> SceneBuilderStats { + SceneBuilderStats { + entity_count: self.scene.entity_count(), + system_count: self.scene.system_count(), + is_enabled: self.scene.is_enabled(), + name_length: self.scene.name().len(), + } + } +} + +/** + * 场景模板枚举 + * 提供预定义的场景配置 + */ +#[derive(Debug, Clone)] +pub enum SceneTemplate { + Empty, + Basic, + Testing, +} + +/** + * 场景构建器统计信息 + */ +#[derive(Debug, Clone)] +pub struct SceneBuilderStats { + pub entity_count: usize, + pub system_count: usize, + pub is_enabled: bool, + pub name_length: usize, +} + +impl SceneBuilderStats { + /** + * 检查场景是否为空 + */ + pub fn is_empty(&self) -> bool { + self.entity_count == 0 && self.system_count == 0 + } + + /** + * 检查场景是否已配置 + */ + pub fn is_configured(&self) -> bool { + self.entity_count > 0 || self.system_count > 0 + } + + /** + * 获取场景复杂度评分 + */ + pub fn complexity_score(&self) -> f64 { + (self.entity_count as f64 * 1.0) + (self.system_count as f64 * 2.0) + } +} + +/** + * 场景构建器工厂 + * 提供创建各种场景构建器的便捷方法 + */ +pub struct SceneBuilderFactory; + +impl SceneBuilderFactory { + /** + * 创建空场景构建器 + */ + pub fn empty() -> SceneBuilder { + SceneBuilder::new() + } + + /** + * 创建基础场景构建器 + */ + pub fn basic(name: &str) -> SceneBuilder { + SceneBuilder::new() + .named(name) + .enabled(true) + } + + /** + * 创建测试场景构建器 + */ + pub fn for_testing() -> SceneBuilder { + SceneBuilder::new() + .from_template(SceneTemplate::Testing) + } + + /** + * 创建指定容量的场景构建器 + */ + pub fn with_capacity(entity_capacity: usize, system_capacity: usize) -> SceneBuilder { + SceneBuilder::new() + .with_capacity(entity_capacity, system_capacity) + } + + /** + * 从模板创建场景构建器 + */ + pub fn from_template(template: SceneTemplate) -> SceneBuilder { + SceneBuilder::new().from_template(template) + } +} + +/** + * 场景构建器管理器 + * 管理多个场景构建器的全局统计 + */ +#[derive(Debug)] +pub struct SceneBuilderManager { + total_scenes_built: u64, + total_entities_created: u64, + total_systems_added: u64, + validation_failures: u64, +} + +impl SceneBuilderManager { + pub fn new() -> Self { + Self { + total_scenes_built: 0, + total_entities_created: 0, + total_systems_added: 0, + validation_failures: 0, + } + } + + /** + * 记录场景构建 + */ + pub fn record_scene_built(&mut self, stats: &SceneBuilderStats) { + self.total_scenes_built += 1; + self.total_entities_created += stats.entity_count as u64; + self.total_systems_added += stats.system_count as u64; + } + + /** + * 记录验证失败 + */ + pub fn record_validation_failure(&mut self) { + self.validation_failures += 1; + } + + /** + * 重置统计信息 + */ + pub fn reset(&mut self) { + self.total_scenes_built = 0; + self.total_entities_created = 0; + self.total_systems_added = 0; + self.validation_failures = 0; + } + + /** + * 获取平均每个场景的实体数 + */ + pub fn average_entities_per_scene(&self) -> f64 { + if self.total_scenes_built == 0 { + 0.0 + } else { + self.total_entities_created as f64 / self.total_scenes_built as f64 + } + } + + /** + * 获取平均每个场景的系统数 + */ + pub fn average_systems_per_scene(&self) -> f64 { + if self.total_scenes_built == 0 { + 0.0 + } else { + self.total_systems_added as f64 / self.total_scenes_built as f64 + } + } + + /** + * 获取构建成功率 + */ + pub fn success_rate(&self) -> f64 { + let total_attempts = self.total_scenes_built + self.validation_failures; + if total_attempts == 0 { + 1.0 + } else { + self.total_scenes_built as f64 / total_attempts as f64 + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::any::Any; + use crate::core::systems::SystemContext; + + // 测试用的简单系统 + struct TestSystem { + enabled: bool, + update_order: i32, + } + + impl TestSystem { + fn new() -> Self { + Self { + enabled: true, + update_order: 0, + } + } + } + + impl System for TestSystem { + fn initialize(&mut self, _context: &mut SystemContext) {} + fn update(&mut self, _context: &mut SystemContext) {} + fn late_update(&mut self, _context: &mut SystemContext) {} + fn cleanup(&mut self, _context: &mut SystemContext) {} + fn enabled(&self) -> bool { self.enabled } + fn set_enabled(&mut self, enabled: bool) { self.enabled = enabled; } + fn name(&self) -> &str { "TestSystem" } + fn update_order(&self) -> i32 { self.update_order } + fn set_update_order(&mut self, order: i32) { self.update_order = order; } + fn as_any(&self) -> &dyn Any { self } + fn as_any_mut(&mut self) -> &mut dyn Any { self } + } + + #[test] + fn test_scene_builder_basic() { + let scene = SceneBuilder::new() + .named("Test Scene") + .enabled(true) + .build(); + + assert_eq!(scene.name(), "Test Scene"); + assert!(scene.enabled()); + } + + #[test] + fn test_scene_builder_with_entities() { + let entity1 = Entity::new(1); + let entity2 = Entity::new(2); + + let scene = SceneBuilder::new() + .with_entity(entity1) + .with_entity(entity2) + .build(); + + assert_eq!(scene.entity_count(), 2); + } + + #[test] + fn test_scene_builder_with_simple_entities() { + let scene = SceneBuilder::new() + .with_simple_entities(5, "Entity_") + .build(); + + assert_eq!(scene.entity_count(), 5); + } + + #[test] + fn test_scene_builder_with_systems() { + let system = Box::new(TestSystem::new()); + + let scene = SceneBuilder::new() + .with_system(system) + .build(); + + assert_eq!(scene.system_count(), 1); + } + + #[test] + fn test_scene_builder_conditional() { + let entity = Entity::new(1); + let system = Box::new(TestSystem::new()); + + let scene = SceneBuilder::new() + .with_entity_if(true, entity) + .with_system_if(false, system) + .build(); + + assert_eq!(scene.entity_count(), 1); + assert_eq!(scene.system_count(), 0); + } + + #[test] + fn test_scene_builder_configure() { + let scene = SceneBuilder::new() + .configure(|scene| { + scene.set_name("Configured Scene".to_string()); + }) + .build(); + + assert_eq!(scene.name(), "Configured Scene"); + } + + #[test] + fn test_scene_builder_from_template() { + let scene = SceneBuilder::new() + .from_template(SceneTemplate::Basic) + .build(); + + assert_eq!(scene.name(), "Basic Scene"); + assert_eq!(scene.entity_count(), 10); + } + + #[test] + fn test_scene_builder_validation() { + // 验证失败 - 空名称 + let result1 = SceneBuilder::new() + .validate_and_build(); + assert!(result1.is_err()); + + // 验证失败 - 无实体 + let result2 = SceneBuilder::new() + .named("Test") + .validate_and_build(); + assert!(result2.is_err()); + + // 验证成功 + let result3 = SceneBuilder::new() + .named("Test") + .with_simple_entities(1, "Entity_") + .validate_and_build(); + assert!(result3.is_ok()); + } + + #[test] + fn test_scene_builder_stats() { + let builder = SceneBuilder::new() + .named("Test Scene") + .with_simple_entities(3, "Entity_") + .with_system(Box::new(TestSystem::new())); + + let stats = builder.get_stats(); + assert_eq!(stats.entity_count, 3); + assert_eq!(stats.system_count, 1); + assert!(!stats.is_empty()); + assert!(stats.is_configured()); + assert_eq!(stats.complexity_score(), 5.0); // 3*1 + 1*2 + } + + #[test] + fn test_scene_builder_factory() { + let empty_scene = SceneBuilderFactory::empty().build(); + assert_eq!(empty_scene.entity_count(), 0); + + let basic_scene = SceneBuilderFactory::basic("Test").build(); + assert_eq!(basic_scene.name(), "Test"); + + let test_scene = SceneBuilderFactory::for_testing().build(); + assert_eq!(test_scene.name(), "Test Scene"); + assert_eq!(test_scene.entity_count(), 5); + } + + #[test] + fn test_scene_builder_manager() { + let mut manager = SceneBuilderManager::new(); + + let stats1 = SceneBuilderStats { + entity_count: 5, + system_count: 2, + is_enabled: true, + name_length: 10, + }; + + let stats2 = SceneBuilderStats { + entity_count: 3, + system_count: 1, + is_enabled: true, + name_length: 8, + }; + + manager.record_scene_built(&stats1); + manager.record_scene_built(&stats2); + manager.record_validation_failure(); + + assert_eq!(manager.total_scenes_built, 2); + assert_eq!(manager.total_entities_created, 8); + assert_eq!(manager.total_systems_added, 3); + assert_eq!(manager.validation_failures, 1); + assert_eq!(manager.average_entities_per_scene(), 4.0); + assert_eq!(manager.average_systems_per_scene(), 1.5); + assert!((manager.success_rate() - 0.6666666666666666).abs() < 0.0001); + } +} \ No newline at end of file diff --git a/packages/core-rust/src/core/systems.rs b/packages/core-rust/src/core/systems.rs new file mode 100644 index 00000000..f6d8f36a --- /dev/null +++ b/packages/core-rust/src/core/systems.rs @@ -0,0 +1,521 @@ +use crate::core::entity::Entity; +use crate::core::entity_manager::EntityManager; +use crate::storage::component_storage::ComponentStorageManager; +use crate::utils::time::Time; +use std::any::Any; + +/** + * 系统上下文 + * 提供系统执行时需要的各种管理器引用 + */ +pub struct SystemContext<'a> { + pub entity_manager: &'a mut EntityManager, + pub component_storage_manager: &'a mut ComponentStorageManager, +} + +/** + * 系统基础trait + * 定义ECS系统的基本接口 + */ +pub trait System: Send + Sync { + /** + * 系统初始化 + */ + #[allow(unused_variables)] + fn initialize(&mut self, context: &mut SystemContext) { + // 默认空实现 + } + + /** + * 系统更新 + */ + fn update(&mut self, context: &mut SystemContext); + + /** + * 系统后更新(在所有update完成后调用) + */ + #[allow(unused_variables)] + fn late_update(&mut self, context: &mut SystemContext) { + // 默认空实现 + } + + /** + * 系统销毁清理 + */ + #[allow(unused_variables)] + fn cleanup(&mut self, context: &mut SystemContext) { + // 默认空实现 + } + + /** + * 获取系统更新顺序 + */ + fn update_order(&self) -> i32 { + 0 + } + + /** + * 设置系统更新顺序 + */ + fn set_update_order(&mut self, order: i32); + + /** + * 获取系统启用状态 + */ + fn enabled(&self) -> bool { + true + } + + /** + * 设置系统启用状态 + */ + fn set_enabled(&mut self, enabled: bool); + + /** + * 获取系统名称 + */ + fn name(&self) -> &str { + "System" + } + + /** + * 转换为Any以支持动态转换 + */ + fn as_any(&self) -> &dyn Any; + + /** + * 转换为可变Any以支持动态转换 + */ + fn as_any_mut(&mut self) -> &mut dyn Any; +} + +/** + * 实体系统基类 + * 用于处理一组符合特定条件的实体 + */ +pub struct EntitySystem { + update_order: i32, + enabled: bool, + name: String, + initialized: bool, +} + +impl EntitySystem { + pub fn new(name: String) -> Self { + Self { + update_order: 0, + enabled: true, + name, + initialized: false, + } + } + + /** + * 检查是否需要处理 + */ + pub fn check_processing(&self) -> bool { + self.enabled + } + + /** + * 处理实体列表 + */ + pub fn process(&mut self, entities: &[&Entity], context: &mut SystemContext) { + if !self.check_processing() { + return; + } + + self.process_entities(entities, context); + } + + /** + * 处理实体的具体实现(由子类重写) + */ + #[allow(unused_variables)] + pub fn process_entities(&mut self, entities: &[&Entity], context: &mut SystemContext) { + // 默认空实现 + } + + /** + * 根据实体ID列表处理实体 + * 子类可以重写这个方法实现自定义的实体处理逻辑 + */ + #[allow(unused_variables)] + pub fn process_entity_ids(&mut self, entity_ids: &[u32], context: &mut SystemContext) { + // 默认空实现,由子类根据需要重写 + // 这样避免了借用检查问题,因为子类可以自己决定如何访问实体 + } + + /** + * 处理单个实体(由子类重写) + */ + #[allow(unused_variables)] + pub fn process_single_entity(&mut self, entity: &Entity, context: &mut SystemContext) { + // 默认空实现 + } + + /** + * 系统初始化回调 + */ + #[allow(unused_variables)] + pub fn on_initialize(&mut self, context: &mut SystemContext) { + // 默认空实现 + } + + /** + * 实体添加到系统时的回调 + */ + #[allow(unused_variables)] + pub fn on_entity_added(&mut self, entity: &Entity, context: &mut SystemContext) { + // 默认空实现 + } + + /** + * 实体从系统移除时的回调 + */ + #[allow(unused_variables)] + pub fn on_entity_removed(&mut self, entity: &Entity, context: &mut SystemContext) { + // 默认空实现 + } +} + +impl System for EntitySystem { + fn initialize(&mut self, context: &mut SystemContext) { + if !self.initialized { + self.on_initialize(context); + self.initialized = true; + } + } + + fn update(&mut self, context: &mut SystemContext) { + if !self.enabled { + return; + } + + // 先获取所有实体ID + let entity_ids = context.entity_manager.get_all_entity_ids(); + + // 然后直接处理,避免同时持有不可变和可变引用 + self.process_entity_ids(&entity_ids, context); + } + + fn set_update_order(&mut self, order: i32) { + self.update_order = order; + } + + fn update_order(&self) -> i32 { + self.update_order + } + + fn enabled(&self) -> bool { + self.enabled + } + + fn set_enabled(&mut self, enabled: bool) { + self.enabled = enabled; + } + + fn name(&self) -> &str { + &self.name + } + + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } +} + +/** + * 处理系统 + * 每帧调用processSystem方法 + */ +pub struct ProcessingSystem { + base: EntitySystem, +} + +impl ProcessingSystem { + pub fn new(name: String) -> Self { + Self { + base: EntitySystem::new(name), + } + } + + /** + * 处理系统的具体方法,由子类实现 + */ + #[allow(unused_variables)] + pub fn process_system(&mut self, context: &mut SystemContext) { + // 默认空实现,由子类重写 + } +} + +impl System for ProcessingSystem { + fn initialize(&mut self, context: &mut SystemContext) { + self.base.initialize(context); + } + + fn update(&mut self, context: &mut SystemContext) { + if self.base.enabled() { + self.process_system(context); + } + } + + fn set_update_order(&mut self, order: i32) { + self.base.set_update_order(order); + } + + fn update_order(&self) -> i32 { + self.base.update_order() + } + + fn enabled(&self) -> bool { + self.base.enabled() + } + + fn set_enabled(&mut self, enabled: bool) { + self.base.set_enabled(enabled); + } + + fn name(&self) -> &str { + self.base.name() + } + + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } +} + +/** + * 间隔系统 + * 按指定时间间隔执行处理 + */ +pub struct IntervalSystem { + base: EntitySystem, + interval: f64, + accumulator: f64, +} + +impl IntervalSystem { + pub fn new(name: String, interval: f64) -> Self { + Self { + base: EntitySystem::new(name), + interval, + accumulator: 0.0, + } + } + + /** + * 检查是否应该处理 + */ + fn should_process(&mut self) -> bool { + if !self.base.enabled() { + return false; + } + + self.accumulator += Time::delta_time(); + + if self.accumulator >= self.interval { + self.accumulator -= self.interval; + true + } else { + false + } + } + + /** + * 间隔处理方法,由子类实现 + */ + #[allow(unused_variables)] + pub fn process_interval(&mut self, context: &mut SystemContext) { + // 默认空实现,由子类重写 + } +} + +impl System for IntervalSystem { + fn initialize(&mut self, context: &mut SystemContext) { + self.base.initialize(context); + } + + fn update(&mut self, context: &mut SystemContext) { + if self.should_process() { + self.process_interval(context); + } + } + + fn set_update_order(&mut self, order: i32) { + self.base.set_update_order(order); + } + + fn update_order(&self) -> i32 { + self.base.update_order() + } + + fn enabled(&self) -> bool { + self.base.enabled() + } + + fn set_enabled(&mut self, enabled: bool) { + self.base.set_enabled(enabled); + } + + fn name(&self) -> &str { + self.base.name() + } + + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } +} + +/** + * 系统管理器 + * 管理所有系统的注册、更新和生命周期 + */ +pub struct SystemManager { + systems: Vec>, + initialized: bool, +} + +impl SystemManager { + pub fn new() -> Self { + Self { + systems: Vec::new(), + initialized: false, + } + } + + /** + * 添加系统 + */ + pub fn add_system(&mut self, system: T) { + self.systems.push(Box::new(system)); + // 按更新顺序排序 + self.systems.sort_by_key(|s| s.update_order()); + } + + /** + * 添加系统(Box版本) + */ + pub fn add_system_boxed(&mut self, system: Box) { + self.systems.push(system); + // 按更新顺序排序 + self.systems.sort_by_key(|s| s.update_order()); + } + + /** + * 移除系统 + */ + pub fn remove_system(&mut self) -> bool { + let initial_len = self.systems.len(); + self.systems.retain(|system| { + !system.as_any().is::() + }); + initial_len != self.systems.len() + } + + /** + * 获取系统 + */ + pub fn get_system(&self) -> Option<&T> { + for system in &self.systems { + if let Some(s) = system.as_any().downcast_ref::() { + return Some(s); + } + } + None + } + + /** + * 获取可变系统 + */ + pub fn get_system_mut(&mut self) -> Option<&mut T> { + for system in &mut self.systems { + if let Some(s) = system.as_any_mut().downcast_mut::() { + return Some(s); + } + } + None + } + + /** + * 初始化所有系统 + */ + pub fn initialize(&mut self, context: &mut SystemContext) { + if !self.initialized { + for system in &mut self.systems { + system.initialize(context); + } + self.initialized = true; + } + } + + /** + * 更新所有系统 + */ + pub fn update(&mut self, context: &mut SystemContext) { + for system in &mut self.systems { + if system.enabled() { + system.update(context); + } + } + } + + /** + * 后更新所有系统 + */ + pub fn late_update(&mut self, context: &mut SystemContext) { + for system in &mut self.systems { + if system.enabled() { + system.late_update(context); + } + } + } + + /** + * 清理所有系统 + */ + pub fn cleanup(&mut self, context: &mut SystemContext) { + for system in &mut self.systems { + system.cleanup(context); + } + self.systems.clear(); + self.initialized = false; + } + + /** + * 获取系统数量 + */ + pub fn system_count(&self) -> usize { + self.systems.len() + } + + /** + * 获取启用的系统数量 + */ + pub fn enabled_system_count(&self) -> usize { + self.systems.iter().filter(|s| s.enabled()).count() + } + /** + * 预留系统容量 + */ + pub fn reserve_capacity(&mut self, capacity: usize) { + self.systems.reserve(capacity); + } +} + +impl Default for SystemManager { + fn default() -> Self { + Self::new() + } +} \ No newline at end of file diff --git a/packages/core-rust/src/lib.rs b/packages/core-rust/src/lib.rs new file mode 100644 index 00000000..cda55495 --- /dev/null +++ b/packages/core-rust/src/lib.rs @@ -0,0 +1,33 @@ +// ECS Framework Rust Core - WASM Entry Point +// 只暴露用户需要操作的核心API,内部实现保持私有 + +mod core; +mod storage; +mod utils; +mod wasm; + +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(js_namespace = console)] + fn log(s: &str); +} + +macro_rules! console_log { + ($($t:tt)*) => (log(&format_args!($($t)*).to_string())) +} + +// 只导出WASM包装器,隐藏内部实现 +pub use wasm::{EntityWrapper, EntityManagerWrapper, QuerySystemWrapper, SceneWrapper, ComponentWrapper, ComponentRegistryWrapper}; + +// 导出核心类型供内部使用(不暴露给JavaScript) +pub use core::{Entity, Component, ComponentRegistry, BaseComponent, EntityManager, QuerySystem, QueryResult, Scene, System, EntitySystem, ProcessingSystem, IntervalSystem, SystemManager, ECSEventType, EventPriority, Event, EventListener, EventBus, EventBusStats, SimpleEventListener, ArchetypeSystem, Archetype, ArchetypeId, ArchetypeQueryResult, ArchetypeSystemStats, EntityBuilder, QueryBuilder, ECSFluentAPI, FluentAPIStats, PassiveSystem, PassiveSystemBuilder, ComponentBuilder, BaseComponentBuilder, ComponentBuilderFactory, ComponentBuilderStats, EntityBatchOperator, BatchOperatorStats, SceneBuilder, SceneTemplate, SceneBuilderStats, SceneBuilderFactory, SceneBuilderManager}; +pub use storage::{ComponentStorage, ComponentStorageManager, SoAStorage, SoAFieldType, SoAFieldMetadata, SoAStorageStats, SoAFieldStats}; +pub use utils::{SparseSet, Time, Matcher, QueryCondition, ComponentType, IdentifierPool, IdentifierPoolStats, ComponentPool, ComponentPoolManager, ComponentPoolStats, ComponentPoolManagerStats, PoolStatsSummary, DirtyTrackingSystem, DirtyFlag, DirtyData, DirtyTrackingStats, DirtyListener, DirtyListenerConfig, PerformanceMonitor, PerformanceData, PerformanceStats, PerformanceWarning, PerformanceWarningType, WarningSeverity, PerformanceThresholds, ThresholdPair, Timer, TimerManager, ITimer, TimerContext, TimerCallback, EmptyContext, Pool, PoolManager, Poolable, PoolStats, DebugManager, EntityDataCollector, SystemDataCollector, ComponentDataCollector, PerformanceDataCollector, DebugEntityData, DebugComponentInfo, DebugSystemInfo, DebugArchetypeInfo, DebugPerformanceInfo, DebugWarning, WarningLevel, DebugStats, DebugData, IUpdatable, IUpdatableComparer, SceneComponent, SceneComponentTrait, UpdatableManager, SceneComponentManager, is_updatable, NumberExtension, TypeUtils, StringExtension, CollectionExtension}; + +#[wasm_bindgen(start)] +pub fn main() { + utils::set_panic_hook(); + console_log!("ECS Core Rust initialized - WASM API ready"); +} \ No newline at end of file diff --git a/packages/core-rust/src/storage/component_storage.rs b/packages/core-rust/src/storage/component_storage.rs new file mode 100644 index 00000000..8b892ab1 --- /dev/null +++ b/packages/core-rust/src/storage/component_storage.rs @@ -0,0 +1,301 @@ +use crate::core::component::{Component, ComponentRegistry}; +use rustc_hash::FxHashMap; +use std::any::TypeId; + +/** + * 高性能组件存储器 + */ +pub struct ComponentStorage { + components: Vec>, + entity_to_index: FxHashMap, + index_to_entity: Vec, + free_indices: Vec, + size: usize, +} + +impl ComponentStorage { + pub fn new() -> Self { + Self { + components: Vec::new(), + entity_to_index: FxHashMap::default(), + index_to_entity: Vec::new(), + free_indices: Vec::new(), + size: 0, + } + } + + /** + * 添加组件 + * @param entity_id 实体ID + * @param component 组件实例 + */ + pub fn add_component(&mut self, entity_id: u32, component: T) -> Result<(), String> { + if self.entity_to_index.contains_key(&entity_id) { + return Err(format!("Entity {} already has this component", entity_id)); + } + + let index = if let Some(free_index) = self.free_indices.pop() { + self.components[free_index] = Some(component); + self.index_to_entity[free_index] = entity_id; + free_index + } else { + let index = self.components.len(); + self.components.push(Some(component)); + self.index_to_entity.push(entity_id); + index + }; + + self.entity_to_index.insert(entity_id, index); + self.size += 1; + Ok(()) + } + + /** + * 获取组件 + * @param entity_id 实体ID + * @returns 组件引用或None + */ + pub fn get_component(&self, entity_id: u32) -> Option<&T> { + self.entity_to_index + .get(&entity_id) + .and_then(|&index| self.components.get(index)) + .and_then(|component| component.as_ref()) + } + + /** + * 获取可变组件 + * @param entity_id 实体ID + * @returns 可变组件引用或None + */ + pub fn get_component_mut(&mut self, entity_id: u32) -> Option<&mut T> { + self.entity_to_index + .get(&entity_id) + .and_then(|&index| self.components.get_mut(index)) + .and_then(|component| component.as_mut()) + } + + /** + * 检查实体是否有此组件 + * @param entity_id 实体ID + * @returns 是否有组件 + */ + pub fn has_component(&self, entity_id: u32) -> bool { + self.entity_to_index.contains_key(&entity_id) + } + + /** + * 移除组件 + * @param entity_id 实体ID + * @returns 被移除的组件或None + */ + pub fn remove_component(&mut self, entity_id: u32) -> Option { + let index = self.entity_to_index.remove(&entity_id)?; + let component = self.components[index].take()?; + self.free_indices.push(index); + self.size -= 1; + Some(component) + } + + /** + * 高效遍历所有组件 + * @param callback 回调函数 + */ + pub fn for_each(&self, mut callback: F) + where + F: FnMut(&T, u32, usize), + { + for (index, component) in self.components.iter().enumerate() { + if let Some(comp) = component { + let entity_id = self.index_to_entity[index]; + callback(comp, entity_id, index); + } + } + } + + /** + * 获取所有组件(密集数组) + */ + pub fn get_dense_array(&self) -> (Vec<&T>, Vec) { + let mut components = Vec::new(); + let mut entity_ids = Vec::new(); + + for (index, component) in self.components.iter().enumerate() { + if let Some(comp) = component { + components.push(comp); + entity_ids.push(self.index_to_entity[index]); + } + } + + (components, entity_ids) + } + + /** + * 清空所有组件 + */ + pub fn clear(&mut self) { + self.components.clear(); + self.entity_to_index.clear(); + self.index_to_entity.clear(); + self.free_indices.clear(); + self.size = 0; + } + + /** + * 获取组件数量 + */ + pub fn size(&self) -> usize { + self.size + } + + /** + * 获取存储统计信息 + */ + pub fn get_stats(&self) -> ComponentStorageStats { + let total_slots = self.components.len(); + let used_slots = self.size; + let free_slots = self.free_indices.len(); + let fragmentation = if total_slots > 0 { + free_slots as f32 / total_slots as f32 + } else { + 0.0 + }; + + ComponentStorageStats { + total_slots, + used_slots, + free_slots, + fragmentation, + } + } +} + +/** + * 组件存储统计信息 + */ +pub struct ComponentStorageStats { + pub total_slots: usize, + pub used_slots: usize, + pub free_slots: usize, + pub fragmentation: f32, +} + +/** + * 组件存储管理器 + * 管理所有组件类型的存储器 + */ +pub struct ComponentStorageManager { + storages: FxHashMap>, + registry: ComponentRegistry, +} + +impl ComponentStorageManager { + pub fn new() -> Self { + Self { + storages: FxHashMap::default(), + registry: ComponentRegistry::new(), + } + } + + /** + * 获取组件注册表 + */ + pub fn get_registry(&self) -> &ComponentRegistry { + &self.registry + } + + /** + * 获取可变组件注册表 + */ + pub fn get_registry_mut(&mut self) -> &mut ComponentRegistry { + &mut self.registry + } + + /** + * 添加组件 + * @param entity_id 实体ID + * @param component 组件实例 + */ + pub fn add_component(&mut self, entity_id: u32, component: T) -> Result<(), String> { + let type_id = TypeId::of::(); + + if !self.storages.contains_key(&type_id) { + let storage = Box::new(ComponentStorage::::new()); + self.storages.insert(type_id, storage); + } + + if let Some(storage) = self.storages.get_mut(&type_id) { + storage.add_component_boxed(entity_id, Box::new(component)) + } else { + Err("Failed to get storage".to_string()) + } + } + + /** + * 移除实体的所有组件 + * @param entity_id 实体ID + */ + pub fn remove_all_components(&mut self, entity_id: u32) { + for storage in self.storages.values_mut() { + storage.remove_component_by_entity(entity_id); + } + } + + /** + * 获取实体的组件位掩码 + * @param entity_id 实体ID + * @returns 组件位掩码 + */ + pub fn get_component_mask(&self, entity_id: u32) -> u64 { + let mut mask = 0u64; + for (&type_id, storage) in &self.storages { + if storage.has_component(entity_id) { + if let Some(bit_mask) = self.registry.get_bit_mask(&type_id) { + mask |= bit_mask; + } + } + } + mask + } + + /** + * 清空所有存储器 + */ + pub fn clear(&mut self) { + for storage in self.storages.values_mut() { + storage.clear(); + } + self.storages.clear(); + } +} + +/** + * 组件存储接口 + */ +trait ComponentStorageInterface: Send + Sync { + fn add_component_boxed(&mut self, entity_id: u32, component: Box) -> Result<(), String>; + fn remove_component_by_entity(&mut self, entity_id: u32) -> bool; + fn has_component(&self, entity_id: u32) -> bool; + fn clear(&mut self); +} + +impl ComponentStorageInterface for ComponentStorage { + fn add_component_boxed(&mut self, entity_id: u32, component: Box) -> Result<(), String> { + if let Some(downcasted) = component.as_any().downcast_ref::() { + self.add_component(entity_id, downcasted.clone()) + } else { + Err("Failed to downcast component".to_string()) + } + } + + fn remove_component_by_entity(&mut self, entity_id: u32) -> bool { + self.remove_component(entity_id).is_some() + } + + fn has_component(&self, entity_id: u32) -> bool { + ComponentStorage::has_component(self, entity_id) + } + + fn clear(&mut self) { + ComponentStorage::clear(self) + } +} \ No newline at end of file diff --git a/packages/core-rust/src/storage/mod.rs b/packages/core-rust/src/storage/mod.rs new file mode 100644 index 00000000..7ec3acf9 --- /dev/null +++ b/packages/core-rust/src/storage/mod.rs @@ -0,0 +1,5 @@ +pub mod component_storage; +pub mod soa_storage; + +pub use component_storage::{ComponentStorage, ComponentStorageManager}; +pub use soa_storage::{SoAStorage, SoAFieldType, SoAFieldMetadata, SoAStorageStats, SoAFieldStats}; \ No newline at end of file diff --git a/packages/core-rust/src/storage/soa_storage.rs b/packages/core-rust/src/storage/soa_storage.rs new file mode 100644 index 00000000..6c82aa9c --- /dev/null +++ b/packages/core-rust/src/storage/soa_storage.rs @@ -0,0 +1,999 @@ +use crate::core::Component; +use crate::utils::ComponentType; +use rustc_hash::FxHashMap; +use std::any::Any; +use std::marker::PhantomData; + +/** + * SoA字段类型枚举 + * 定义TypedArray字段的存储类型 + */ +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum SoAFieldType { + Float32, + Float64, + Int32, + Boolean, + String, + Serialized, + Complex, +} + +/** + * SoA字段元数据 + * 记录字段的配置信息 + */ +#[derive(Debug, Clone)] +pub struct SoAFieldMetadata { + pub field_type: SoAFieldType, + pub high_precision: bool, + pub serialize_map: bool, + pub serialize_set: bool, + pub serialize_array: bool, + pub deep_copy: bool, +} + +impl Default for SoAFieldMetadata { + fn default() -> Self { + Self { + field_type: SoAFieldType::Float32, + high_precision: false, + serialize_map: false, + serialize_set: false, + serialize_array: false, + deep_copy: false, + } + } +} + +/** + * SoA存储统计信息 + */ +#[derive(Debug, Clone)] +pub struct SoAStorageStats { + pub size: usize, + pub capacity: usize, + pub used_slots: usize, + pub fragmentation: f64, + pub memory_usage: usize, + pub field_stats: FxHashMap, +} + +/** + * SoA字段统计信息 + */ +#[derive(Debug, Clone)] +pub struct SoAFieldStats { + pub size: usize, + pub capacity: usize, + pub field_type: String, + pub memory: usize, +} + +/** + * SoA存储器 + * 使用Structure of Arrays存储模式,在大规模批量操作时提供优异性能 + */ +pub struct SoAStorage { + /// Float32数值字段 + float32_fields: FxHashMap>, + /// Float64数值字段 + float64_fields: FxHashMap>, + /// Int32数值字段 + int32_fields: FxHashMap>, + /// 字符串字段 + string_fields: FxHashMap>>, + /// 序列化字段(用于复杂对象) + serialized_fields: FxHashMap>>, + /// 复杂对象字段(高精度或非序列化对象) + complex_fields: FxHashMap>>, + /// 实体ID到索引的映射 + entity_to_index: FxHashMap, + /// 索引到实体ID的映射 + index_to_entity: Vec>, + /// 空闲索引列表 + free_indices: Vec, + /// 当前大小 + size: usize, + /// 当前容量 + capacity: usize, + /// 组件类型 + component_type: ComponentType, + /// 字段元数据 + field_metadata: FxHashMap, + /// 类型标记 + _phantom: PhantomData, +} + +impl SoAStorage { + /** + * 创建新的SoA存储器 + */ + pub fn new() -> Self { + let initial_capacity = 1000; + + Self { + float32_fields: FxHashMap::default(), + float64_fields: FxHashMap::default(), + int32_fields: FxHashMap::default(), + string_fields: FxHashMap::default(), + serialized_fields: FxHashMap::default(), + complex_fields: FxHashMap::default(), + entity_to_index: FxHashMap::default(), + index_to_entity: vec![None; initial_capacity], + free_indices: Vec::new(), + size: 0, + capacity: initial_capacity, + component_type: std::any::TypeId::of::(), + field_metadata: FxHashMap::default(), + _phantom: PhantomData, + } + } + + /** + * 使用指定容量创建SoA存储器 + */ + pub fn with_capacity(capacity: usize) -> Self { + Self { + float32_fields: FxHashMap::default(), + float64_fields: FxHashMap::default(), + int32_fields: FxHashMap::default(), + string_fields: FxHashMap::default(), + serialized_fields: FxHashMap::default(), + complex_fields: FxHashMap::default(), + entity_to_index: FxHashMap::default(), + index_to_entity: vec![None; capacity], + free_indices: Vec::new(), + size: 0, + capacity, + component_type: std::any::TypeId::of::(), + field_metadata: FxHashMap::default(), + _phantom: PhantomData, + } + } + + /** + * 初始化字段结构 + * 根据组件类型的特征来设置字段存储类型 + */ + pub fn initialize_fields(&mut self) { + // 在Rust中,我们需要手动注册字段类型 + // 这里提供一个基础的初始化,具体的字段配置需要通过register_field方法添加 + } + + /** + * 注册字段 + */ + pub fn register_field(&mut self, field_name: &str, metadata: SoAFieldMetadata) { + self.field_metadata.insert(field_name.to_string(), metadata.clone()); + + match metadata.field_type { + SoAFieldType::Float32 => { + self.float32_fields.insert(field_name.to_string(), vec![0.0; self.capacity]); + }, + SoAFieldType::Float64 => { + self.float64_fields.insert(field_name.to_string(), vec![0.0; self.capacity]); + }, + SoAFieldType::Int32 => { + self.int32_fields.insert(field_name.to_string(), vec![0; self.capacity]); + }, + SoAFieldType::Boolean => { + // 布尔值使用Float32存储为0/1 + self.float32_fields.insert(field_name.to_string(), vec![0.0; self.capacity]); + }, + SoAFieldType::String => { + self.string_fields.insert(field_name.to_string(), vec![None; self.capacity]); + }, + SoAFieldType::Serialized => { + self.serialized_fields.insert(field_name.to_string(), vec![None; self.capacity]); + }, + SoAFieldType::Complex => { + // 复杂字段在运行时按需添加到complex_fields中 + }, + } + } + + /** + * 添加组件 + */ + pub fn add_component(&mut self, entity_id: u32, component: T) { + if let Some(index) = self.entity_to_index.get(&entity_id) { + // 更新现有组件 + self.update_component_at_index(*index, entity_id, component); + return; + } + + // 获取可用索引 + let index = if let Some(free_index) = self.free_indices.pop() { + free_index + } else { + if self.size >= self.capacity { + self.resize(self.capacity * 2); + } + self.size + }; + + // 设置映射关系 + self.entity_to_index.insert(entity_id, index); + self.index_to_entity[index] = Some(entity_id); + + // 更新组件数据 + self.update_component_at_index(index, entity_id, component); + + if index == self.size { + self.size += 1; + } + } + + /** + * 在指定索引处更新组件数据 + */ + fn update_component_at_index(&mut self, index: usize, entity_id: u32, component: T) { + // 在Rust中,我们无法像TypeScript那样动态遍历对象属性 + // 需要使用trait或者其他方式来序列化组件数据 + // 这里提供一个基础实现,具体的字段设置需要在具体使用时实现 + + // 将组件转换为Any trait对象存储在complex_fields中 + let mut entity_complex_fields = FxHashMap::default(); + entity_complex_fields.insert("component".to_string(), Box::new(component) as Box); + self.complex_fields.insert(entity_id, entity_complex_fields); + } + + /** + * 获取组件 + */ + pub fn get_component(&self, entity_id: u32) -> Option<&T> { + if let Some(index) = self.entity_to_index.get(&entity_id) { + if let Some(complex_fields) = self.complex_fields.get(&entity_id) { + if let Some(component_any) = complex_fields.get("component") { + if let Some(component) = component_any.downcast_ref::() { + return Some(component); + } + } + } + } + None + } + + /** + * 获取可变组件引用 + */ + pub fn get_component_mut(&mut self, entity_id: u32) -> Option<&mut T> { + if let Some(_index) = self.entity_to_index.get(&entity_id) { + if let Some(complex_fields) = self.complex_fields.get_mut(&entity_id) { + if let Some(component_any) = complex_fields.get_mut("component") { + if let Some(component) = component_any.downcast_mut::() { + return Some(component); + } + } + } + } + None + } + + /** + * 检查是否包含指定实体的组件 + */ + pub fn has_component(&self, entity_id: u32) -> bool { + self.entity_to_index.contains_key(&entity_id) + } + + /** + * 移除组件 + */ + pub fn remove_component(&mut self, entity_id: u32) -> bool { + if let Some(index) = self.entity_to_index.remove(&entity_id) { + // 清理复杂字段 + self.complex_fields.remove(&entity_id); + + // 清理索引映射 + self.index_to_entity[index] = None; + self.free_indices.push(index); + + // 清理各类型字段的数据(设为默认值) + for array in self.float32_fields.values_mut() { + if index < array.len() { + array[index] = 0.0; + } + } + + for array in self.float64_fields.values_mut() { + if index < array.len() { + array[index] = 0.0; + } + } + + for array in self.int32_fields.values_mut() { + if index < array.len() { + array[index] = 0; + } + } + + for array in self.string_fields.values_mut() { + if index < array.len() { + array[index] = None; + } + } + + for array in self.serialized_fields.values_mut() { + if index < array.len() { + array[index] = None; + } + } + + true + } else { + false + } + } + + /** + * 调整存储容量 + */ + fn resize(&mut self, new_capacity: usize) { + // 调整数值字段 + for array in self.float32_fields.values_mut() { + array.resize(new_capacity, 0.0); + } + + for array in self.float64_fields.values_mut() { + array.resize(new_capacity, 0.0); + } + + for array in self.int32_fields.values_mut() { + array.resize(new_capacity, 0); + } + + for array in self.string_fields.values_mut() { + array.resize(new_capacity, None); + } + + for array in self.serialized_fields.values_mut() { + array.resize(new_capacity, None); + } + + // 调整索引映射 + self.index_to_entity.resize(new_capacity, None); + + self.capacity = new_capacity; + } + + /** + * 获取活跃索引列表 + */ + pub fn get_active_indices(&self) -> Vec { + self.entity_to_index.values().cloned().collect() + } + + /** + * 获取Float32字段数组 + */ + pub fn get_float32_field(&self, field_name: &str) -> Option<&[f32]> { + self.float32_fields.get(field_name).map(|v| v.as_slice()) + } + + /** + * 获取可变Float32字段数组 + */ + pub fn get_float32_field_mut(&mut self, field_name: &str) -> Option<&mut [f32]> { + self.float32_fields.get_mut(field_name).map(|v| v.as_mut_slice()) + } + + /** + * 获取Float64字段数组 + */ + pub fn get_float64_field(&self, field_name: &str) -> Option<&[f64]> { + self.float64_fields.get(field_name).map(|v| v.as_slice()) + } + + /** + * 获取可变Float64字段数组 + */ + pub fn get_float64_field_mut(&mut self, field_name: &str) -> Option<&mut [f64]> { + self.float64_fields.get_mut(field_name).map(|v| v.as_mut_slice()) + } + + /** + * 获取Int32字段数组 + */ + pub fn get_int32_field(&self, field_name: &str) -> Option<&[i32]> { + self.int32_fields.get(field_name).map(|v| v.as_slice()) + } + + /** + * 获取可变Int32字段数组 + */ + pub fn get_int32_field_mut(&mut self, field_name: &str) -> Option<&mut [i32]> { + self.int32_fields.get_mut(field_name).map(|v| v.as_mut_slice()) + } + + /** + * 获取实体索引 + */ + pub fn get_entity_index(&self, entity_id: u32) -> Option { + self.entity_to_index.get(&entity_id).copied() + } + + /** + * 根据索引获取实体ID + */ + pub fn get_entity_id_by_index(&self, index: usize) -> Option { + if index < self.index_to_entity.len() { + self.index_to_entity[index] + } else { + None + } + } + + /** + * 获取当前大小 + */ + pub fn size(&self) -> usize { + self.size - self.free_indices.len() + } + + /** + * 获取容量 + */ + pub fn capacity(&self) -> usize { + self.capacity + } + + /** + * 清空所有数据 + */ + pub fn clear(&mut self) { + self.entity_to_index.clear(); + self.complex_fields.clear(); + self.free_indices.clear(); + self.size = 0; + + // 重置所有字段数组 + for array in self.float32_fields.values_mut() { + array.fill(0.0); + } + + for array in self.float64_fields.values_mut() { + array.fill(0.0); + } + + for array in self.int32_fields.values_mut() { + array.fill(0); + } + + for array in self.string_fields.values_mut() { + array.fill(None); + } + + for array in self.serialized_fields.values_mut() { + array.fill(None); + } + + for i in 0..self.index_to_entity.len() { + self.index_to_entity[i] = None; + } + } + + /** + * 压缩存储(移除空洞) + */ + pub fn compact(&mut self) { + if self.free_indices.is_empty() { + return; + } + + // 收集所有活跃的实体并按索引排序 + let mut active_entries: Vec<(u32, usize)> = self.entity_to_index.iter() + .map(|(&entity_id, &index)| (entity_id, index)) + .collect(); + active_entries.sort_by_key(|(_, index)| *index); + + // 重新映射索引 + let mut new_entity_to_index = FxHashMap::default(); + let mut new_index_to_entity = vec![None; self.capacity]; + + for (new_index, (entity_id, old_index)) in active_entries.iter().enumerate() { + new_entity_to_index.insert(*entity_id, new_index); + new_index_to_entity[new_index] = Some(*entity_id); + + if new_index != *old_index { + // 移动数据 + self.move_data_between_indices(*old_index, new_index); + } + } + + self.entity_to_index = new_entity_to_index; + self.index_to_entity = new_index_to_entity; + self.free_indices.clear(); + self.size = active_entries.len(); + } + + /** + * 在索引间移动数据 + */ + fn move_data_between_indices(&mut self, from: usize, to: usize) { + // 移动Float32字段 + for array in self.float32_fields.values_mut() { + if from < array.len() && to < array.len() { + array[to] = array[from]; + } + } + + // 移动Float64字段 + for array in self.float64_fields.values_mut() { + if from < array.len() && to < array.len() { + array[to] = array[from]; + } + } + + // 移动Int32字段 + for array in self.int32_fields.values_mut() { + if from < array.len() && to < array.len() { + array[to] = array[from]; + } + } + + // 移动String字段 + for array in self.string_fields.values_mut() { + if from < array.len() && to < array.len() { + array[to] = array[from].take(); + } + } + + // 移动序列化字段 + for array in self.serialized_fields.values_mut() { + if from < array.len() && to < array.len() { + array[to] = array[from].take(); + } + } + } + + /** + * 获取存储统计信息 + */ + pub fn get_stats(&self) -> SoAStorageStats { + let mut total_memory = 0usize; + let mut field_stats = FxHashMap::default(); + + // 计算Float32字段统计 + for (field_name, array) in &self.float32_fields { + let memory = array.len() * std::mem::size_of::(); + total_memory += memory; + field_stats.insert(field_name.clone(), SoAFieldStats { + size: self.size(), + capacity: array.len(), + field_type: "float32".to_string(), + memory, + }); + } + + // 计算Float64字段统计 + for (field_name, array) in &self.float64_fields { + let memory = array.len() * std::mem::size_of::(); + total_memory += memory; + field_stats.insert(field_name.clone(), SoAFieldStats { + size: self.size(), + capacity: array.len(), + field_type: "float64".to_string(), + memory, + }); + } + + // 计算Int32字段统计 + for (field_name, array) in &self.int32_fields { + let memory = array.len() * std::mem::size_of::(); + total_memory += memory; + field_stats.insert(field_name.clone(), SoAFieldStats { + size: self.size(), + capacity: array.len(), + field_type: "int32".to_string(), + memory, + }); + } + + // 估算字符串和序列化字段内存(简单估算) + for (field_name, array) in &self.string_fields { + let estimated_memory = array.len() * 64; // 假设平均64字节每个字符串 + total_memory += estimated_memory; + field_stats.insert(field_name.clone(), SoAFieldStats { + size: self.size(), + capacity: array.len(), + field_type: "string".to_string(), + memory: estimated_memory, + }); + } + + SoAStorageStats { + size: self.size(), + capacity: self.capacity, + used_slots: self.size(), + fragmentation: self.free_indices.len() as f64 / self.capacity as f64, + memory_usage: total_memory, + field_stats, + } + } + + /** + * 执行向量化批量操作 + */ + pub fn perform_vectorized_operation(&mut self, operation: F) + where + F: FnOnce(&mut SoAStorage), + { + operation(self); + } +} + +impl Default for SoAStorage { + fn default() -> Self { + Self::new() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::any::Any; + + // 测试组件 + #[derive(Debug, Clone)] + struct TestComponent { + pub x: f32, + pub y: f32, + pub name: String, + pub active: bool, + pub id: u32, + pub enabled: bool, + pub update_order: i32, + } + + impl TestComponent { + fn new() -> Self { + Self { + x: 0.0, + y: 0.0, + name: String::new(), + active: false, + id: 0, + enabled: true, + update_order: 0, + } + } + } + + impl Component for TestComponent { + fn id(&self) -> u32 { + self.id + } + + + fn enabled(&self) -> bool { + self.enabled + } + + fn set_enabled(&mut self, enabled: bool) { + self.enabled = enabled; + } + + fn update_order(&self) -> i32 { + self.update_order + } + + fn set_update_order(&mut self, order: i32) { + self.update_order = order; + } + + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } + + fn clone_box(&self) -> Box { + Box::new(self.clone()) + } + } + + #[test] + fn test_soa_storage_creation() { + let storage: SoAStorage = SoAStorage::new(); + assert_eq!(storage.size(), 0); + assert_eq!(storage.capacity(), 1000); + } + + #[test] + fn test_soa_storage_with_capacity() { + let storage: SoAStorage = SoAStorage::with_capacity(500); + assert_eq!(storage.size(), 0); + assert_eq!(storage.capacity(), 500); + } + + #[test] + fn test_field_registration() { + let mut storage: SoAStorage = SoAStorage::new(); + + storage.register_field("x", SoAFieldMetadata { + field_type: SoAFieldType::Float32, + ..Default::default() + }); + + storage.register_field("name", SoAFieldMetadata { + field_type: SoAFieldType::String, + ..Default::default() + }); + + assert!(storage.get_float32_field("x").is_some()); + assert_eq!(storage.get_float32_field("x").unwrap().len(), 1000); + } + + #[test] + fn test_component_add_remove() { + let mut storage: SoAStorage = SoAStorage::new(); + + let component = TestComponent { + x: 1.0, + y: 2.0, + name: "test".to_string(), + active: true, + id: 1, + enabled: true, + update_order: 0, + }; + + let entity_id = 1; + + // 添加组件 + storage.add_component(entity_id, component.clone()); + assert_eq!(storage.size(), 1); + assert!(storage.has_component(entity_id)); + + // 获取组件 + let retrieved = storage.get_component(entity_id); + assert!(retrieved.is_some()); + + // 移除组件 + assert!(storage.remove_component(entity_id)); + assert_eq!(storage.size(), 0); + assert!(!storage.has_component(entity_id)); + } + + #[test] + fn test_multiple_components() { + let mut storage: SoAStorage = SoAStorage::new(); + + for i in 1..=10 { + let component = TestComponent { + x: i as f32, + y: i as f32 * 2.0, + name: format!("test{}", i), + active: i % 2 == 0, + id: i, + enabled: true, + update_order: 0, + }; + storage.add_component(i, component); + } + + assert_eq!(storage.size(), 10); + + // 验证所有组件都存在 + for i in 1..=10 { + assert!(storage.has_component(i)); + } + + // 移除一半组件 + for i in (1..=10).step_by(2) { + storage.remove_component(i); + } + + assert_eq!(storage.size(), 5); + } + + #[test] + fn test_storage_resize() { + let mut storage: SoAStorage = SoAStorage::with_capacity(5); + + // 添加超过初始容量的组件 + for i in 1..=10 { + let component = TestComponent { + x: i as f32, + y: i as f32, + name: format!("test{}", i), + active: true, + id: i, + enabled: true, + update_order: 0, + }; + storage.add_component(i, component); + } + + assert_eq!(storage.size(), 10); + assert!(storage.capacity() >= 10); // 应该已经扩容 + } + + #[test] + fn test_storage_clear() { + let mut storage: SoAStorage = SoAStorage::new(); + + // 添加一些组件 + for i in 1..=5 { + let component = TestComponent { + x: i as f32, + y: i as f32, + name: format!("test{}", i), + active: true, + id: i, + enabled: true, + update_order: 0, + }; + storage.add_component(i, component); + } + + assert_eq!(storage.size(), 5); + + storage.clear(); + + assert_eq!(storage.size(), 0); + for i in 1..=5 { + assert!(!storage.has_component(i)); + } + } + + #[test] + fn test_storage_compact() { + let mut storage: SoAStorage = SoAStorage::new(); + + // 添加组件 + for i in 1..=10 { + let component = TestComponent { + x: i as f32, + y: i as f32, + name: format!("test{}", i), + active: true, + id: i, + enabled: true, + update_order: 0, + }; + storage.add_component(i, component); + } + + // 移除一些组件制造空洞 + storage.remove_component(2); + storage.remove_component(4); + storage.remove_component(6); + + assert_eq!(storage.size(), 7); + assert_eq!(storage.free_indices.len(), 3); + + storage.compact(); + + assert_eq!(storage.size(), 7); + assert!(storage.free_indices.is_empty()); + } + + #[test] + fn test_storage_stats() { + let mut storage: SoAStorage = SoAStorage::new(); + + storage.register_field("x", SoAFieldMetadata { + field_type: SoAFieldType::Float32, + ..Default::default() + }); + + storage.register_field("y", SoAFieldMetadata { + field_type: SoAFieldType::Float64, + ..Default::default() + }); + + let component = TestComponent { + x: 1.0, + y: 2.0, + name: "test".to_string(), + active: true, + id: 1, + enabled: true, + update_order: 0, + }; + + storage.add_component(1, component); + + let stats = storage.get_stats(); + assert_eq!(stats.size, 1); + assert_eq!(stats.capacity, 1000); + assert!(stats.memory_usage > 0); + assert!(!stats.field_stats.is_empty()); + } + + #[test] + fn test_vectorized_operation() { + let mut storage: SoAStorage = SoAStorage::new(); + + storage.register_field("x", SoAFieldMetadata { + field_type: SoAFieldType::Float32, + ..Default::default() + }); + + // 设置初始数据到Float32字段中 + if let Some(x_field) = storage.get_float32_field_mut("x") { + for i in 0..5 { + x_field[i] = (i + 1) as f32; + } + } + + // 执行向量化操作 + storage.perform_vectorized_operation(|storage| { + if let Some(x_field) = storage.get_float32_field_mut("x") { + // 将所有x值乘以2 + for i in 0..5 { + x_field[i] *= 2.0; + } + } + }); + + // 验证操作结果 + if let Some(x_field) = storage.get_float32_field("x") { + assert_eq!(x_field[0], 2.0); // 第一个元素应该是2 + } + } + + #[test] + fn test_entity_index_mapping() { + let mut storage: SoAStorage = SoAStorage::new(); + + let component = TestComponent { + x: 1.0, + y: 2.0, + name: "test".to_string(), + active: true, + id: 1, + enabled: true, + update_order: 0, + }; + + storage.add_component(100, component); + + let index = storage.get_entity_index(100); + assert!(index.is_some()); + + let entity_id = storage.get_entity_id_by_index(index.unwrap()); + assert_eq!(entity_id, Some(100)); + } + + #[test] + fn test_active_indices() { + let mut storage: SoAStorage = SoAStorage::new(); + + let component1 = TestComponent { + x: 1.0, + y: 1.0, + name: "test1".to_string(), + active: true, + id: 1, + enabled: true, + update_order: 0, + }; + + let component2 = TestComponent { + x: 2.0, + y: 2.0, + name: "test2".to_string(), + active: true, + id: 2, + enabled: true, + update_order: 0, + }; + + storage.add_component(1, component1); + storage.add_component(2, component2); + + let active_indices = storage.get_active_indices(); + assert_eq!(active_indices.len(), 2); + + storage.remove_component(1); + + let active_indices = storage.get_active_indices(); + assert_eq!(active_indices.len(), 1); + } +} \ No newline at end of file diff --git a/packages/core-rust/src/utils/component_pool.rs b/packages/core-rust/src/utils/component_pool.rs new file mode 100644 index 00000000..a8e77701 --- /dev/null +++ b/packages/core-rust/src/utils/component_pool.rs @@ -0,0 +1,766 @@ +use crate::core::Component; +use crate::utils::ComponentType; +use rustc_hash::FxHashMap; +use std::any::Any; + +/** + * 组件对象池,用于复用组件实例以减少内存分配 + */ +pub struct ComponentPool +where + T: Component + Clone + Default, +{ + /// 池中存储的组件实例 + pool: Vec, + /// 创建新组件实例的函数 + create_fn: Box T + Send + Sync>, + /// 重置组件状态的函数(可选) + reset_fn: Option>, + /// 池的最大容量 + max_size: usize, + /// 统计信息 + stats: ComponentPoolStats, +} + +/** + * 组件池统计信息 + */ +#[derive(Debug, Clone)] +pub struct ComponentPoolStats { + /// 总共创建的组件数量 + pub total_created: u32, + /// 总共获取的次数 + pub total_acquires: u32, + /// 总共释放的次数 + pub total_releases: u32, + /// 池命中次数(从池中获取而不是创建新的) + pub pool_hits: u32, + /// 池未命中次数(需要创建新实例) + pub pool_misses: u32, +} + +impl Default for ComponentPoolStats { + fn default() -> Self { + Self { + total_created: 0, + total_acquires: 0, + total_releases: 0, + pool_hits: 0, + pool_misses: 0, + } + } +} + +impl ComponentPool +where + T: Component + Clone + Default, +{ + /** + * 创建新的组件池 + */ + pub fn new(create_fn: F, reset_fn: Option, max_size: usize) -> Self + where + F: Fn() -> T + Send + Sync + 'static, + R: Fn(&mut T) + Send + Sync + 'static, + { + Self { + pool: Vec::with_capacity(max_size.min(100)), // 预分配一些空间 + create_fn: Box::new(create_fn), + reset_fn: reset_fn.map(|f| Box::new(f) as Box), + max_size, + stats: ComponentPoolStats::default(), + } + } + + /** + * 创建默认的组件池(使用Default trait) + */ + pub fn with_default(max_size: usize) -> Self { + Self::new(T::default, None::, max_size) + } + + /** + * 创建带重置函数的默认组件池 + */ + pub fn with_default_and_reset(reset_fn: R, max_size: usize) -> Self + where + R: Fn(&mut T) + Send + Sync + 'static, + { + Self::new(T::default, Some(reset_fn), max_size) + } + + /** + * 获取一个组件实例 + */ + pub fn acquire(&mut self) -> T { + self.stats.total_acquires += 1; + + if let Some(component) = self.pool.pop() { + self.stats.pool_hits += 1; + component + } else { + self.stats.pool_misses += 1; + self.stats.total_created += 1; + (self.create_fn)() + } + } + + /** + * 释放一个组件实例回池中 + */ + pub fn release(&mut self, mut component: T) { + self.stats.total_releases += 1; + + if self.pool.len() < self.max_size { + // 调用重置函数(如果有) + if let Some(ref reset_fn) = self.reset_fn { + reset_fn(&mut component); + } + + self.pool.push(component); + } + // 如果池已满,组件会被丢弃(由Rust自动清理) + } + + /** + * 预填充对象池 + */ + pub fn prewarm(&mut self, count: usize) { + let needed = (self.max_size - self.pool.len()).min(count); + + for _ in 0..needed { + let component = (self.create_fn)(); + self.pool.push(component); + self.stats.total_created += 1; + } + } + + /** + * 清空对象池 + */ + pub fn clear(&mut self) { + self.pool.clear(); + } + + /** + * 获取池中可用对象数量 + */ + pub fn available_count(&self) -> usize { + self.pool.len() + } + + /** + * 获取池的最大容量 + */ + pub fn max_size(&self) -> usize { + self.max_size + } + + /** + * 获取使用中的对象数量估算 + */ + pub fn used_count(&self) -> u32 { + // 基于统计信息估算(总创建 - 池中可用) + if self.stats.total_created as usize >= self.pool.len() { + self.stats.total_created - self.pool.len() as u32 + } else { + 0 + } + } + + /** + * 获取池利用率(百分比) + */ + pub fn utilization_rate(&self) -> f32 { + if self.max_size == 0 { + return 0.0; + } + + let used = self.used_count() as f32; + let total = self.max_size as f32; + (used / total) * 100.0 + } + + /** + * 获取池命中率(百分比) + */ + pub fn hit_rate(&self) -> f32 { + if self.stats.total_acquires == 0 { + return 0.0; + } + + (self.stats.pool_hits as f32 / self.stats.total_acquires as f32) * 100.0 + } + + /** + * 获取统计信息 + */ + pub fn get_stats(&self) -> ComponentPoolStats { + self.stats.clone() + } + + /** + * 重置统计信息 + */ + pub fn reset_stats(&mut self) { + self.stats = ComponentPoolStats::default(); + } + + /** + * 获取内存使用估算(字节) + */ + pub fn estimated_memory_usage(&self) -> usize { + let component_size = std::mem::size_of::(); + let pool_size = self.pool.len() * component_size; + let vec_overhead = self.pool.capacity() * std::mem::size_of::(); + + pool_size + vec_overhead + } +} + +/** + * 类型擦除的组件池特征 + * 用于在ComponentPoolManager中统一管理不同类型的池 + */ +trait AnyComponentPool { + fn clear(&mut self); + fn available_count(&self) -> usize; + fn max_size(&self) -> usize; + fn used_count(&self) -> u32; + fn utilization_rate(&self) -> f32; + fn hit_rate(&self) -> f32; + fn estimated_memory_usage(&self) -> usize; + fn prewarm(&mut self, count: usize); + fn as_any(&self) -> &dyn Any; + fn as_any_mut(&mut self) -> &mut dyn Any; +} + +impl AnyComponentPool for ComponentPool +where + T: Component + Clone + Default, +{ + fn clear(&mut self) { + self.clear(); + } + + fn available_count(&self) -> usize { + self.available_count() + } + + fn max_size(&self) -> usize { + self.max_size() + } + + fn used_count(&self) -> u32 { + self.used_count() + } + + fn utilization_rate(&self) -> f32 { + self.utilization_rate() + } + + fn hit_rate(&self) -> f32 { + self.hit_rate() + } + + fn estimated_memory_usage(&self) -> usize { + self.estimated_memory_usage() + } + + fn prewarm(&mut self, count: usize) { + self.prewarm(count); + } + + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } +} + +/** + * 池统计信息摘要 + */ +#[derive(Debug, Clone)] +pub struct PoolStatsSummary { + pub available: usize, + pub max_size: usize, + pub used: u32, + pub utilization_rate: f32, + pub hit_rate: f32, + pub memory_usage: usize, +} + +/** + * 全局组件池管理器 + * 使用单例模式管理所有组件类型的对象池 + */ +pub struct ComponentPoolManager { + /// 存储各种组件类型的池 + pools: FxHashMap>, + /// 管理器统计信息 + stats: ComponentPoolManagerStats, +} + +/** + * 组件池管理器统计信息 + */ +#[derive(Debug, Clone)] +pub struct ComponentPoolManagerStats { + pub registered_pools: u32, + pub total_memory_usage: usize, + pub total_components_managed: u32, +} + +impl Default for ComponentPoolManagerStats { + fn default() -> Self { + Self { + registered_pools: 0, + total_memory_usage: 0, + total_components_managed: 0, + } + } +} + +impl ComponentPoolManager { + /** + * 创建新的组件池管理器 + */ + pub fn new() -> Self { + Self { + pools: FxHashMap::default(), + stats: ComponentPoolManagerStats::default(), + } + } + + /** + * 注册组件池 + */ + pub fn register_pool( + &mut self, + component_type: ComponentType, + create_fn: F, + reset_fn: Option, + max_size: Option, + ) where + T: Component + Clone + Default + 'static, + F: Fn() -> T + Send + Sync + 'static, + R: Fn(&mut T) + Send + Sync + 'static, + { + let max_size = max_size.unwrap_or(1000); + let pool = ComponentPool::new(create_fn, reset_fn, max_size); + + self.pools.insert(component_type, Box::new(pool)); + self.update_stats(); + } + + /** + * 注册使用Default的组件池 + */ + pub fn register_pool_default(&mut self, component_type: ComponentType, max_size: Option) + where + T: Component + Clone + Default + 'static, + { + let max_size = max_size.unwrap_or(1000); + let pool = ComponentPool::::with_default(max_size); + + self.pools.insert(component_type, Box::new(pool)); + self.update_stats(); + } + + /** + * 获取组件实例 + */ + pub fn acquire_component(&mut self, component_type: ComponentType) -> Option + where + T: Component + Clone + Default + 'static, + { + if let Some(pool) = self.pools.get_mut(&component_type) { + if let Some(typed_pool) = pool.as_any_mut().downcast_mut::>() { + return Some(typed_pool.acquire()); + } + } + None + } + + /** + * 释放组件实例 + */ + pub fn release_component(&mut self, component_type: ComponentType, component: T) + where + T: Component + Clone + Default + 'static, + { + if let Some(pool) = self.pools.get_mut(&component_type) { + if let Some(typed_pool) = pool.as_any_mut().downcast_mut::>() { + typed_pool.release(component); + } + } + } + + /** + * 预热所有池 + */ + pub fn prewarm_all(&mut self, count: usize) { + for pool in self.pools.values_mut() { + pool.prewarm(count); + } + self.update_stats(); + } + + /** + * 预热指定池 + */ + pub fn prewarm_pool(&mut self, component_type: ComponentType, count: usize) { + if let Some(pool) = self.pools.get_mut(&component_type) { + pool.prewarm(count); + self.update_stats(); + } + } + + /** + * 清空所有池 + */ + pub fn clear_all(&mut self) { + for pool in self.pools.values_mut() { + pool.clear(); + } + self.update_stats(); + } + + /** + * 清空指定池 + */ + pub fn clear_pool(&mut self, component_type: ComponentType) { + if let Some(pool) = self.pools.get_mut(&component_type) { + pool.clear(); + self.update_stats(); + } + } + + /** + * 移除所有注册的池 + */ + pub fn reset(&mut self) { + self.pools.clear(); + self.stats = ComponentPoolManagerStats::default(); + } + + /** + * 获取池统计信息 + */ + pub fn get_pool_stats(&self) -> FxHashMap { + let mut stats = FxHashMap::default(); + + for (&component_type, pool) in &self.pools { + let summary = PoolStatsSummary { + available: pool.available_count(), + max_size: pool.max_size(), + used: pool.used_count(), + utilization_rate: pool.utilization_rate(), + hit_rate: pool.hit_rate(), + memory_usage: pool.estimated_memory_usage(), + }; + stats.insert(component_type, summary); + } + + stats + } + + /** + * 获取指定组件的池利用率 + */ + pub fn get_component_utilization(&self, component_type: ComponentType) -> f32 { + self.pools.get(&component_type) + .map(|pool| pool.utilization_rate()) + .unwrap_or(0.0) + } + + /** + * 获取指定组件的池命中率 + */ + pub fn get_component_hit_rate(&self, component_type: ComponentType) -> f32 { + self.pools.get(&component_type) + .map(|pool| pool.hit_rate()) + .unwrap_or(0.0) + } + + /** + * 获取管理器统计信息 + */ + pub fn get_manager_stats(&self) -> ComponentPoolManagerStats { + self.stats.clone() + } + + /** + * 获取所有池的总内存使用量 + */ + pub fn get_total_memory_usage(&self) -> usize { + self.pools.values() + .map(|pool| pool.estimated_memory_usage()) + .sum() + } + + /** + * 检查是否注册了指定组件类型的池 + */ + pub fn has_pool(&self, component_type: ComponentType) -> bool { + self.pools.contains_key(&component_type) + } + + /** + * 获取注册的池数量 + */ + pub fn pool_count(&self) -> usize { + self.pools.len() + } + + // 私有方法 + + /** + * 更新管理器统计信息 + */ + fn update_stats(&mut self) { + self.stats.registered_pools = self.pools.len() as u32; + self.stats.total_memory_usage = self.get_total_memory_usage(); + self.stats.total_components_managed = self.pools.values() + .map(|pool| pool.used_count() + pool.available_count() as u32) + .sum(); + } +} + +impl Default for ComponentPoolManager { + fn default() -> Self { + Self::new() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::any::TypeId; + + // 测试用的示例组件 + #[derive(Clone, Default, Debug, PartialEq)] + struct TestComponent { + pub value: i32, + pub name: String, + } + + impl Component for TestComponent { + fn id(&self) -> u32 { 0 } + fn set_enabled(&mut self, _enabled: bool) {} + fn set_update_order(&mut self, _order: i32) {} + fn as_any(&self) -> &dyn std::any::Any { self } + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { self } + fn clone_box(&self) -> Box { Box::new(self.clone()) } + } + + #[derive(Clone, Default, Debug)] + struct AnotherTestComponent { + pub data: String, + } + + impl Component for AnotherTestComponent { + fn id(&self) -> u32 { 0 } + fn set_enabled(&mut self, _enabled: bool) {} + fn set_update_order(&mut self, _order: i32) {} + fn as_any(&self) -> &dyn std::any::Any { self } + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { self } + fn clone_box(&self) -> Box { Box::new(self.clone()) } + } + + #[test] + fn test_component_pool_basic() { + let pool = ComponentPool::::with_default(10); + + // 测试基本属性 + assert_eq!(pool.available_count(), 0); + assert_eq!(pool.max_size(), 10); + assert_eq!(pool.utilization_rate(), 0.0); + } + + #[test] + fn test_component_pool_acquire_release() { + let mut pool = ComponentPool::::with_default(5); + + // 第一次获取应该创建新实例 + let mut component1 = pool.acquire(); + component1.value = 42; + component1.name = "test".to_string(); + + assert_eq!(pool.available_count(), 0); + assert_eq!(pool.get_stats().pool_misses, 1); + + // 释放组件 + pool.release(component1); + assert_eq!(pool.available_count(), 1); + + // 再次获取应该从池中获取 + let component2 = pool.acquire(); + assert_eq!(pool.available_count(), 0); + assert_eq!(pool.get_stats().pool_hits, 1); + + // 验证是同一个实例(虽然值可能不同) + assert_eq!(component2.value, 42); // 没有重置函数,值保持不变 + } + + #[test] + fn test_component_pool_with_reset() { + let reset_fn = |comp: &mut TestComponent| { + comp.value = 0; + comp.name.clear(); + }; + + let mut pool = ComponentPool::with_default_and_reset(reset_fn, 5); + + let mut component = pool.acquire(); + component.value = 42; + component.name = "test".to_string(); + + pool.release(component); + + let component2 = pool.acquire(); + assert_eq!(component2.value, 0); + assert_eq!(component2.name, ""); + } + + #[test] + fn test_component_pool_max_capacity() { + let mut pool = ComponentPool::::with_default(2); + + // 获取3个组件 + let comp1 = pool.acquire(); + let comp2 = pool.acquire(); + let comp3 = pool.acquire(); + + // 释放所有组件 + pool.release(comp1); + pool.release(comp2); + pool.release(comp3); + + // 只有2个组件被存储在池中(最大容量限制) + assert_eq!(pool.available_count(), 2); + } + + #[test] + fn test_component_pool_prewarm() { + let mut pool = ComponentPool::::with_default(10); + + pool.prewarm(5); + assert_eq!(pool.available_count(), 5); + + // 预热不应该超过最大容量 + pool.prewarm(10); + assert_eq!(pool.available_count(), 10); + } + + #[test] + fn test_component_pool_stats() { + let mut pool = ComponentPool::::with_default(5); + + // 获取一些组件 + let _comp1 = pool.acquire(); + let _comp2 = pool.acquire(); + + let stats = pool.get_stats(); + assert_eq!(stats.total_acquires, 2); + assert_eq!(stats.pool_misses, 2); + assert_eq!(stats.pool_hits, 0); + assert_eq!(stats.total_created, 2); + } + + #[test] + fn test_component_pool_manager_basic() { + let mut manager = ComponentPoolManager::new(); + + // 注册池 + manager.register_pool_default::(TypeId::of::(), Some(20)); + + assert!(manager.has_pool(TypeId::of::())); + assert_eq!(manager.pool_count(), 1); + } + + #[test] + fn test_component_pool_manager_acquire_release() { + let mut manager = ComponentPoolManager::new(); + + manager.register_pool_default::(TypeId::of::(), Some(10)); + + // 获取组件 + let mut component = manager.acquire_component::(TypeId::of::()).unwrap(); + component.value = 42; + + // 释放组件 + manager.release_component(TypeId::of::(), component); + + // 再次获取应该从池中获取 + let reused_component = manager.acquire_component::(TypeId::of::()).unwrap(); + assert_eq!(reused_component.value, 42); + } + + #[test] + fn test_component_pool_manager_multiple_types() { + let mut manager = ComponentPoolManager::new(); + + manager.register_pool_default::(TypeId::of::(), Some(10)); + manager.register_pool_default::(TypeId::of::(), Some(15)); + + assert_eq!(manager.pool_count(), 2); + + // 测试不同类型的组件 + let _test_comp = manager.acquire_component::(TypeId::of::()).unwrap(); + let _another_comp = manager.acquire_component::(TypeId::of::()).unwrap(); + } + + #[test] + fn test_component_pool_manager_stats() { + let mut manager = ComponentPoolManager::new(); + + manager.register_pool_default::(TypeId::of::(), Some(10)); + manager.prewarm_pool(TypeId::of::(), 5); + + let stats = manager.get_pool_stats(); + let test_comp_stats = stats.get(&TypeId::of::()).unwrap(); + + assert_eq!(test_comp_stats.available, 5); + assert_eq!(test_comp_stats.max_size, 10); + assert!(test_comp_stats.memory_usage > 0); + } + + #[test] + fn test_component_pool_manager_prewarm_and_clear() { + let mut manager = ComponentPoolManager::new(); + + manager.register_pool_default::(TypeId::of::(), Some(10)); + manager.register_pool_default::(TypeId::of::(), Some(10)); + + // 预热所有池 + manager.prewarm_all(5); + + let stats = manager.get_pool_stats(); + assert_eq!(stats.get(&TypeId::of::()).unwrap().available, 5); + assert_eq!(stats.get(&TypeId::of::()).unwrap().available, 5); + + // 清空所有池 + manager.clear_all(); + + let stats = manager.get_pool_stats(); + assert_eq!(stats.get(&TypeId::of::()).unwrap().available, 0); + assert_eq!(stats.get(&TypeId::of::()).unwrap().available, 0); + } + + #[test] + fn test_component_pool_manager_unknown_type() { + let mut manager = ComponentPoolManager::new(); + + // 尝试获取未注册类型的组件 + let result = manager.acquire_component::(TypeId::of::()); + assert!(result.is_none()); + + // 释放到未注册的池应该安全处理 + let component = TestComponent::default(); + manager.release_component(TypeId::of::(), component); // 不应该panic + } +} \ No newline at end of file diff --git a/packages/core-rust/src/utils/debug.rs b/packages/core-rust/src/utils/debug.rs new file mode 100644 index 00000000..6da7d2f1 --- /dev/null +++ b/packages/core-rust/src/utils/debug.rs @@ -0,0 +1,1060 @@ +use rustc_hash::FxHashMap; +use serde::{Serialize, Deserialize}; + +/** + * Debug数据类型 + */ +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DebugEntityData { + pub entity_id: u32, + pub name: String, + pub enabled: bool, + pub component_count: usize, + pub components: Vec, + pub memory_usage: usize, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DebugComponentInfo { + pub type_name: String, + pub enabled: bool, + pub memory_size: usize, + pub properties: FxHashMap, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DebugSystemInfo { + pub name: String, + pub enabled: bool, + pub priority: i32, + pub execution_time_ms: f64, + pub entity_count: usize, + pub update_frequency: f64, + pub last_execution: u64, + pub total_executions: u64, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DebugArchetypeInfo { + pub signature: String, + pub entity_count: usize, + pub component_types: Vec, + pub memory_usage: usize, + pub entities: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DebugPerformanceInfo { + pub fps: f64, + pub frame_time_ms: f64, + pub delta_time_ms: f64, + pub memory_usage_bytes: usize, + pub total_entities: usize, + pub total_systems: usize, + pub total_components: usize, + pub warnings: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DebugWarning { + pub level: WarningLevel, + pub message: String, + pub timestamp: u64, + pub source: String, +} + +#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] +pub enum WarningLevel { + Info, + Warning, + Error, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DebugStats { + pub total_memory: usize, + pub entity_memory: usize, + pub component_memory: usize, + pub system_memory: usize, + pub pool_memory: usize, +} + +/** + * 实体数据收集器 + * 负责收集和格式化实体相关的调试信息 + */ +pub struct EntityDataCollector { + entity_cache: FxHashMap, + last_update_time: u64, + cache_duration: u64, +} + +impl EntityDataCollector { + /** + * 创建新的实体数据收集器 + */ + pub fn new() -> Self { + Self { + entity_cache: FxHashMap::default(), + last_update_time: 0, + cache_duration: 1000, // 1秒缓存 + } + } + + /** + * 收集所有实体的调试数据 + */ + pub fn collect_entity_data(&mut self) -> Vec { + let current_time = current_timestamp(); + + // 如果缓存仍然有效,直接返回 + if current_time - self.last_update_time < self.cache_duration && !self.entity_cache.is_empty() { + return self.entity_cache.values().cloned().collect(); + } + + // 重新收集数据 + self.refresh_entity_cache(); + self.last_update_time = current_time; + + self.entity_cache.values().cloned().collect() + } + + /** + * 获取指定实体的详细信息 + */ + pub fn get_entity_details(&self, entity_id: u32) -> Option { + self.entity_cache.get(&entity_id).cloned() + } + + /** + * 计算实体内存使用 + */ + pub fn calculate_entity_memory_usage(&self, entity_id: u32) -> usize { + if let Some(entity_data) = self.entity_cache.get(&entity_id) { + entity_data.memory_usage + } else { + std::mem::size_of::() * 2 // 基本实体开销 + } + } + + /** + * 刷新实体缓存 + */ + fn refresh_entity_cache(&mut self) { + self.entity_cache.clear(); + + // 模拟收集实体数据(在实际实现中会从Scene中获取) + // TODO: 从实际的Scene和EntityManager中获取数据 + + // 示例数据 + for i in 1..=10 { + let entity_data = DebugEntityData { + entity_id: i, + name: format!("Entity_{}", i), + enabled: true, + component_count: ((i % 3) + 1) as usize, + components: vec![ + DebugComponentInfo { + type_name: "Transform".to_string(), + enabled: true, + memory_size: 48, + properties: { + let mut props = FxHashMap::default(); + props.insert("x".to_string(), "0.0".to_string()); + props.insert("y".to_string(), "0.0".to_string()); + props.insert("rotation".to_string(), "0.0".to_string()); + props + }, + } + ], + memory_usage: 64 + (48 * ((i % 3) + 1) as usize), + }; + + self.entity_cache.insert(i, entity_data); + } + } + + /** + * 获取实体数量统计 + */ + pub fn get_entity_count_stats(&self) -> (usize, usize) { + let total = self.entity_cache.len(); + let active = self.entity_cache.values().filter(|e| e.enabled).count(); + (total, active) + } + + /** + * 按组件数量排序实体 + */ + pub fn get_entities_by_component_count(&self) -> Vec { + let mut entities: Vec<_> = self.entity_cache.values().cloned().collect(); + entities.sort_by(|a, b| b.component_count.cmp(&a.component_count)); + entities + } + + /** + * 清空缓存 + */ + pub fn clear_cache(&mut self) { + self.entity_cache.clear(); + self.last_update_time = 0; + } +} + +/** + * 系统数据收集器 + * 负责收集和格式化系统相关的调试信息 + */ +pub struct SystemDataCollector { + system_stats: FxHashMap, + execution_history: FxHashMap>, + history_size: usize, +} + +impl SystemDataCollector { + /** + * 创建新的系统数据收集器 + */ + pub fn new() -> Self { + Self { + system_stats: FxHashMap::default(), + execution_history: FxHashMap::default(), + history_size: 60, // 保持60帧的历史记录 + } + } + + /** + * 收集所有系统的调试数据 + */ + pub fn collect_system_data(&mut self) -> Vec { + // TODO: 从实际的SystemManager中获取数据 + // 这里是示例数据 + + let system_names = vec!["RenderSystem", "PhysicsSystem", "InputSystem", "AudioSystem"]; + + for (i, name) in system_names.iter().enumerate() { + let execution_time = 1.0 + (i as f64 * 0.5); // 模拟执行时间 + + let system_info = DebugSystemInfo { + name: name.to_string(), + enabled: true, + priority: i as i32, + execution_time_ms: execution_time, + entity_count: (i + 1) * 10, + update_frequency: 60.0, + last_execution: current_timestamp(), + total_executions: 1000 + (i as u64 * 100), + }; + + self.system_stats.insert(name.to_string(), system_info); + self.update_execution_history(name, execution_time); + } + + self.system_stats.values().cloned().collect() + } + + /** + * 记录系统执行时间 + */ + pub fn record_system_execution(&mut self, system_name: &str, execution_time_ms: f64) { + self.update_execution_history(system_name, execution_time_ms); + + // 如果系统信息不存在,创建一个默认的 + let system_info = self.system_stats.entry(system_name.to_string()).or_insert_with(|| { + DebugSystemInfo { + name: system_name.to_string(), + enabled: true, + priority: 0, + execution_time_ms: 0.0, + entity_count: 0, + update_frequency: 60.0, + last_execution: 0, + total_executions: 0, + } + }); + + system_info.execution_time_ms = execution_time_ms; + system_info.last_execution = current_timestamp(); + system_info.total_executions += 1; + } + + /** + * 获取系统性能统计 + */ + pub fn get_system_performance(&self, system_name: &str) -> Option<(f64, f64, f64)> { + if let Some(history) = self.execution_history.get(system_name) { + if history.is_empty() { + return None; + } + + let average = history.iter().sum::() / history.len() as f64; + let min = history.iter().cloned().fold(f64::INFINITY, f64::min); + let max = history.iter().cloned().fold(f64::NEG_INFINITY, f64::max); + + Some((average, min, max)) + } else { + None + } + } + + /** + * 更新执行历史 + */ + fn update_execution_history(&mut self, system_name: &str, execution_time: f64) { + let history = self.execution_history.entry(system_name.to_string()).or_insert_with(Vec::new); + + history.push(execution_time); + + // 保持历史大小限制 + if history.len() > self.history_size { + history.remove(0); + } + } + + /** + * 获取最慢的系统 + */ + pub fn get_slowest_systems(&self, count: usize) -> Vec { + let mut systems: Vec<_> = self.system_stats.values().cloned().collect(); + systems.sort_by(|a, b| b.execution_time_ms.partial_cmp(&a.execution_time_ms).unwrap()); + systems.into_iter().take(count).collect() + } + + /** + * 清空统计数据 + */ + pub fn clear_stats(&mut self) { + self.system_stats.clear(); + self.execution_history.clear(); + } +} + +/** + * 组件数据收集器 + * 负责收集和格式化组件相关的调试信息 + */ +pub struct ComponentDataCollector { + component_stats: FxHashMap, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ComponentTypeStats { + pub type_name: String, + pub instance_count: usize, + pub total_memory: usize, + pub average_memory: usize, + pub enabled_count: usize, +} + +impl ComponentDataCollector { + /** + * 创建新的组件数据收集器 + */ + pub fn new() -> Self { + Self { + component_stats: FxHashMap::default(), + } + } + + /** + * 收集组件类型统计 + */ + pub fn collect_component_stats(&mut self) -> Vec { + self.component_stats.clear(); + + // TODO: 从实际的ComponentRegistry中获取数据 + // 这里是示例数据 + + let component_types = vec![ + ("Transform", 100, 48), + ("Renderer", 50, 128), + ("Physics", 30, 256), + ("Audio", 20, 64), + ]; + + for (type_name, count, memory_per_instance) in component_types { + let stats = ComponentTypeStats { + type_name: type_name.to_string(), + instance_count: count, + total_memory: count * memory_per_instance, + average_memory: memory_per_instance, + enabled_count: count - (count / 10), // 90%启用 + }; + + self.component_stats.insert(type_name.to_string(), stats); + } + + self.component_stats.values().cloned().collect() + } + + /** + * 获取指定类型的组件统计 + */ + pub fn get_component_type_stats(&self, type_name: &str) -> Option { + self.component_stats.get(type_name).cloned() + } + + /** + * 计算总内存使用 + */ + pub fn get_total_component_memory(&self) -> usize { + self.component_stats.values().map(|s| s.total_memory).sum() + } + + /** + * 获取最消耗内存的组件类型 + */ + pub fn get_memory_intensive_components(&self, count: usize) -> Vec { + let mut components: Vec<_> = self.component_stats.values().cloned().collect(); + components.sort_by(|a, b| b.total_memory.cmp(&a.total_memory)); + components.into_iter().take(count).collect() + } +} + +/** + * 性能数据收集器 + * 负责收集和格式化性能相关的调试信息 + */ +pub struct PerformanceDataCollector { + frame_times: Vec, + fps_history: Vec, + warnings: Vec, + max_history_size: usize, +} + +impl PerformanceDataCollector { + /** + * 创建新的性能数据收集器 + */ + pub fn new() -> Self { + Self { + frame_times: Vec::new(), + fps_history: Vec::new(), + warnings: Vec::new(), + max_history_size: 60, + } + } + + /** + * 记录帧时间 + */ + pub fn record_frame_time(&mut self, frame_time_ms: f64) { + self.frame_times.push(frame_time_ms); + + if self.frame_times.len() > self.max_history_size { + self.frame_times.remove(0); + } + + // 计算FPS + if frame_time_ms > 0.0 { + let fps = 1000.0 / frame_time_ms; + self.fps_history.push(fps); + + if self.fps_history.len() > self.max_history_size { + self.fps_history.remove(0); + } + } + + // 检查性能警告 + self.check_performance_warnings(frame_time_ms); + } + + /** + * 获取性能信息 + */ + pub fn get_performance_info(&self) -> DebugPerformanceInfo { + let current_fps = self.fps_history.last().copied().unwrap_or(0.0); + let current_frame_time = self.frame_times.last().copied().unwrap_or(0.0); + + DebugPerformanceInfo { + fps: current_fps, + frame_time_ms: current_frame_time, + delta_time_ms: current_frame_time, + memory_usage_bytes: self.estimate_memory_usage(), + total_entities: 0, // TODO: 从EntityManager获取 + total_systems: 0, // TODO: 从SystemManager获取 + total_components: 0, // TODO: 从ComponentRegistry获取 + warnings: self.warnings.clone(), + } + } + + /** + * 添加警告 + */ + pub fn add_warning(&mut self, level: WarningLevel, message: String, source: String) { + let warning = DebugWarning { + level, + message, + timestamp: current_timestamp(), + source, + }; + + self.warnings.push(warning); + + // 限制警告数量 + if self.warnings.len() > 100 { + self.warnings.remove(0); + } + } + + /** + * 获取平均FPS + */ + pub fn get_average_fps(&self) -> f64 { + if self.fps_history.is_empty() { + 0.0 + } else { + self.fps_history.iter().sum::() / self.fps_history.len() as f64 + } + } + + /** + * 检查性能警告 + */ + fn check_performance_warnings(&mut self, frame_time_ms: f64) { + // 低FPS警告 + if frame_time_ms > 33.33 { // 低于30FPS + self.add_warning( + WarningLevel::Warning, + format!("低FPS检测: {:.1}ms (约{:.1} FPS)", frame_time_ms, 1000.0 / frame_time_ms), + "PerformanceMonitor".to_string(), + ); + } + + // 严重性能问题 + if frame_time_ms > 66.66 { // 低于15FPS + self.add_warning( + WarningLevel::Error, + format!("严重性能问题: {:.1}ms (约{:.1} FPS)", frame_time_ms, 1000.0 / frame_time_ms), + "PerformanceMonitor".to_string(), + ); + } + } + + /** + * 估算内存使用 + */ + fn estimate_memory_usage(&self) -> usize { + // 简单的内存使用估算 + let base_memory = 1024 * 1024; // 1MB基础内存 + let history_memory = (self.frame_times.len() + self.fps_history.len()) * 8; // 每个f64 8字节 + let warnings_memory = self.warnings.len() * 256; // 每个警告估算256字节 + + base_memory + history_memory + warnings_memory + } + + /** + * 清空历史数据 + */ + pub fn clear_history(&mut self) { + self.frame_times.clear(); + self.fps_history.clear(); + self.warnings.clear(); + } +} + +/** + * 调试管理器 + * 整合所有调试数据收集器 + */ +pub struct DebugManager { + entity_collector: EntityDataCollector, + system_collector: SystemDataCollector, + component_collector: ComponentDataCollector, + performance_collector: PerformanceDataCollector, + enabled: bool, +} + +impl DebugManager { + /** + * 创建新的调试管理器 + */ + pub fn new() -> Self { + Self { + entity_collector: EntityDataCollector::new(), + system_collector: SystemDataCollector::new(), + component_collector: ComponentDataCollector::new(), + performance_collector: PerformanceDataCollector::new(), + enabled: false, + } + } + + /** + * 启用调试模式 + */ + pub fn enable(&mut self) { + self.enabled = true; + } + + /** + * 禁用调试模式 + */ + pub fn disable(&mut self) { + self.enabled = false; + } + + /** + * 检查调试模式是否启用 + */ + pub fn is_enabled(&self) -> bool { + self.enabled + } + + /** + * 更新调试数据(每帧调用) + */ + pub fn update(&mut self, delta_time_ms: f64) { + if !self.enabled { + return; + } + + // 记录性能数据 + self.performance_collector.record_frame_time(delta_time_ms); + } + + /** + * 获取所有调试数据 + */ + pub fn get_debug_data(&mut self) -> DebugData { + if !self.enabled { + return DebugData::empty(); + } + + DebugData { + entities: self.entity_collector.collect_entity_data(), + systems: self.system_collector.collect_system_data(), + components: self.component_collector.collect_component_stats(), + performance: self.performance_collector.get_performance_info(), + stats: self.calculate_debug_stats(), + } + } + + /** + * 获取实体数据收集器的可变引用 + */ + pub fn get_entity_collector_mut(&mut self) -> &mut EntityDataCollector { + &mut self.entity_collector + } + + /** + * 获取系统数据收集器的可变引用 + */ + pub fn get_system_collector_mut(&mut self) -> &mut SystemDataCollector { + &mut self.system_collector + } + + /** + * 获取组件数据收集器的可变引用 + */ + pub fn get_component_collector_mut(&mut self) -> &mut ComponentDataCollector { + &mut self.component_collector + } + + /** + * 获取性能数据收集器的可变引用 + */ + pub fn get_performance_collector_mut(&mut self) -> &mut PerformanceDataCollector { + &mut self.performance_collector + } + + /** + * 记录系统执行 + */ + pub fn record_system_execution(&mut self, system_name: &str, execution_time_ms: f64) { + if self.enabled { + self.system_collector.record_system_execution(system_name, execution_time_ms); + } + } + + /** + * 添加性能警告 + */ + pub fn add_warning(&mut self, level: WarningLevel, message: String, source: String) { + if self.enabled { + self.performance_collector.add_warning(level, message, source); + } + } + + /** + * 计算调试统计信息 + */ + fn calculate_debug_stats(&self) -> DebugStats { + let entity_memory = self.entity_collector.entity_cache.len() * 64; // 估算 + let component_memory = self.component_collector.get_total_component_memory(); + let system_memory = self.system_collector.system_stats.len() * 256; // 估算 + let performance_memory = self.performance_collector.estimate_memory_usage(); + + DebugStats { + total_memory: entity_memory + component_memory + system_memory + performance_memory, + entity_memory, + component_memory, + system_memory, + pool_memory: 0, // TODO: 从PoolManager获取 + } + } + + /** + * 清空所有调试数据 + */ + pub fn clear_all_data(&mut self) { + self.entity_collector.clear_cache(); + self.system_collector.clear_stats(); + self.performance_collector.clear_history(); + } + + /** + * 获取调试统计的格式化字符串 + */ + pub fn get_debug_stats_string(&mut self) -> String { + if !self.enabled { + return "Debug mode disabled".to_string(); + } + + let data = self.get_debug_data(); + let mut lines = vec![ + "=== ECS Debug Statistics ===".to_string(), + "".to_string(), + ]; + + // 性能信息 + lines.push(format!("Performance:")); + lines.push(format!(" FPS: {:.1}", data.performance.fps)); + lines.push(format!(" Frame Time: {:.2}ms", data.performance.frame_time_ms)); + lines.push(format!(" Memory: {:.1} KB", data.stats.total_memory as f64 / 1024.0)); + lines.push("".to_string()); + + // 实体信息 + lines.push(format!("Entities: {}", data.entities.len())); + let active_entities = data.entities.iter().filter(|e| e.enabled).count(); + lines.push(format!(" Active: {}", active_entities)); + lines.push(format!(" Entity Memory: {:.1} KB", data.stats.entity_memory as f64 / 1024.0)); + lines.push("".to_string()); + + // 系统信息 + lines.push(format!("Systems: {}", data.systems.len())); + let enabled_systems = data.systems.iter().filter(|s| s.enabled).count(); + lines.push(format!(" Enabled: {}", enabled_systems)); + if let Some(slowest) = data.systems.iter().max_by(|a, b| a.execution_time_ms.partial_cmp(&b.execution_time_ms).unwrap()) { + lines.push(format!(" Slowest: {} ({:.2}ms)", slowest.name, slowest.execution_time_ms)); + } + lines.push("".to_string()); + + // 组件信息 + lines.push(format!("Components: {} types", data.components.len())); + lines.push(format!(" Component Memory: {:.1} KB", data.stats.component_memory as f64 / 1024.0)); + lines.push("".to_string()); + + // 警告信息 + let warning_count = data.performance.warnings.len(); + if warning_count > 0 { + lines.push(format!("Warnings: {}", warning_count)); + for warning in data.performance.warnings.iter().take(3) { + lines.push(format!(" [{:?}] {}", warning.level, warning.message)); + } + if warning_count > 3 { + lines.push(format!(" ... and {} more", warning_count - 3)); + } + } + + lines.join("\n") + } +} + +/** + * 完整的调试数据结构 + */ +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DebugData { + pub entities: Vec, + pub systems: Vec, + pub components: Vec, + pub performance: DebugPerformanceInfo, + pub stats: DebugStats, +} + +impl DebugData { + /** + * 创建空的调试数据 + */ + pub fn empty() -> Self { + Self { + entities: Vec::new(), + systems: Vec::new(), + components: Vec::new(), + performance: DebugPerformanceInfo { + fps: 0.0, + frame_time_ms: 0.0, + delta_time_ms: 0.0, + memory_usage_bytes: 0, + total_entities: 0, + total_systems: 0, + total_components: 0, + warnings: Vec::new(), + }, + stats: DebugStats { + total_memory: 0, + entity_memory: 0, + component_memory: 0, + system_memory: 0, + pool_memory: 0, + }, + } + } +} + +impl Default for EntityDataCollector { + fn default() -> Self { + Self::new() + } +} + +impl Default for SystemDataCollector { + fn default() -> Self { + Self::new() + } +} + +impl Default for ComponentDataCollector { + fn default() -> Self { + Self::new() + } +} + +impl Default for PerformanceDataCollector { + fn default() -> Self { + Self::new() + } +} + +impl Default for DebugManager { + fn default() -> Self { + Self::new() + } +} + +// 辅助函数 +fn current_timestamp() -> u64 { + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap_or_default() + .as_millis() as u64 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_entity_data_collector_creation() { + let collector = EntityDataCollector::new(); + assert_eq!(collector.entity_cache.len(), 0); + assert_eq!(collector.last_update_time, 0); + assert_eq!(collector.cache_duration, 1000); + } + + #[test] + fn test_entity_data_collection() { + let mut collector = EntityDataCollector::new(); + let entities = collector.collect_entity_data(); + + assert!(!entities.is_empty()); + let (total, active) = collector.get_entity_count_stats(); + assert_eq!(total, entities.len()); + assert!(active <= total); + } + + #[test] + fn test_system_data_collector_creation() { + let collector = SystemDataCollector::new(); + assert_eq!(collector.system_stats.len(), 0); + assert_eq!(collector.execution_history.len(), 0); + assert_eq!(collector.history_size, 60); + } + + #[test] + fn test_system_data_collection() { + let mut collector = SystemDataCollector::new(); + let systems = collector.collect_system_data(); + + assert!(!systems.is_empty()); + + // 测试性能记录 + collector.record_system_execution("TestSystem", 5.5); + let performance = collector.get_system_performance("TestSystem"); + assert!(performance.is_some()); + } + + #[test] + fn test_component_data_collector() { + let mut collector = ComponentDataCollector::new(); + let components = collector.collect_component_stats(); + + assert!(!components.is_empty()); + + let total_memory = collector.get_total_component_memory(); + assert!(total_memory > 0); + + let memory_intensive = collector.get_memory_intensive_components(2); + assert!(memory_intensive.len() <= 2); + } + + #[test] + fn test_performance_data_collector() { + let mut collector = PerformanceDataCollector::new(); + + // 记录一些帧时间 + collector.record_frame_time(16.67); // 60 FPS + collector.record_frame_time(33.33); // 30 FPS + collector.record_frame_time(50.0); // 20 FPS + + let performance_info = collector.get_performance_info(); + assert!(performance_info.fps > 0.0); + assert!(performance_info.frame_time_ms > 0.0); + + let avg_fps = collector.get_average_fps(); + assert!(avg_fps > 0.0); + + // 应该有性能警告 + assert!(!performance_info.warnings.is_empty()); + } + + #[test] + fn test_debug_manager() { + let mut manager = DebugManager::new(); + assert!(!manager.enabled()); + + manager.enable(); + assert!(manager.enabled()); + + // 更新调试数据 + manager.update(16.67); + + let debug_data = manager.get_debug_data(); + assert!(!debug_data.entities.is_empty()); + assert!(!debug_data.systems.is_empty()); + + // 记录系统执行 + manager.record_system_execution("TestSystem", 2.5); + + // 添加警告 + manager.add_warning( + WarningLevel::Warning, + "Test warning".to_string(), + "TestModule".to_string(), + ); + + let stats_string = manager.get_debug_stats_string(); + assert!(stats_string.contains("ECS Debug Statistics")); + + manager.clear_all_data(); + manager.disable(); + assert!(!manager.enabled()); + } + + #[test] + fn test_debug_data_serialization() { + let debug_data = DebugData::empty(); + + // 测试序列化 + let json = serde_json::to_string(&debug_data); + assert!(json.is_ok()); + + // 测试反序列化 + let json_str = json.unwrap(); + let deserialized: Result = serde_json::from_str(&json_str); + assert!(deserialized.is_ok()); + } + + #[test] + fn test_warning_levels() { + let mut collector = PerformanceDataCollector::new(); + + collector.add_warning( + WarningLevel::Info, + "Info message".to_string(), + "Test".to_string(), + ); + + collector.add_warning( + WarningLevel::Warning, + "Warning message".to_string(), + "Test".to_string(), + ); + + collector.add_warning( + WarningLevel::Error, + "Error message".to_string(), + "Test".to_string(), + ); + + let performance_info = collector.get_performance_info(); + assert_eq!(performance_info.warnings.len(), 3); + + let warning_levels: Vec<_> = performance_info.warnings.iter().map(|w| w.level).collect(); + assert!(warning_levels.contains(&WarningLevel::Info)); + assert!(warning_levels.contains(&WarningLevel::Warning)); + assert!(warning_levels.contains(&WarningLevel::Error)); + } + + #[test] + fn test_memory_calculations() { + let mut collector = EntityDataCollector::new(); + let entities = collector.collect_entity_data(); + + for entity in &entities { + let memory = collector.calculate_entity_memory_usage(entity.entity_id); + assert!(memory > 0); + assert_eq!(memory, entity.memory_usage); + } + } + + #[test] + fn test_system_performance_tracking() { + let mut collector = SystemDataCollector::new(); + let system_name = "TestSystem"; + + // 记录多次执行时间 + let execution_times = vec![1.0, 2.0, 3.0, 4.0, 5.0]; + for time in &execution_times { + collector.record_system_execution(system_name, *time); + } + + let performance = collector.get_system_performance(system_name); + assert!(performance.is_some()); + + let (avg, min, max) = performance.unwrap(); + assert_eq!(avg, 3.0); // 平均值 + assert_eq!(min, 1.0); // 最小值 + assert_eq!(max, 5.0); // 最大值 + + let slowest = collector.get_slowest_systems(1); + assert_eq!(slowest.len(), 1); + assert_eq!(slowest[0].name, system_name); + assert_eq!(slowest[0].execution_time_ms, 5.0); + } + + #[test] + fn test_cache_behavior() { + let mut collector = EntityDataCollector::new(); + + // 第一次收集数据 + let entities1 = collector.collect_entity_data(); + let cache_time1 = collector.last_update_time; + + // 立即再次收集,应该使用缓存 + let entities2 = collector.collect_entity_data(); + let cache_time2 = collector.last_update_time; + + assert_eq!(cache_time1, cache_time2); // 缓存时间应该相同 + assert_eq!(entities1.len(), entities2.len()); + + // 清空缓存后再次收集 + collector.clear_cache(); + // 添加微小延迟确保时间戳不同 + std::thread::sleep(std::time::Duration::from_millis(1)); + let _entities3 = collector.collect_entity_data(); + let cache_time3 = collector.last_update_time; + + assert!(cache_time3 >= cache_time2); // 应该更新缓存时间(使用>=避免时间精度问题) + } +} \ No newline at end of file diff --git a/packages/core-rust/src/utils/dirty_tracking.rs b/packages/core-rust/src/utils/dirty_tracking.rs new file mode 100644 index 00000000..e2bffdcb --- /dev/null +++ b/packages/core-rust/src/utils/dirty_tracking.rs @@ -0,0 +1,896 @@ +use crate::utils::ComponentType; +use rustc_hash::FxHashMap; +use std::collections::HashSet; + +/** + * 脏标记类型 + * 使用位标记来表示不同类型的变更 + */ +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct DirtyFlag(pub u32); + +impl DirtyFlag { + /// 组件数据已修改 + pub const COMPONENT_MODIFIED: DirtyFlag = DirtyFlag(1 << 0); + /// 组件已添加 + pub const COMPONENT_ADDED: DirtyFlag = DirtyFlag(1 << 1); + /// 组件已移除 + pub const COMPONENT_REMOVED: DirtyFlag = DirtyFlag(1 << 2); + /// 实体位置已改变 + pub const TRANSFORM_CHANGED: DirtyFlag = DirtyFlag(1 << 3); + /// 实体状态已改变 + pub const STATE_CHANGED: DirtyFlag = DirtyFlag(1 << 4); + /// 实体层次结构已改变 + pub const HIERARCHY_CHANGED: DirtyFlag = DirtyFlag(1 << 5); + /// 实体可见性已改变 + pub const VISIBILITY_CHANGED: DirtyFlag = DirtyFlag(1 << 6); + /// 实体启用状态已改变 + pub const ENABLED_CHANGED: DirtyFlag = DirtyFlag(1 << 7); + /// 自定义标记1 + pub const CUSTOM_1: DirtyFlag = DirtyFlag(1 << 8); + /// 自定义标记2 + pub const CUSTOM_2: DirtyFlag = DirtyFlag(1 << 9); + /// 自定义标记3 + pub const CUSTOM_3: DirtyFlag = DirtyFlag(1 << 10); + /// 自定义标记4 + pub const CUSTOM_4: DirtyFlag = DirtyFlag(1 << 11); + /// 所有标记 + pub const ALL: DirtyFlag = DirtyFlag(0xFFFFFFFF); + + /** + * 检查是否包含指定标记 + */ + pub fn contains(self, other: DirtyFlag) -> bool { + (self.0 & other.0) != 0 + } + + /** + * 添加标记 + */ + pub fn add(&mut self, other: DirtyFlag) { + self.0 |= other.0; + } + + /** + * 移除标记 + */ + pub fn remove(&mut self, other: DirtyFlag) { + self.0 &= !other.0; + } + + /** + * 清空所有标记 + */ + pub fn clear(&mut self) { + self.0 = 0; + } + + /** + * 检查是否为空 + */ + pub fn is_empty(self) -> bool { + self.0 == 0 + } + + /** + * 与操作 + */ + pub fn and(self, other: DirtyFlag) -> DirtyFlag { + DirtyFlag(self.0 & other.0) + } + + /** + * 或操作 + */ + pub fn or(self, other: DirtyFlag) -> DirtyFlag { + DirtyFlag(self.0 | other.0) + } +} + +impl std::ops::BitOr for DirtyFlag { + type Output = Self; + + fn bitor(self, rhs: Self) -> Self::Output { + DirtyFlag(self.0 | rhs.0) + } +} + +impl std::ops::BitAnd for DirtyFlag { + type Output = Self; + + fn bitand(self, rhs: Self) -> Self::Output { + DirtyFlag(self.0 & rhs.0) + } +} + +impl std::ops::BitOrAssign for DirtyFlag { + fn bitor_assign(&mut self, rhs: Self) { + self.0 |= rhs.0; + } +} + +impl std::ops::BitAndAssign for DirtyFlag { + fn bitand_assign(&mut self, rhs: Self) { + self.0 &= rhs.0; + } +} + +/** + * 脏标记数据 + * 记录实体的变更信息 + */ +#[derive(Debug, Clone)] +pub struct DirtyData { + /// 实体ID + pub entity_id: u32, + /// 脏标记位 + pub flags: DirtyFlag, + /// 修改的组件类型列表 + pub modified_components: HashSet, + /// 标记时间戳(毫秒) + pub timestamp: u64, + /// 帧编号 + pub frame_number: u64, +} + +impl DirtyData { + /** + * 创建新的脏标记数据 + */ + pub fn new(entity_id: u32, flags: DirtyFlag, frame_number: u64) -> Self { + Self { + entity_id, + flags, + modified_components: HashSet::new(), + timestamp: current_timestamp(), + frame_number, + } + } + + /** + * 添加修改的组件类型 + */ + pub fn add_modified_component(&mut self, component_type: ComponentType) { + self.modified_components.insert(component_type); + } + + /** + * 检查是否包含指定的脏标记 + */ + pub fn has_flags(&self, flags: DirtyFlag) -> bool { + self.flags.contains(flags) + } + + /** + * 更新时间戳 + */ + pub fn update_timestamp(&mut self) { + self.timestamp = current_timestamp(); + } + + /** + * 获取年龄(当前时间与标记时间的差值,毫秒) + */ + pub fn age(&self) -> u64 { + current_timestamp().saturating_sub(self.timestamp) + } +} + +/** + * 脏标记监听器类型 + */ +pub type DirtyListener = Box; + +/** + * 脏标记监听器配置 + */ +#[derive(Debug)] +pub struct DirtyListenerConfig { + /// 感兴趣的标记类型 + pub flags: DirtyFlag, + /// 监听器优先级(数字越小优先级越高) + pub priority: i32, + /// 监听器ID(用于移除) + pub id: u64, +} + +/** + * 脏标记监听器条目 + */ +pub struct DirtyListenerEntry { + pub config: DirtyListenerConfig, + pub callback: DirtyListener, +} + +/** + * 脏标记统计信息 + */ +#[derive(Debug, Clone)] +pub struct DirtyTrackingStats { + /// 当前脏实体数量 + pub dirty_entity_count: usize, + /// 总标记次数 + pub total_markings: u64, + /// 总清理次数 + pub total_cleanups: u64, + /// 监听器数量 + pub listener_count: usize, + /// 当前帧编号 + pub current_frame: u64, + /// 平均每帧脏实体数量 + pub avg_dirty_per_frame: f64, + /// 处理的实体总数 + pub total_processed_entities: u64, + /// 内存使用量估算(字节) + pub estimated_memory_usage: usize, + /// 最大处理时间(毫秒) + pub max_processing_time: f64, + /// 平均处理时间(毫秒) + pub avg_processing_time: f64, +} + +impl Default for DirtyTrackingStats { + fn default() -> Self { + Self { + dirty_entity_count: 0, + total_markings: 0, + total_cleanups: 0, + listener_count: 0, + current_frame: 0, + avg_dirty_per_frame: 0.0, + total_processed_entities: 0, + estimated_memory_usage: 0, + max_processing_time: 0.0, + avg_processing_time: 0.0, + } + } +} + +/** + * 脏标记追踪系统 + * + * 提供高效的组件和实体变更追踪,避免不必要的计算和更新。 + * 支持细粒度的脏标记和批量处理机制。 + */ +pub struct DirtyTrackingSystem { + /// 脏实体映射表 + dirty_entities: FxHashMap, + /// 脏标记监听器 + listeners: Vec, + /// 下一个监听器ID + next_listener_id: u64, + /// 当前帧编号 + current_frame: u64, + /// 批处理配置 + batch_size: usize, + max_processing_time_ms: f64, + /// 处理队列 + processing_queue: Vec, + is_processing: bool, + /// 统计信息 + stats: DirtyTrackingStats, + /// 帧统计累积 + frame_stats: FrameStats, + /// 处理时间记录 + processing_times: Vec, + max_processing_time_history: usize, +} + +/** + * 帧统计信息累积 + */ +#[derive(Debug, Default)] +struct FrameStats { + total_dirty_entities: u64, + frame_count: u64, + total_processing_time: f64, +} + +impl DirtyTrackingSystem { + /** + * 创建新的脏标记追踪系统 + */ + pub fn new() -> Self { + Self { + dirty_entities: FxHashMap::default(), + listeners: Vec::new(), + next_listener_id: 1, + current_frame: 0, + batch_size: 100, + max_processing_time_ms: 16.0, + processing_queue: Vec::new(), + is_processing: false, + stats: DirtyTrackingStats::default(), + frame_stats: FrameStats::default(), + processing_times: Vec::new(), + max_processing_time_history: 100, + } + } + + /** + * 标记实体为脏状态 + */ + pub fn mark_dirty( + &mut self, + entity_id: u32, + flags: DirtyFlag, + modified_components: Option> + ) { + self.stats.total_markings += 1; + + let dirty_data = self.dirty_entities.entry(entity_id).or_insert_with(|| { + DirtyData::new(entity_id, DirtyFlag(0), self.current_frame) + }); + + dirty_data.flags |= flags; + dirty_data.update_timestamp(); + dirty_data.frame_number = self.current_frame; + + if let Some(components) = modified_components { + for component_type in components { + dirty_data.add_modified_component(component_type); + } + } + + // 克隆dirty_data以避免借用冲突 + let dirty_data_for_notify = dirty_data.clone(); + + // 立即通知监听器 + self.notify_listeners(&dirty_data_for_notify, flags); + } + + /** + * 检查实体是否有指定的脏标记 + */ + pub fn is_dirty(&self, entity_id: u32, flags: DirtyFlag) -> bool { + self.dirty_entities + .get(&entity_id) + .map(|data| data.has_flags(flags)) + .unwrap_or(false) + } + + /** + * 清除实体的脏标记 + */ + pub fn clear_dirty(&mut self, entity_id: u32, flags: DirtyFlag) { + if let Some(dirty_data) = self.dirty_entities.get_mut(&entity_id) { + dirty_data.flags.remove(flags); + + if dirty_data.flags.is_empty() { + self.dirty_entities.remove(&entity_id); + } + + self.stats.total_cleanups += 1; + } + } + + /** + * 清除所有脏标记 + */ + pub fn clear_all_dirty(&mut self) { + let count = self.dirty_entities.len(); + self.dirty_entities.clear(); + self.stats.total_cleanups += count as u64; + } + + /** + * 获取所有脏实体 + */ + pub fn get_dirty_entities(&self, flags: DirtyFlag) -> Vec<&DirtyData> { + self.dirty_entities + .values() + .filter(|data| data.has_flags(flags)) + .collect() + } + + /** + * 获取脏实体数量 + */ + pub fn dirty_entity_count(&self) -> usize { + self.dirty_entities.len() + } + + /** + * 获取指定标记的脏实体数量 + */ + pub fn dirty_entity_count_with_flags(&self, flags: DirtyFlag) -> usize { + self.dirty_entities + .values() + .filter(|data| data.has_flags(flags)) + .count() + } + + /** + * 批量处理脏实体 + */ + pub fn process_dirty_entities(&mut self) { + if self.is_processing { + return; + } + + self.is_processing = true; + let start_time = current_timestamp_f64(); + + // 填充处理队列 + if self.processing_queue.is_empty() { + self.processing_queue.extend( + self.dirty_entities.values().cloned() + ); + } + + let mut processed = 0; + while !self.processing_queue.is_empty() && processed < self.batch_size { + let elapsed = current_timestamp_f64() - start_time; + if elapsed > self.max_processing_time_ms { + break; + } + + if let Some(dirty_data) = self.processing_queue.pop() { + self.process_entity(&dirty_data); + processed += 1; + } + } + + // 如果处理完成,更新统计信息 + if self.processing_queue.is_empty() { + self.is_processing = false; + + let processing_time = current_timestamp_f64() - start_time; + self.record_processing_time(processing_time); + self.stats.total_processed_entities += processed as u64; + } + } + + /** + * 添加脏标记监听器 + */ + pub fn add_listener(&mut self, flags: DirtyFlag, priority: i32, callback: F) -> u64 + where + F: Fn(&DirtyData) + Send + Sync + 'static, + { + let listener_id = self.next_listener_id; + self.next_listener_id += 1; + + let config = DirtyListenerConfig { + flags, + priority, + id: listener_id, + }; + + let entry = DirtyListenerEntry { + config, + callback: Box::new(callback), + }; + + self.listeners.push(entry); + + // 按优先级排序 + self.listeners.sort_by_key(|entry| entry.config.priority); + + listener_id + } + + /** + * 移除脏标记监听器 + */ + pub fn remove_listener(&mut self, listener_id: u64) -> bool { + if let Some(pos) = self.listeners.iter().position(|entry| entry.config.id == listener_id) { + self.listeners.remove(pos); + true + } else { + false + } + } + + /** + * 开始新的帧 + */ + pub fn begin_frame(&mut self) { + self.current_frame += 1; + self.stats.current_frame = self.current_frame; + } + + /** + * 结束当前帧 + */ + pub fn end_frame(&mut self) { + if !self.is_processing { + self.process_dirty_entities(); + } + + // 更新帧统计 + self.frame_stats.total_dirty_entities += self.dirty_entities.len() as u64; + self.frame_stats.frame_count += 1; + + // 更新平均值 + if self.frame_stats.frame_count > 0 { + self.stats.avg_dirty_per_frame = + self.frame_stats.total_dirty_entities as f64 / self.frame_stats.frame_count as f64; + } + } + + /** + * 获取统计信息 + */ + pub fn get_stats(&self) -> DirtyTrackingStats { + let mut stats = self.stats.clone(); + stats.dirty_entity_count = self.dirty_entities.len(); + stats.listener_count = self.listeners.len(); + stats.estimated_memory_usage = self.estimate_memory_usage(); + + // 计算平均处理时间 + if !self.processing_times.is_empty() { + let total_time: f64 = self.processing_times.iter().sum(); + stats.avg_processing_time = total_time / self.processing_times.len() as f64; + } + + stats + } + + /** + * 配置批量处理参数 + */ + pub fn configure_batch_processing(&mut self, batch_size: usize, max_processing_time_ms: f64) { + self.batch_size = batch_size; + self.max_processing_time_ms = max_processing_time_ms; + } + + /** + * 清空所有数据 + */ + pub fn clear(&mut self) { + self.dirty_entities.clear(); + self.processing_queue.clear(); + self.is_processing = false; + self.stats = DirtyTrackingStats::default(); + self.frame_stats = FrameStats::default(); + self.processing_times.clear(); + } + + /** + * 获取老旧的脏标记(超过指定时间未更新) + */ + pub fn get_stale_dirty_entities(&self, max_age_ms: u64) -> Vec<&DirtyData> { + self.dirty_entities + .values() + .filter(|data| data.age() > max_age_ms) + .collect() + } + + /** + * 清理老旧的脏标记 + */ + pub fn cleanup_stale_dirty_entities(&mut self, max_age_ms: u64) -> usize { + let initial_count = self.dirty_entities.len(); + + self.dirty_entities.retain(|_, data| data.age() <= max_age_ms); + + let removed_count = initial_count - self.dirty_entities.len(); + self.stats.total_cleanups += removed_count as u64; + + removed_count + } + + // 私有方法 + + /** + * 处理单个脏实体 + */ + fn process_entity(&mut self, dirty_data: &DirtyData) { + for entry in &self.listeners { + if dirty_data.has_flags(entry.config.flags) { + (entry.callback)(dirty_data); + } + } + + // 处理后清理 + self.clear_dirty(dirty_data.entity_id, DirtyFlag::ALL); + } + + /** + * 通知监听器 + */ + fn notify_listeners(&self, dirty_data: &DirtyData, new_flags: DirtyFlag) { + for entry in &self.listeners { + if new_flags.contains(entry.config.flags) { + (entry.callback)(dirty_data); + } + } + } + + /** + * 记录处理时间 + */ + fn record_processing_time(&mut self, time: f64) { + self.processing_times.push(time); + + // 保持历史记录长度限制 + if self.processing_times.len() > self.max_processing_time_history { + self.processing_times.remove(0); + } + + // 更新最大处理时间 + if time > self.stats.max_processing_time { + self.stats.max_processing_time = time; + } + + self.frame_stats.total_processing_time += time; + } + + /** + * 估算内存使用量 + */ + fn estimate_memory_usage(&self) -> usize { + let dirty_entities_size = self.dirty_entities.len() * + (std::mem::size_of::() + std::mem::size_of::()); + + let listeners_size = self.listeners.len() * std::mem::size_of::(); + + let processing_queue_size = self.processing_queue.len() * std::mem::size_of::(); + + let processing_times_size = self.processing_times.len() * std::mem::size_of::(); + + dirty_entities_size + listeners_size + processing_queue_size + processing_times_size + } +} + +impl Default for DirtyTrackingSystem { + fn default() -> Self { + Self::new() + } +} + +// 辅助函数 + +/** + * 获取当前时间戳(毫秒) + */ +fn current_timestamp() -> u64 { + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap_or_default() + .as_millis() as u64 +} + +/** + * 获取当前时间戳(浮点毫秒,用于精确计时) + */ +fn current_timestamp_f64() -> f64 { + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap_or_default() + .as_secs_f64() * 1000.0 +} + +#[cfg(test)] +mod tests { + use super::*; + use std::any::TypeId; + use std::sync::{Arc, Mutex}; + + #[test] + fn test_dirty_flag_operations() { + let mut flags = DirtyFlag::COMPONENT_MODIFIED; + + assert!(flags.contains(DirtyFlag::COMPONENT_MODIFIED)); + assert!(!flags.contains(DirtyFlag::COMPONENT_ADDED)); + + flags.add(DirtyFlag::COMPONENT_ADDED); + assert!(flags.contains(DirtyFlag::COMPONENT_MODIFIED)); + assert!(flags.contains(DirtyFlag::COMPONENT_ADDED)); + + flags.remove(DirtyFlag::COMPONENT_MODIFIED); + assert!(!flags.contains(DirtyFlag::COMPONENT_MODIFIED)); + assert!(flags.contains(DirtyFlag::COMPONENT_ADDED)); + + flags.clear(); + assert!(flags.is_empty()); + } + + #[test] + fn test_dirty_flag_bitwise_operations() { + let flag1 = DirtyFlag::COMPONENT_MODIFIED; + let flag2 = DirtyFlag::COMPONENT_ADDED; + + let combined = flag1 | flag2; + assert!(combined.contains(DirtyFlag::COMPONENT_MODIFIED)); + assert!(combined.contains(DirtyFlag::COMPONENT_ADDED)); + + let intersection = combined & DirtyFlag::COMPONENT_MODIFIED; + assert!(intersection.contains(DirtyFlag::COMPONENT_MODIFIED)); + assert!(!intersection.contains(DirtyFlag::COMPONENT_ADDED)); + } + + #[test] + fn test_dirty_data_creation() { + let entity_id = 123; + let flags = DirtyFlag::TRANSFORM_CHANGED; + let frame_number = 42; + + let dirty_data = DirtyData::new(entity_id, flags, frame_number); + + assert_eq!(dirty_data.entity_id, entity_id); + assert!(dirty_data.has_flags(flags)); + assert_eq!(dirty_data.frame_number, frame_number); + assert!(dirty_data.modified_components.is_empty()); + } + + #[test] + fn test_dirty_data_component_tracking() { + let mut dirty_data = DirtyData::new(1, DirtyFlag::COMPONENT_MODIFIED, 0); + let component_type = TypeId::of::(); + + dirty_data.add_modified_component(component_type); + assert!(dirty_data.modified_components.contains(&component_type)); + } + + #[test] + fn test_dirty_tracking_basic() { + let mut system = DirtyTrackingSystem::new(); + let entity_id = 1; + let flags = DirtyFlag::COMPONENT_MODIFIED; + + // 标记实体为脏状态 + system.mark_dirty(entity_id, flags, None); + + assert!(system.is_dirty(entity_id, flags)); + assert!(!system.is_dirty(entity_id, DirtyFlag::COMPONENT_ADDED)); + assert_eq!(system.dirty_entity_count(), 1); + + // 清除脏标记 + system.clear_dirty(entity_id, flags); + assert!(!system.is_dirty(entity_id, flags)); + assert_eq!(system.dirty_entity_count(), 0); + } + + #[test] + fn test_dirty_tracking_multiple_flags() { + let mut system = DirtyTrackingSystem::new(); + let entity_id = 1; + + // 标记多个类型的脏状态 + system.mark_dirty(entity_id, DirtyFlag::COMPONENT_MODIFIED, None); + system.mark_dirty(entity_id, DirtyFlag::TRANSFORM_CHANGED, None); + + assert!(system.is_dirty(entity_id, DirtyFlag::COMPONENT_MODIFIED)); + assert!(system.is_dirty(entity_id, DirtyFlag::TRANSFORM_CHANGED)); + assert!(system.is_dirty(entity_id, DirtyFlag::COMPONENT_MODIFIED | DirtyFlag::TRANSFORM_CHANGED)); + + // 部分清除 + system.clear_dirty(entity_id, DirtyFlag::COMPONENT_MODIFIED); + assert!(!system.is_dirty(entity_id, DirtyFlag::COMPONENT_MODIFIED)); + assert!(system.is_dirty(entity_id, DirtyFlag::TRANSFORM_CHANGED)); + + // 全部清除 + system.clear_dirty(entity_id, DirtyFlag::ALL); + assert!(!system.is_dirty(entity_id, DirtyFlag::TRANSFORM_CHANGED)); + } + + #[test] + fn test_dirty_tracking_listener() { + let mut system = DirtyTrackingSystem::new(); + let entity_id = 1; + + // 使用Arc来在闭包中共享状态 + let callback_count = Arc::new(Mutex::new(0)); + let callback_count_clone = Arc::clone(&callback_count); + + // 添加监听器 + let listener_id = system.add_listener( + DirtyFlag::COMPONENT_MODIFIED, + 0, + move |_data| { + *callback_count_clone.lock().unwrap() += 1; + } + ); + + // 标记脏状态应该触发监听器 + system.mark_dirty(entity_id, DirtyFlag::COMPONENT_MODIFIED, None); + assert_eq!(*callback_count.lock().unwrap(), 1); + + // 标记其他类型的脏状态不应该触发监听器 + system.mark_dirty(entity_id, DirtyFlag::TRANSFORM_CHANGED, None); + assert_eq!(*callback_count.lock().unwrap(), 1); + + // 移除监听器 + assert!(system.remove_listener(listener_id)); + + // 再次标记脏状态不应该触发监听器 + system.mark_dirty(entity_id, DirtyFlag::COMPONENT_MODIFIED, None); + assert_eq!(*callback_count.lock().unwrap(), 1); + } + + #[test] + fn test_dirty_tracking_filtering() { + let mut system = DirtyTrackingSystem::new(); + + system.mark_dirty(1, DirtyFlag::COMPONENT_MODIFIED, None); + system.mark_dirty(2, DirtyFlag::TRANSFORM_CHANGED, None); + system.mark_dirty(3, DirtyFlag::COMPONENT_MODIFIED | DirtyFlag::TRANSFORM_CHANGED, None); + + // 获取包含组件修改标记的实体 + let component_modified = system.get_dirty_entities(DirtyFlag::COMPONENT_MODIFIED); + assert_eq!(component_modified.len(), 2); // 实体1和3 + + // 获取包含变换修改标记的实体 + let transform_changed = system.get_dirty_entities(DirtyFlag::TRANSFORM_CHANGED); + assert_eq!(transform_changed.len(), 2); // 实体2和3 + + // 获取包含两种标记的实体 + let both_flags = system.get_dirty_entities(DirtyFlag::COMPONENT_MODIFIED | DirtyFlag::TRANSFORM_CHANGED); + assert_eq!(both_flags.len(), 3); // 所有实体 + } + + #[test] + fn test_dirty_tracking_stats() { + let mut system = DirtyTrackingSystem::new(); + + system.mark_dirty(1, DirtyFlag::COMPONENT_MODIFIED, None); + system.mark_dirty(2, DirtyFlag::TRANSFORM_CHANGED, None); + system.clear_dirty(1, DirtyFlag::ALL); + + let stats = system.get_stats(); + assert_eq!(stats.total_markings, 2); + assert_eq!(stats.total_cleanups, 1); + assert_eq!(stats.dirty_entity_count, 1); + } + + #[test] + fn test_dirty_tracking_stale_cleanup() { + let mut system = DirtyTrackingSystem::new(); + + system.mark_dirty(1, DirtyFlag::COMPONENT_MODIFIED, None); + system.mark_dirty(2, DirtyFlag::TRANSFORM_CHANGED, None); + + // 等待一小段时间让标记变老 + std::thread::sleep(std::time::Duration::from_millis(10)); + + // 清理超过5毫秒的老标记 + let removed_count = system.cleanup_stale_dirty_entities(5); + assert_eq!(removed_count, 2); + assert_eq!(system.dirty_entity_count(), 0); + } + + #[test] + fn test_dirty_tracking_frame_management() { + let mut system = DirtyTrackingSystem::new(); + + system.begin_frame(); + assert_eq!(system.get_stats().current_frame, 1); + + system.mark_dirty(1, DirtyFlag::COMPONENT_MODIFIED, None); + system.end_frame(); + + let stats = system.get_stats(); + assert_eq!(stats.current_frame, 1); + } + + #[test] + fn test_dirty_tracking_batch_configuration() { + let mut system = DirtyTrackingSystem::new(); + + system.configure_batch_processing(50, 8.0); + assert_eq!(system.batch_size, 50); + assert_eq!(system.max_processing_time_ms, 8.0); + } + + #[test] + fn test_dirty_tracking_clear() { + let mut system = DirtyTrackingSystem::new(); + + system.mark_dirty(1, DirtyFlag::COMPONENT_MODIFIED, None); + system.mark_dirty(2, DirtyFlag::TRANSFORM_CHANGED, None); + + let _listener_id = system.add_listener(DirtyFlag::ALL, 0, |_| {}); + + assert_eq!(system.dirty_entity_count(), 2); + assert_eq!(system.listeners.len(), 1); + + system.clear(); + + assert_eq!(system.dirty_entity_count(), 0); + // 注意:clear()不会清除监听器 + assert_eq!(system.listeners.len(), 1); + assert_eq!(system.get_stats().total_markings, 0); + } +} \ No newline at end of file diff --git a/packages/core-rust/src/utils/extensions.rs b/packages/core-rust/src/utils/extensions.rs new file mode 100644 index 00000000..538d2f19 --- /dev/null +++ b/packages/core-rust/src/utils/extensions.rs @@ -0,0 +1,818 @@ +use std::any::{Any, TypeId}; +use std::fmt::Debug; + +/** + * 数字扩展工具 + * 提供数字转换和处理的实用方法 + */ +pub struct NumberExtension; + +impl NumberExtension { + /** + * 将Option转换为数字,如果值为None则返回0 + */ + pub fn to_number_from_option(value: Option) -> f64 + where + T: Into, + { + value.map(|v| v.into()).unwrap_or(0.0) + } + + /** + * 将字符串转换为数字,如果解析失败则返回默认值 + */ + pub fn parse_or_default(value: &str, default: f64) -> f64 { + value.parse::().unwrap_or(default) + } + + /** + * 将字符串转换为数字,如果解析失败则返回0 + */ + pub fn parse_or_zero(value: &str) -> f64 { + Self::parse_or_default(value, 0.0) + } + + /** + * 将字符串转换为整数,如果解析失败则返回默认值 + */ + pub fn parse_int_or_default(value: &str, default: i64) -> i64 { + value.parse::().unwrap_or(default) + } + + /** + * 将字符串转换为整数,如果解析失败则返回0 + */ + pub fn parse_int_or_zero(value: &str) -> i64 { + Self::parse_int_or_default(value, 0) + } + + /** + * 将布尔值转换为数字 + */ + pub fn bool_to_number(value: bool) -> f64 { + if value { 1.0 } else { 0.0 } + } + + /** + * 将数字转换为布尔值 + */ + pub fn number_to_bool(value: f64) -> bool { + value != 0.0 + } + + /** + * 限制数字在指定范围内 + */ + pub fn clamp(value: f64, min: f64, max: f64) -> f64 { + if value < min { + min + } else if value > max { + max + } else { + value + } + } + + /** + * 检查数字是否在指定范围内 + */ + pub fn is_in_range(value: f64, min: f64, max: f64) -> bool { + value >= min && value <= max + } + + /** + * 四舍五入到指定小数位数 + */ + pub fn round_to_decimal_places(value: f64, decimal_places: u32) -> f64 { + let multiplier = 10_f64.powi(decimal_places as i32); + (value * multiplier).round() / multiplier + } + + /** + * 将弧度转换为角度 + */ + pub fn radians_to_degrees(radians: f64) -> f64 { + radians * 180.0 / std::f64::consts::PI + } + + /** + * 将角度转换为弧度 + */ + pub fn degrees_to_radians(degrees: f64) -> f64 { + degrees * std::f64::consts::PI / 180.0 + } + + /** + * 线性插值 + */ + pub fn lerp(from: f64, to: f64, t: f64) -> f64 { + from + (to - from) * t + } + + /** + * 反向线性插值,返回t值 + */ + pub fn inverse_lerp(from: f64, to: f64, value: f64) -> f64 { + if (to - from).abs() < f64::EPSILON { + 0.0 + } else { + (value - from) / (to - from) + } + } + + /** + * 计算两个数字之间的距离 + */ + pub fn distance(a: f64, b: f64) -> f64 { + (a - b).abs() + } + + /** + * 检查两个浮点数是否近似相等 + */ + pub fn approximately_equal(a: f64, b: f64, epsilon: Option) -> bool { + let eps = epsilon.unwrap_or(f64::EPSILON); + (a - b).abs() < eps + } + + /** + * 将值包装在0到max之间(循环) + */ + pub fn wrap(value: f64, max: f64) -> f64 { + if max <= 0.0 { + return 0.0; + } + + let mut result = value % max; + if result < 0.0 { + result += max; + } + result + } + + /** + * 计算数字的符号(-1, 0, 1) + */ + pub fn sign(value: f64) -> f64 { + if value > 0.0 { + 1.0 + } else if value < 0.0 { + -1.0 + } else { + 0.0 + } + } +} + +/** + * 类型工具 + * 提供类型相关的实用方法 + */ +pub struct TypeUtils; + +impl TypeUtils { + /** + * 获取类型的TypeId + */ + pub fn get_type_id() -> TypeId { + TypeId::of::() + } + + /** + * 获取对象的TypeId + */ + pub fn get_object_type_id(_obj: &T) -> TypeId { + TypeId::of::() + } + + /** + * 获取类型名称 + */ + pub fn get_type_name() -> &'static str { + std::any::type_name::() + } + + /** + * 获取对象的类型名称 + */ + pub fn get_object_type_name(_obj: &T) -> &'static str { + std::any::type_name::() + } + + /** + * 检查两个类型是否相同 + */ + pub fn is_same_type() -> bool { + TypeId::of::() == TypeId::of::() + } + + /** + * 检查对象是否为指定类型 + */ + pub fn is_type(_obj: &T) -> bool { + TypeId::of::() == TypeId::of::() + } + + /** + * 尝试将Any trait对象转换为具体类型 + */ + pub fn downcast_ref(obj: &dyn Any) -> Option<&T> { + obj.downcast_ref::() + } + + /** + * 尝试将可变Any trait对象转换为具体类型 + */ + pub fn downcast_mut(obj: &mut dyn Any) -> Option<&mut T> { + obj.downcast_mut::() + } + + /** + * 检查是否可以转换为指定类型 + */ + pub fn can_downcast(obj: &dyn Any) -> bool { + obj.is::() + } + + /** + * 获取类型的大小(字节) + */ + pub fn get_type_size() -> usize { + std::mem::size_of::() + } + + /** + * 获取对象的大小(字节) + */ + pub fn get_object_size(obj: &T) -> usize { + std::mem::size_of_val(obj) + } + + /** + * 检查类型是否为零大小类型 + */ + pub fn is_zero_sized() -> bool { + std::mem::size_of::() == 0 + } + + /** + * 获取类型的对齐要求 + */ + pub fn get_type_align() -> usize { + std::mem::align_of::() + } + + /** + * 检查类型是否实现了Copy trait(通过编译时检查) + */ + pub fn is_copy_type() -> bool { + true + } + + /** + * 检查类型是否实现了Clone trait(通过编译时检查) + */ + pub fn is_clone_type() -> bool { + true + } + + /** + * 检查类型是否实现了Debug trait(通过编译时检查) + */ + pub fn is_debug_type() -> bool { + true + } + + /** + * 安全地克隆对象(如果实现了Clone) + */ + pub fn safe_clone(obj: &T) -> T { + obj.clone() + } + + /** + * 获取类型的显示字符串(如果实现了Debug) + */ + pub fn debug_string(obj: &T) -> String { + format!("{:?}", obj) + } +} + +/** + * 字符串扩展工具 + * 提供字符串处理的实用方法 + */ +pub struct StringExtension; + +impl StringExtension { + /** + * 检查字符串是否为空或仅包含空白字符 + */ + pub fn is_null_or_whitespace(s: Option<&str>) -> bool { + match s { + None => true, + Some(s) => s.trim().is_empty(), + } + } + + /** + * 检查字符串是否为空 + */ + pub fn is_null_or_empty(s: Option<&str>) -> bool { + match s { + None => true, + Some(s) => s.is_empty(), + } + } + + /** + * 截断字符串到指定长度 + */ + pub fn truncate(s: &str, max_length: usize) -> String { + if s.len() <= max_length { + s.to_string() + } else { + let mut truncated = String::with_capacity(max_length + 3); + truncated.push_str(&s[..max_length]); + truncated.push_str("..."); + truncated + } + } + + /** + * 将字符串转换为Pascal命名 + */ + pub fn to_pascal_case(s: &str) -> String { + s.split_whitespace() + .map(|word| { + let mut chars = word.chars(); + match chars.next() { + None => String::new(), + Some(first) => first.to_uppercase().collect::() + &chars.as_str().to_lowercase(), + } + }) + .collect::>() + .join("") + } + + /** + * 将字符串转换为camel命名 + */ + pub fn to_camel_case(s: &str) -> String { + let pascal = Self::to_pascal_case(s); + if pascal.is_empty() { + return pascal; + } + + let mut chars = pascal.chars(); + match chars.next() { + None => String::new(), + Some(first) => first.to_lowercase().collect::() + chars.as_str(), + } + } + + /** + * 将字符串转换为snake_case + */ + pub fn to_snake_case(s: &str) -> String { + s.chars() + .enumerate() + .flat_map(|(i, c)| { + if i > 0 && c.is_uppercase() { + vec!['_', c.to_lowercase().next().unwrap()] + } else { + vec![c.to_lowercase().next().unwrap()] + } + }) + .collect() + } + + /** + * 重复字符串指定次数 + */ + pub fn repeat(s: &str, count: usize) -> String { + s.repeat(count) + } + + /** + * 左侧填充字符到指定长度 + */ + pub fn pad_left(s: &str, total_width: usize, pad_char: char) -> String { + if s.len() >= total_width { + s.to_string() + } else { + let pad_count = total_width - s.len(); + pad_char.to_string().repeat(pad_count) + s + } + } + + /** + * 右侧填充字符到指定长度 + */ + pub fn pad_right(s: &str, total_width: usize, pad_char: char) -> String { + if s.len() >= total_width { + s.to_string() + } else { + let pad_count = total_width - s.len(); + s.to_string() + &pad_char.to_string().repeat(pad_count) + } + } + + /** + * 反转字符串 + */ + pub fn reverse(s: &str) -> String { + s.chars().rev().collect() + } + + /** + * 统计子字符串出现次数 + */ + pub fn count_occurrences(s: &str, pattern: &str) -> usize { + if pattern.is_empty() { + return 0; + } + + let mut count = 0; + let mut start = 0; + + while let Some(pos) = s[start..].find(pattern) { + count += 1; + start += pos + pattern.len(); + } + + count + } + + /** + * 移除字符串中的所有空白字符 + */ + pub fn remove_whitespace(s: &str) -> String { + s.chars().filter(|c| !c.is_whitespace()).collect() + } +} + +/** + * 集合扩展工具 + * 提供集合操作的实用方法 + */ +pub struct CollectionExtension; + +impl CollectionExtension { + /** + * 检查Vector是否为空或None + */ + pub fn is_null_or_empty(vec: Option<&Vec>) -> bool { + match vec { + None => true, + Some(v) => v.is_empty(), + } + } + + /** + * 安全地获取Vector中指定索引的元素 + */ + pub fn get_safe(vec: &[T], index: usize) -> Option<&T> { + vec.get(index) + } + + /** + * 查找满足条件的第一个元素 + */ + pub fn find(vec: &[T], predicate: F) -> Option<&T> + where + F: Fn(&T) -> bool, + { + vec.iter().find(|&item| predicate(item)) + } + + /** + * 查找满足条件的所有元素 + */ + pub fn find_all(vec: &[T], predicate: F) -> Vec<&T> + where + F: Fn(&T) -> bool, + { + vec.iter().filter(|&item| predicate(item)).collect() + } + + /** + * 检查是否存在满足条件的元素 + */ + pub fn exists(vec: &[T], predicate: F) -> bool + where + F: Fn(&T) -> bool, + { + vec.iter().any(|item| predicate(item)) + } + + /** + * 检查所有元素是否都满足条件 + */ + pub fn all(vec: &[T], predicate: F) -> bool + where + F: Fn(&T) -> bool, + { + vec.iter().all(|item| predicate(item)) + } + + /** + * 获取Vector的最大值 + */ + pub fn max(vec: &[T]) -> Option { + vec.iter().max().cloned() + } + + /** + * 获取Vector的最小值 + */ + pub fn min(vec: &[T]) -> Option { + vec.iter().min().cloned() + } + + /** + * 计算数字Vector的和 + */ + pub fn sum(vec: &[T]) -> T + where + T: std::iter::Sum + Copy, + { + vec.iter().copied().sum() + } + + /** + * 计算数字Vector的平均值 + */ + pub fn average(vec: &[f64]) -> Option { + if vec.is_empty() { + None + } else { + Some(Self::sum(vec) / vec.len() as f64) + } + } + + /** + * 去重Vector中的元素 + */ + pub fn distinct(vec: &[T]) -> Vec { + let mut result = Vec::new(); + for item in vec { + if !result.contains(item) { + result.push(item.clone()); + } + } + result + } + + /** + * 分块处理Vector + */ + pub fn chunk(vec: &[T], size: usize) -> Vec<&[T]> { + if size == 0 { + return Vec::new(); + } + vec.chunks(size).collect() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_number_extension_parse() { + assert_eq!(NumberExtension::parse_or_zero("123"), 123.0); + assert_eq!(NumberExtension::parse_or_zero("123.45"), 123.45); + assert_eq!(NumberExtension::parse_or_zero("invalid"), 0.0); + assert_eq!(NumberExtension::parse_or_default("invalid", 99.0), 99.0); + + assert_eq!(NumberExtension::parse_int_or_zero("123"), 123); + assert_eq!(NumberExtension::parse_int_or_zero("invalid"), 0); + assert_eq!(NumberExtension::parse_int_or_default("invalid", 99), 99); + } + + #[test] + fn test_number_extension_bool_conversion() { + assert_eq!(NumberExtension::bool_to_number(true), 1.0); + assert_eq!(NumberExtension::bool_to_number(false), 0.0); + + assert_eq!(NumberExtension::number_to_bool(1.0), true); + assert_eq!(NumberExtension::number_to_bool(0.0), false); + assert_eq!(NumberExtension::number_to_bool(0.5), true); + assert_eq!(NumberExtension::number_to_bool(-1.0), true); + } + + #[test] + fn test_number_extension_clamp() { + assert_eq!(NumberExtension::clamp(5.0, 0.0, 10.0), 5.0); + assert_eq!(NumberExtension::clamp(-1.0, 0.0, 10.0), 0.0); + assert_eq!(NumberExtension::clamp(15.0, 0.0, 10.0), 10.0); + } + + #[test] + fn test_number_extension_range() { + assert!(NumberExtension::is_in_range(5.0, 0.0, 10.0)); + assert!(!NumberExtension::is_in_range(-1.0, 0.0, 10.0)); + assert!(!NumberExtension::is_in_range(15.0, 0.0, 10.0)); + } + + #[test] + fn test_number_extension_round() { + assert_eq!(NumberExtension::round_to_decimal_places(3.14159, 2), 3.14); + assert_eq!(NumberExtension::round_to_decimal_places(3.14159, 0), 3.0); + } + + #[test] + fn test_number_extension_angle_conversion() { + let degrees = NumberExtension::radians_to_degrees(std::f64::consts::PI); + assert!((degrees - 180.0).abs() < 0.001); + + let radians = NumberExtension::degrees_to_radians(180.0); + assert!((radians - std::f64::consts::PI).abs() < 0.001); + } + + #[test] + fn test_number_extension_lerp() { + assert_eq!(NumberExtension::lerp(0.0, 10.0, 0.5), 5.0); + assert_eq!(NumberExtension::lerp(0.0, 10.0, 0.0), 0.0); + assert_eq!(NumberExtension::lerp(0.0, 10.0, 1.0), 10.0); + + assert_eq!(NumberExtension::inverse_lerp(0.0, 10.0, 5.0), 0.5); + } + + #[test] + fn test_number_extension_distance() { + assert_eq!(NumberExtension::distance(5.0, 3.0), 2.0); + assert_eq!(NumberExtension::distance(3.0, 5.0), 2.0); + assert_eq!(NumberExtension::distance(-2.0, 3.0), 5.0); + } + + #[test] + fn test_number_extension_approximately_equal() { + assert!(NumberExtension::approximately_equal(1.0, 1.0000001, Some(0.001))); + assert!(!NumberExtension::approximately_equal(1.0, 1.1, Some(0.001))); + } + + #[test] + fn test_number_extension_wrap() { + assert_eq!(NumberExtension::wrap(5.0, 10.0), 5.0); + assert_eq!(NumberExtension::wrap(15.0, 10.0), 5.0); + assert_eq!(NumberExtension::wrap(-1.0, 10.0), 9.0); + } + + #[test] + fn test_number_extension_sign() { + assert_eq!(NumberExtension::sign(5.0), 1.0); + assert_eq!(NumberExtension::sign(-5.0), -1.0); + assert_eq!(NumberExtension::sign(0.0), 0.0); + } + + #[test] + fn test_type_utils_type_id() { + assert_eq!(TypeUtils::get_type_id::(), TypeUtils::get_type_id::()); + assert_ne!(TypeUtils::get_type_id::(), TypeUtils::get_type_id::()); + + let value = 42i32; + assert_eq!(TypeUtils::get_object_type_id(&value), TypeUtils::get_type_id::()); + } + + #[test] + fn test_type_utils_type_name() { + assert!(TypeUtils::get_type_name::().contains("i32")); + + let value = 42i32; + assert!(TypeUtils::get_object_type_name(&value).contains("i32")); + } + + #[test] + fn test_type_utils_same_type() { + assert!(TypeUtils::is_same_type::()); + assert!(!TypeUtils::is_same_type::()); + } + + #[test] + fn test_type_utils_size() { + assert_eq!(TypeUtils::get_type_size::(), 4); + assert_eq!(TypeUtils::get_type_size::(), 8); + + let value = 42i32; + assert_eq!(TypeUtils::get_object_size(&value), 4); + } + + #[test] + fn test_type_utils_zero_sized() { + assert!(TypeUtils::is_zero_sized::<()>()); + assert!(!TypeUtils::is_zero_sized::()); + } + + #[test] + fn test_string_extension_null_checks() { + assert!(StringExtension::is_null_or_empty(None)); + assert!(StringExtension::is_null_or_empty(Some(""))); + assert!(!StringExtension::is_null_or_empty(Some("hello"))); + + assert!(StringExtension::is_null_or_whitespace(None)); + assert!(StringExtension::is_null_or_whitespace(Some(" "))); + assert!(!StringExtension::is_null_or_whitespace(Some("hello"))); + } + + #[test] + fn test_string_extension_truncate() { + assert_eq!(StringExtension::truncate("hello world", 5), "hello..."); + assert_eq!(StringExtension::truncate("hi", 10), "hi"); + } + + #[test] + fn test_string_extension_case_conversion() { + assert_eq!(StringExtension::to_pascal_case("hello world"), "HelloWorld"); + assert_eq!(StringExtension::to_camel_case("hello world"), "helloWorld"); + assert_eq!(StringExtension::to_snake_case("HelloWorld"), "hello_world"); + } + + #[test] + fn test_string_extension_padding() { + assert_eq!(StringExtension::pad_left("123", 5, '0'), "00123"); + assert_eq!(StringExtension::pad_right("123", 5, '0'), "12300"); + } + + #[test] + fn test_string_extension_reverse() { + assert_eq!(StringExtension::reverse("hello"), "olleh"); + } + + #[test] + fn test_string_extension_count_occurrences() { + assert_eq!(StringExtension::count_occurrences("hello world hello", "hello"), 2); + assert_eq!(StringExtension::count_occurrences("test", "xyz"), 0); + } + + #[test] + fn test_collection_extension_null_checks() { + assert!(CollectionExtension::is_null_or_empty(None::<&Vec>)); + assert!(CollectionExtension::is_null_or_empty(Some(&Vec::::new()))); + assert!(!CollectionExtension::is_null_or_empty(Some(&vec![1, 2, 3]))); + } + + #[test] + fn test_collection_extension_safe_get() { + let vec = vec![1, 2, 3]; + assert_eq!(CollectionExtension::get_safe(&vec, 0), Some(&1)); + assert_eq!(CollectionExtension::get_safe(&vec, 5), None); + } + + #[test] + fn test_collection_extension_find() { + let vec = vec![1, 2, 3, 4, 5]; + assert_eq!(CollectionExtension::find(&vec, |&x| x > 3), Some(&4)); + assert_eq!(CollectionExtension::find(&vec, |&x| x > 10), None); + + let found_all = CollectionExtension::find_all(&vec, |&x| x > 3); + assert_eq!(found_all, vec![&4, &5]); + } + + #[test] + fn test_collection_extension_predicates() { + let vec = vec![1, 2, 3, 4, 5]; + assert!(CollectionExtension::exists(&vec, |&x| x > 3)); + assert!(!CollectionExtension::exists(&vec, |&x| x > 10)); + + assert!(CollectionExtension::all(&vec, |&x| x > 0)); + assert!(!CollectionExtension::all(&vec, |&x| x > 3)); + } + + #[test] + fn test_collection_extension_math() { + let vec = vec![1.0, 2.0, 3.0, 4.0, 5.0]; + assert_eq!(CollectionExtension::sum(&vec), 15.0); + assert_eq!(CollectionExtension::average(&vec), Some(3.0)); + + let int_vec = vec![1, 5, 3, 2, 4]; + assert_eq!(CollectionExtension::max(&int_vec), Some(5)); + assert_eq!(CollectionExtension::min(&int_vec), Some(1)); + } + + #[test] + fn test_collection_extension_distinct() { + let vec = vec![1, 2, 2, 3, 1, 4]; + let distinct = CollectionExtension::distinct(&vec); + assert_eq!(distinct, vec![1, 2, 3, 4]); + } + + #[test] + fn test_collection_extension_chunk() { + let vec = vec![1, 2, 3, 4, 5, 6, 7]; + let chunks = CollectionExtension::chunk(&vec, 3); + assert_eq!(chunks.len(), 3); + assert_eq!(chunks[0], &[1, 2, 3]); + assert_eq!(chunks[1], &[4, 5, 6]); + assert_eq!(chunks[2], &[7]); + } + + #[test] + fn test_number_extension_to_number_from_option() { + assert_eq!(NumberExtension::to_number_from_option(Some(42)), 42.0); + let result = NumberExtension::to_number_from_option(Some(3.14f32)); + assert!((result - 3.14).abs() < 0.0001); // 使用近似相等检查浮点数 + assert_eq!(NumberExtension::to_number_from_option::(None), 0.0); + } +} \ No newline at end of file diff --git a/packages/core-rust/src/utils/identifier_pool.rs b/packages/core-rust/src/utils/identifier_pool.rs new file mode 100644 index 00000000..4b195eed --- /dev/null +++ b/packages/core-rust/src/utils/identifier_pool.rs @@ -0,0 +1,518 @@ +use std::collections::HashMap; + +/** + * 延迟回收项结构 + */ +#[derive(Debug, Clone)] +struct PendingRecycleItem { + index: u16, + generation: u16, + timestamp: u64, +} + +/** + * 世代式ID池统计信息 + */ +#[derive(Debug, Clone, Default)] +pub struct IdentifierPoolStats { + /// 已分配的总索引数 + pub total_allocated: u64, + /// 总计回收次数 + pub total_recycled: u64, + /// 当前活跃实体数 + pub current_active: u32, + /// 当前空闲的索引数 + pub currently_free: u32, + /// 等待回收的ID数 + pub pending_recycle: u32, + /// 理论最大实体数(设计限制) + pub max_possible_entities: u32, + /// 当前使用的最大索引 + pub max_used_index: u16, + /// 内存使用(字节) + pub memory_usage: usize, + /// 内存扩展次数 + pub memory_expansions: u32, + /// 平均世代版本 + pub average_generation: f64, + /// 世代存储大小 + pub generation_storage_size: usize, +} + +/** + * 世代式ID池管理器 + * + * 用于管理实体ID的分配和回收,支持世代版本控制以防止悬空引用问题。 + * 世代式ID由索引和版本组成,当ID被回收时版本会递增,确保旧引用失效。 + * + * 支持动态扩展,理论上可以支持到65535个索引(16位),每个索引65535个版本(16位)。 + * 总计可以处理超过42亿个独特的ID组合,完全满足ECS大规模实体需求。 + */ +#[derive(Debug)] +pub struct IdentifierPool { + /// 下一个可用的索引 + next_available_index: u16, + + /// 空闲的索引列表 + free_indices: Vec, + + /// 每个索引对应的世代版本 + /// 使用HashMap实现动态扩展 + generations: HashMap, + + /// 延迟回收队列 + /// 防止在同一帧内立即重用ID,避免时序问题 + pending_recycle: Vec, + + /// 延迟回收时间(毫秒) + recycle_delay: u64, + + /// 内存扩展块大小 + expansion_block_size: u16, + + /// 统计信息 + stats: IdentifierPoolStats, +} + +impl IdentifierPool { + /// 最大索引限制(16位) + /// 这是框架设计选择:16位索引 + 16位版本 = 32位ID,确保高效位操作 + pub const MAX_INDEX: u16 = 0xFFFF; // 65535 + + /// 最大世代限制(16位) + pub const MAX_GENERATION: u16 = 0xFFFF; // 65535 + + /** + * 构造函数 + * + * @param recycle_delay 延迟回收时间(毫秒),默认为100ms + * @param expansion_block_size 内存扩展块大小,默认为1024 + */ + pub fn new(recycle_delay: u64, expansion_block_size: u16) -> Self { + let mut pool = Self { + next_available_index: 0, + free_indices: Vec::new(), + generations: HashMap::new(), + pending_recycle: Vec::new(), + recycle_delay, + expansion_block_size, + stats: IdentifierPoolStats::default(), + }; + + // 预分配第一个块的世代信息 + pool.pre_allocate_generations(0, pool.expansion_block_size); + pool + } + + /** + * 使用默认参数创建ID池 + */ + pub fn with_defaults() -> Self { + Self::new(100, 1024) + } + + /** + * 获取一个可用的ID + * + * 返回一个32位ID,高16位为世代版本,低16位为索引。 + * + * @returns 新分配的实体ID + * @throws Error 当达到索引限制时 + */ + pub fn check_out(&mut self) -> Result { + // 处理延迟回收队列 + self.process_delayed_recycle(false); + + let index: u16; + + if let Some(recycled_index) = self.free_indices.pop() { + // 重用回收的索引 + index = recycled_index; + } else { + // 分配新索引 + if self.next_available_index >= Self::MAX_INDEX { + return Err(format!( + "实体索引已达到框架设计限制 ({})。\ + 这意味着您已经分配了超过65535个不同的实体索引。\ + 这是16位索引设计的限制,考虑优化实体回收策略或升级到64位ID设计。", + Self::MAX_INDEX + )); + } + + index = self.next_available_index; + self.next_available_index += 1; + + // 按需扩展世代存储 + self.ensure_generation_capacity(index); + } + + let generation = self.generations.get(&index).copied().unwrap_or(1); + self.stats.total_allocated += 1; + self.stats.current_active += 1; + + Ok(self.pack_id(index, generation)) + } + + /** + * 回收一个ID + * + * 验证ID的有效性后,将其加入延迟回收队列。 + * ID不会立即可重用,而是在延迟时间后才真正回收。 + * + * @param id 要回收的实体ID + * @returns 是否成功回收(ID是否有效且未被重复回收) + */ + pub fn check_in(&mut self, id: u32) -> bool { + let index = self.unpack_index(id); + let generation = self.unpack_generation(id); + + // 验证ID有效性 + if !self.is_valid_id(index, generation) { + return false; + } + + // 检查是否已经在待回收队列中 + let already_pending = self.pending_recycle.iter() + .any(|item| item.index == index && item.generation == generation); + + if already_pending { + return false; // 已经在回收队列中,拒绝重复回收 + } + + // 加入延迟回收队列 + self.pending_recycle.push(PendingRecycleItem { + index, + generation, + timestamp: self.get_current_time_ms(), + }); + + self.stats.current_active -= 1; + self.stats.total_recycled += 1; + + true + } + + /** + * 验证ID是否有效 + * + * 检查ID的索引和世代版本是否匹配当前状态。 + * + * @param id 要验证的实体ID + * @returns ID是否有效 + */ + pub fn is_valid(&self, id: u32) -> bool { + let index = self.unpack_index(id); + let generation = self.unpack_generation(id); + self.is_valid_id(index, generation) + } + + /** + * 获取统计信息 + * + * @returns 池的当前状态统计 + */ + pub fn get_stats(&self) -> IdentifierPoolStats { + // 计算平均世代版本 + let (total_generation, generation_count) = self.generations.iter() + .filter(|(&index, _)| index < self.next_available_index) + .fold((0u64, 0u32), |(sum, count), (_, &generation)| { + (sum + generation as u64, count + 1) + }); + + let average_generation = if generation_count > 0 { + (total_generation as f64) / (generation_count as f64) + } else { + 1.0 + }; + + IdentifierPoolStats { + total_allocated: self.stats.total_allocated, + total_recycled: self.stats.total_recycled, + current_active: self.stats.current_active, + currently_free: self.free_indices.len() as u32, + pending_recycle: self.pending_recycle.len() as u32, + max_possible_entities: (Self::MAX_INDEX as u32) + 1, + max_used_index: if self.next_available_index > 0 { + self.next_available_index - 1 + } else { + 0 + }, + memory_usage: self.calculate_memory_usage(), + memory_expansions: self.stats.memory_expansions, + average_generation: (average_generation * 100.0).round() / 100.0, + generation_storage_size: self.generations.len(), + } + } + + /** + * 强制执行延迟回收处理 + * + * 在某些情况下可能需要立即处理延迟回收队列, + * 比如内存压力大或者需要精确的统计信息时。 + */ + pub fn force_process_delayed_recycle(&mut self) { + self.process_delayed_recycle(true); + } + + /** + * 清理过期的延迟回收项 + * + * 将超过延迟时间的回收项真正回收到空闲列表中。 + * + * @param force_all 是否强制处理所有延迟回收项 + */ + fn process_delayed_recycle(&mut self, force_all: bool) { + if self.pending_recycle.is_empty() { + return; + } + + let now = self.get_current_time_ms(); + let mut ready_to_recycle = Vec::new(); + let mut still_pending = Vec::new(); + + // 分离已到期和未到期的项 + for item in self.pending_recycle.drain(..) { + if force_all || now.saturating_sub(item.timestamp) >= self.recycle_delay { + ready_to_recycle.push(item); + } else { + still_pending.push(item); + } + } + + // 处理到期的回收项 + for item in ready_to_recycle { + // 再次验证ID有效性(防止重复回收) + if self.is_valid_id(item.index, item.generation) { + // 递增世代版本 + let new_generation = if item.generation >= Self::MAX_GENERATION { + 1 // 重置为1而不是0 + } else { + item.generation + 1 + }; + + self.generations.insert(item.index, new_generation); + + // 添加到空闲列表 + self.free_indices.push(item.index); + } + } + + // 更新待回收队列 + self.pending_recycle = still_pending; + } + + /** + * 预分配世代信息 + * + * @param start_index 起始索引 + * @param count 分配数量 + */ + fn pre_allocate_generations(&mut self, start_index: u16, count: u16) { + for i in 0..count { + let index = start_index.saturating_add(i); + if index <= Self::MAX_INDEX { + self.generations.insert(index, 1); + } else { + break; + } + } + self.stats.memory_expansions += 1; + } + + /** + * 确保指定索引的世代信息存在 + * + * @param index 索引 + */ + fn ensure_generation_capacity(&mut self, index: u16) { + if !self.generations.contains_key(&index) { + // 计算需要扩展的起始位置 + let expansion_start = (index / self.expansion_block_size) * self.expansion_block_size; + + // 预分配一个块 + self.pre_allocate_generations(expansion_start, self.expansion_block_size); + } + } + + /** + * 计算内存使用量 + * + * @returns 内存使用字节数 + */ + fn calculate_memory_usage(&self) -> usize { + let generation_map_size = self.generations.len() * (std::mem::size_of::() * 2 + 24); // HashMap overhead + let free_indices_size = self.free_indices.capacity() * std::mem::size_of::(); + let pending_recycle_size = self.pending_recycle.capacity() * std::mem::size_of::(); + + generation_map_size + free_indices_size + pending_recycle_size + } + + /** + * 打包索引和世代为32位ID + * + * @param index 索引(16位) + * @param generation 世代版本(16位) + * @returns 打包后的32位ID + */ + fn pack_id(&self, index: u16, generation: u16) -> u32 { + ((generation as u32) << 16) | (index as u32) + } + + /** + * 从ID中解包索引 + * + * @param id 32位ID + * @returns 索引部分(16位) + */ + fn unpack_index(&self, id: u32) -> u16 { + (id & 0xFFFF) as u16 + } + + /** + * 从ID中解包世代版本 + * + * @param id 32位ID + * @returns 世代版本部分(16位) + */ + fn unpack_generation(&self, id: u32) -> u16 { + ((id >> 16) & 0xFFFF) as u16 + } + + /** + * 内部ID有效性检查 + * + * @param index 索引 + * @param generation 世代版本 + * @returns 是否有效 + */ + fn is_valid_id(&self, index: u16, generation: u16) -> bool { + if index >= self.next_available_index { + return false; + } + + if let Some(¤t_generation) = self.generations.get(&index) { + current_generation == generation + } else { + false + } + } + + /** + * 获取当前时间(毫秒) + * 在实际应用中应该使用更准确的时间源 + */ + fn get_current_time_ms(&self) -> u64 { + // 简单的时间实现,实际使用中可能需要更精确的时间源 + // 在WASM环境中可以通过js_sys::Date获取 + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap_or_default() + .as_millis() as u64 + } +} + +impl Default for IdentifierPool { + fn default() -> Self { + Self::with_defaults() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_identifier_pool_basic() { + let mut pool = IdentifierPool::with_defaults(); + + // 分配ID + let id1 = pool.check_out().unwrap(); + let id2 = pool.check_out().unwrap(); + + assert_ne!(id1, id2); + assert!(pool.is_valid(id1)); + assert!(pool.is_valid(id2)); + + let stats = pool.get_stats(); + assert_eq!(stats.current_active, 2); + assert_eq!(stats.total_allocated, 2); + } + + #[test] + fn test_identifier_pool_recycle() { + let mut pool = IdentifierPool::with_defaults(); + + let id = pool.check_out().unwrap(); + assert!(pool.is_valid(id)); + + // 回收ID + assert!(pool.check_in(id)); + + // ID应该仍然有效直到延迟回收处理 + assert!(pool.is_valid(id)); + + // 强制处理延迟回收 + pool.force_process_delayed_recycle(); + + // 现在ID应该无效 + assert!(!pool.is_valid(id)); + + let stats = pool.get_stats(); + assert_eq!(stats.current_active, 0); + assert_eq!(stats.currently_free, 1); + } + + #[test] + fn test_identifier_pool_generation_increment() { + let mut pool = IdentifierPool::with_defaults(); + + let id1 = pool.check_out().unwrap(); + let index = pool.unpack_index(id1); + let generation1 = pool.unpack_generation(id1); + + // 回收并强制处理 + pool.check_in(id1); + pool.force_process_delayed_recycle(); + + // 重新分配同一个索引 + let id2 = pool.check_out().unwrap(); + let index2 = pool.unpack_index(id2); + let generation2 = pool.unpack_generation(id2); + + assert_eq!(index, index2); // 同一个索引 + assert_eq!(generation2, generation1 + 1); // 世代递增 + assert!(!pool.is_valid(id1)); // 旧ID无效 + assert!(pool.is_valid(id2)); // 新ID有效 + } + + #[test] + fn test_identifier_pool_double_recycle() { + let mut pool = IdentifierPool::with_defaults(); + + let id = pool.check_out().unwrap(); + + // 第一次回收应该成功 + assert!(pool.check_in(id)); + + // 第二次回收应该失败 + assert!(!pool.check_in(id)); + } + + #[test] + fn test_identifier_pool_stats() { + let mut pool = IdentifierPool::with_defaults(); + + let _id1 = pool.check_out().unwrap(); + let id2 = pool.check_out().unwrap(); + let _id3 = pool.check_out().unwrap(); + + pool.check_in(id2); + + let stats = pool.get_stats(); + assert_eq!(stats.total_allocated, 3); + assert_eq!(stats.total_recycled, 1); + assert_eq!(stats.current_active, 2); + assert_eq!(stats.pending_recycle, 1); + assert_eq!(stats.max_used_index, 2); + } +} \ No newline at end of file diff --git a/packages/core-rust/src/utils/matcher.rs b/packages/core-rust/src/utils/matcher.rs new file mode 100644 index 00000000..f005b9f6 --- /dev/null +++ b/packages/core-rust/src/utils/matcher.rs @@ -0,0 +1,456 @@ +use std::any::TypeId; + +/** + * 组件类型标识符 + * 在Rust中使用TypeId来标识组件类型 + */ +pub type ComponentType = TypeId; + +/** + * 查询条件结构 + * 定义实体查询的所有条件类型 + */ +#[derive(Debug, Clone)] +pub struct QueryCondition { + /// 必须包含所有这些组件 + pub all: Vec, + /// 必须包含至少一个这些组件 + pub any: Vec, + /// 不能包含任何这些组件 + pub none: Vec, + /// 按标签查询 + pub tag: Option, + /// 按名称查询 + pub name: Option, + /// 单组件查询 + pub component: Option, +} + +impl Default for QueryCondition { + fn default() -> Self { + Self { + all: Vec::new(), + any: Vec::new(), + none: Vec::new(), + tag: None, + name: None, + component: None, + } + } +} + +/** + * 实体匹配条件描述符 + * + * 用于描述实体查询条件,不执行实际查询 + * 支持链式调用构建复杂查询条件 + */ +#[derive(Debug)] +pub struct Matcher { + condition: QueryCondition, +} + +impl Matcher { + /** + * 创建新的匹配器 + */ + pub fn new() -> Self { + Self { + condition: QueryCondition::default(), + } + } + + // ========== 静态构造方法 ========== + + /** + * 创建匹配器,要求所有指定的组件 + */ + pub fn all_of(component_types: &[ComponentType]) -> Self { + let mut matcher = Self::new(); + matcher.all_of_types(component_types); + matcher + } + + /** + * 创建匹配器,要求至少一个指定的组件 + */ + pub fn any_of(component_types: &[ComponentType]) -> Self { + let mut matcher = Self::new(); + matcher.any_of_types(component_types); + matcher + } + + /** + * 创建匹配器,排除指定的组件 + */ + pub fn none_of(component_types: &[ComponentType]) -> Self { + let mut matcher = Self::new(); + matcher.none_of_types(component_types); + matcher + } + + /** + * 创建按标签查询的匹配器 + */ + pub fn by_tag(tag: u32) -> Self { + let mut matcher = Self::new(); + matcher.with_tag(tag); + matcher + } + + /** + * 创建按名称查询的匹配器 + */ + pub fn by_name(name: String) -> Self { + let mut matcher = Self::new(); + matcher.with_name(name); + matcher + } + + /** + * 创建单组件查询的匹配器 + */ + pub fn by_component(component_type: ComponentType) -> Self { + let mut matcher = Self::new(); + matcher.with_component(component_type); + matcher + } + + /** + * 创建复杂查询构建器 + */ + pub fn complex() -> Self { + Self::new() + } + + /** + * 创建空匹配器(向后兼容) + */ + pub fn empty() -> Self { + Self::new() + } + + // ========== 链式构建方法 ========== + + /** + * 必须包含所有指定组件 + */ + pub fn all_of_types(&mut self, component_types: &[ComponentType]) -> &mut Self { + self.condition.all.extend_from_slice(component_types); + self + } + + /** + * 必须包含所有指定组件(单个组件版本) + */ + pub fn all(&mut self, component_type: ComponentType) -> &mut Self { + self.condition.all.push(component_type); + self + } + + /** + * 必须包含至少一个指定组件 + */ + pub fn any_of_types(&mut self, component_types: &[ComponentType]) -> &mut Self { + self.condition.any.extend_from_slice(component_types); + self + } + + /** + * 必须包含至少一个指定组件(单个组件版本) + */ + pub fn any(&mut self, component_type: ComponentType) -> &mut Self { + self.condition.any.push(component_type); + self + } + + /** + * 不能包含任何指定组件 + */ + pub fn none_of_types(&mut self, component_types: &[ComponentType]) -> &mut Self { + self.condition.none.extend_from_slice(component_types); + self + } + + /** + * 不能包含指定组件(单个组件版本) + */ + pub fn none(&mut self, component_type: ComponentType) -> &mut Self { + self.condition.none.push(component_type); + self + } + + /** + * 排除指定组件(别名方法) + */ + pub fn exclude(&mut self, component_type: ComponentType) -> &mut Self { + self.none(component_type) + } + + /** + * 至少包含其中之一(别名方法) + */ + pub fn one(&mut self, component_type: ComponentType) -> &mut Self { + self.any(component_type) + } + + /** + * 按标签查询 + */ + pub fn with_tag(&mut self, tag: u32) -> &mut Self { + self.condition.tag = Some(tag); + self + } + + /** + * 按名称查询 + */ + pub fn with_name(&mut self, name: String) -> &mut Self { + self.condition.name = Some(name); + self + } + + /** + * 单组件查询 + */ + pub fn with_component(&mut self, component_type: ComponentType) -> &mut Self { + self.condition.component = Some(component_type); + self + } + + /** + * 移除标签条件 + */ + pub fn without_tag(&mut self) -> &mut Self { + self.condition.tag = None; + self + } + + /** + * 移除名称条件 + */ + pub fn without_name(&mut self) -> &mut Self { + self.condition.name = None; + self + } + + /** + * 移除单组件条件 + */ + pub fn without_component(&mut self) -> &mut Self { + self.condition.component = None; + self + } + + // ========== 查询和工具方法 ========== + + /** + * 获取查询条件(只读) + */ + pub fn get_condition(&self) -> &QueryCondition { + &self.condition + } + + /** + * 获取查询条件的克隆 + */ + pub fn clone_condition(&self) -> QueryCondition { + self.condition.clone() + } + + /** + * 检查是否为空条件 + */ + pub fn is_empty(&self) -> bool { + self.condition.all.is_empty() && + self.condition.any.is_empty() && + self.condition.none.is_empty() && + self.condition.tag.is_none() && + self.condition.name.is_none() && + self.condition.component.is_none() + } + + /** + * 重置所有条件 + */ + pub fn reset(&mut self) -> &mut Self { + self.condition.all.clear(); + self.condition.any.clear(); + self.condition.none.clear(); + self.condition.tag = None; + self.condition.name = None; + self.condition.component = None; + self + } + + /** + * 克隆匹配器 + */ + pub fn clone(&self) -> Self { + Self { + condition: self.condition.clone(), + } + } + + /** + * 获取所有条件的组件类型数量(用于性能分析) + */ + pub fn component_type_count(&self) -> usize { + self.condition.all.len() + + self.condition.any.len() + + self.condition.none.len() + + if self.condition.component.is_some() { 1 } else { 0 } + } + + /** + * 检查查询条件的复杂度 + */ + pub fn complexity_level(&self) -> u32 { + let mut level = 0; + + if !self.condition.all.is_empty() { level += 1; } + if !self.condition.any.is_empty() { level += 2; } + if !self.condition.none.is_empty() { level += 1; } + if self.condition.tag.is_some() { level += 1; } + if self.condition.name.is_some() { level += 1; } + if self.condition.component.is_some() { level += 1; } + + level + } +} + +impl Default for Matcher { + fn default() -> Self { + Self::new() + } +} + +/** + * 用于测试和调试的方法 + */ +impl Matcher { + /** + * 格式化为调试字符串 + */ + pub fn debug_string(&self) -> String { + let mut parts = Vec::new(); + + if !self.condition.all.is_empty() { + parts.push(format!("all({} types)", self.condition.all.len())); + } + + if !self.condition.any.is_empty() { + parts.push(format!("any({} types)", self.condition.any.len())); + } + + if !self.condition.none.is_empty() { + parts.push(format!("none({} types)", self.condition.none.len())); + } + + if let Some(tag) = self.condition.tag { + parts.push(format!("tag({})", tag)); + } + + if let Some(ref name) = self.condition.name { + parts.push(format!("name({})", name)); + } + + if self.condition.component.is_some() { + parts.push("component(1 type)".to_string()); + } + + if parts.is_empty() { + "Matcher[empty]".to_string() + } else { + format!("Matcher[{}]", parts.join(" & ")) + } + } +} + +// 实现Display trait以支持打印 +impl std::fmt::Display for Matcher { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.debug_string()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::any::TypeId; + + // 测试用的示例组件 + struct TestComponent1; + struct TestComponent2; + struct TestComponent3; + + #[test] + fn test_matcher_all() { + let mut matcher = Matcher::new(); + matcher.all(TypeId::of::()) + .all(TypeId::of::()); + + assert_eq!(matcher.get_condition().all.len(), 2); + assert!(!matcher.is_empty()); + } + + #[test] + fn test_matcher_any() { + let mut matcher = Matcher::new(); + matcher.any(TypeId::of::()) + .any(TypeId::of::()); + + assert_eq!(matcher.get_condition().any.len(), 2); + } + + #[test] + fn test_matcher_none() { + let mut matcher = Matcher::new(); + matcher.none(TypeId::of::()); + + assert_eq!(matcher.get_condition().none.len(), 1); + } + + #[test] + fn test_matcher_complex() { + let mut matcher = Matcher::complex(); + matcher.all(TypeId::of::()) + .any(TypeId::of::()) + .none(TypeId::of::()) + .with_tag(42) + .with_name("test_entity".to_string()); + + assert_eq!(matcher.complexity_level(), 6); + assert!(!matcher.is_empty()); + } + + #[test] + fn test_matcher_static_constructors() { + let types = vec![TypeId::of::(), TypeId::of::()]; + let matcher = Matcher::all_of(&types); + assert_eq!(matcher.get_condition().all.len(), 2); + } + + #[test] + fn test_matcher_reset() { + let mut matcher = Matcher::new(); + matcher.all(TypeId::of::()) + .with_tag(42); + + assert!(!matcher.is_empty()); + + matcher.reset(); + assert!(matcher.is_empty()); + } + + #[test] + fn test_matcher_clone() { + let mut matcher = Matcher::new(); + matcher.all(TypeId::of::()) + .with_tag(42); + + let cloned = matcher.clone(); + assert_eq!(cloned.get_condition().all.len(), 1); + assert_eq!(cloned.get_condition().tag, Some(42)); + } +} \ No newline at end of file diff --git a/packages/core-rust/src/utils/mod.rs b/packages/core-rust/src/utils/mod.rs new file mode 100644 index 00000000..232b7961 --- /dev/null +++ b/packages/core-rust/src/utils/mod.rs @@ -0,0 +1,46 @@ +pub mod sparse_set; +pub mod time; +pub mod matcher; +pub mod identifier_pool; +pub mod component_pool; +pub mod dirty_tracking; +pub mod performance_monitor; +pub mod timer; +pub mod pool; +pub mod debug; +pub mod updatable; +pub mod extensions; + +pub use sparse_set::SparseSet; +pub use time::Time; +pub use matcher::{Matcher, QueryCondition, ComponentType}; +pub use identifier_pool::{IdentifierPool, IdentifierPoolStats}; +pub use component_pool::{ComponentPool, ComponentPoolManager, ComponentPoolStats, ComponentPoolManagerStats, PoolStatsSummary}; +pub use dirty_tracking::{DirtyTrackingSystem, DirtyFlag, DirtyData, DirtyTrackingStats, DirtyListener, DirtyListenerConfig}; +pub use performance_monitor::{PerformanceMonitor, PerformanceData, PerformanceStats, PerformanceWarning, PerformanceWarningType, WarningSeverity, PerformanceThresholds, ThresholdPair}; +pub use timer::{Timer, TimerManager, ITimer, TimerContext, TimerCallback, EmptyContext}; +pub use pool::{Pool, PoolManager, Poolable, PoolStats}; +pub use debug::{DebugManager, EntityDataCollector, SystemDataCollector, ComponentDataCollector, PerformanceDataCollector, DebugEntityData, DebugComponentInfo, DebugSystemInfo, DebugArchetypeInfo, DebugPerformanceInfo, DebugWarning, WarningLevel, DebugStats, DebugData}; +pub use updatable::{IUpdatable, IUpdatableComparer, SceneComponent, SceneComponentTrait, UpdatableManager, SceneComponentManager, is_updatable}; +pub use extensions::{NumberExtension, TypeUtils, StringExtension, CollectionExtension}; + +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(js_namespace = console)] + fn error(msg: String); +} + +#[cfg(feature = "console_error_panic_hook")] +pub fn set_panic_hook() { + console_error_panic_hook::set_once(); +} + +#[cfg(not(feature = "console_error_panic_hook"))] +pub fn set_panic_hook() {} + +#[allow(dead_code)] +pub fn log_error(msg: &str) { + error(msg.to_string()); +} \ No newline at end of file diff --git a/packages/core-rust/src/utils/performance_monitor.rs b/packages/core-rust/src/utils/performance_monitor.rs new file mode 100644 index 00000000..33e81dcb --- /dev/null +++ b/packages/core-rust/src/utils/performance_monitor.rs @@ -0,0 +1,824 @@ +use rustc_hash::FxHashMap; +use std::time::{Instant, SystemTime, UNIX_EPOCH}; +use std::collections::VecDeque; + +/** + * 性能数据 + */ +#[derive(Debug, Clone)] +pub struct PerformanceData { + /// 系统名称 + pub name: String, + /// 执行时间(毫秒) + pub execution_time: f64, + /// 处理的实体数量 + pub entity_count: usize, + /// 平均每个实体的处理时间 + pub average_time_per_entity: f64, + /// 最后更新时间戳 + pub last_update_time: u64, + /// 内存使用量(字节) + pub memory_usage: Option, + /// CPU使用率(百分比) + pub cpu_usage: Option, +} + +/** + * 性能统计信息 + */ +#[derive(Debug, Clone)] +pub struct PerformanceStats { + /// 总执行时间 + pub total_time: f64, + /// 平均执行时间 + pub average_time: f64, + /// 最小执行时间 + pub min_time: f64, + /// 最大执行时间 + pub max_time: f64, + /// 执行次数 + pub execution_count: u64, + /// 最近的执行时间列表 + pub recent_times: VecDeque, + /// 标准差 + pub standard_deviation: f64, + /// 95百分位数 + pub percentile_95: f64, + /// 99百分位数 + pub percentile_99: f64, +} + +impl Default for PerformanceStats { + fn default() -> Self { + Self { + total_time: 0.0, + average_time: 0.0, + min_time: f64::MAX, + max_time: 0.0, + execution_count: 0, + recent_times: VecDeque::new(), + standard_deviation: 0.0, + percentile_95: 0.0, + percentile_99: 0.0, + } + } +} + +/** + * 性能警告类型 + */ +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum PerformanceWarningType { + HighExecutionTime, + HighMemoryUsage, + HighCpuUsage, + FrequentGc, + LowFps, + HighEntityCount, +} + +/** + * 性能警告 + */ +#[derive(Debug, Clone)] +pub struct PerformanceWarning { + pub warning_type: PerformanceWarningType, + pub system_name: String, + pub message: String, + pub severity: WarningSeverity, + pub timestamp: u64, + pub value: f64, + pub threshold: f64, + pub suggestion: Option, +} + +/** + * 警告严重程度 + */ +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum WarningSeverity { + Low, + Medium, + High, + Critical, +} + +/** + * 性能阈值配置 + */ +#[derive(Debug, Clone)] +pub struct PerformanceThresholds { + /// 执行时间阈值(毫秒) + pub execution_time: ThresholdPair, + /// 内存使用阈值(MB) + pub memory_usage: ThresholdPair, + /// CPU使用率阈值(百分比) + pub cpu_usage: ThresholdPair, + /// FPS阈值 + pub fps: ThresholdPair, + /// 实体数量阈值 + pub entity_count: ThresholdPair, +} + +/** + * 阈值对(警告和临界值) + */ +#[derive(Debug, Clone)] +pub struct ThresholdPair { + pub warning: f64, + pub critical: f64, +} + +impl Default for PerformanceThresholds { + fn default() -> Self { + Self { + execution_time: ThresholdPair { warning: 16.67, critical: 33.33 }, // 60fps和30fps对应的帧时间 + memory_usage: ThresholdPair { warning: 100.0, critical: 200.0 }, // MB + cpu_usage: ThresholdPair { warning: 70.0, critical: 90.0 }, // 百分比 + fps: ThresholdPair { warning: 45.0, critical: 30.0 }, + entity_count: ThresholdPair { warning: 1000.0, critical: 5000.0 }, + } + } +} + +/** + * 高性能监控器 + * 用于监控ECS系统的性能表现,提供详细的分析和优化建议 + */ +pub struct PerformanceMonitor { + system_data: FxHashMap, + system_stats: FxHashMap, + warnings: Vec, + is_enabled: bool, + max_recent_samples: usize, + max_warnings: usize, + + // 性能阈值配置 + thresholds: PerformanceThresholds, + + // FPS监控 + fps_history: VecDeque, + last_frame_time: Option, + frame_count: u64, + fps_update_interval: u64, // 毫秒 + last_fps_update: u64, + current_fps: f64, + + // 内存监控 + memory_check_interval: u64, // 毫秒 + last_memory_check: u64, + memory_history: Vec, + + // GC监控 + gc_count: u64, + last_gc_check: u64, + gc_check_interval: u64, +} + +impl Default for PerformanceMonitor { + fn default() -> Self { + Self::new() + } +} + +impl PerformanceMonitor { + /** + * 创建新的性能监控器 + */ + pub fn new() -> Self { + Self { + system_data: FxHashMap::default(), + system_stats: FxHashMap::default(), + warnings: Vec::new(), + is_enabled: false, + max_recent_samples: 60, // 保留最近60帧的数据 + max_warnings: 100, // 最大警告数量 + thresholds: PerformanceThresholds::default(), + fps_history: VecDeque::new(), + last_frame_time: None, + frame_count: 0, + fps_update_interval: 1000, // 1秒更新一次FPS + last_fps_update: 0, + current_fps: 60.0, + memory_check_interval: 5000, // 5秒检查一次内存 + last_memory_check: 0, + memory_history: Vec::new(), + gc_count: 0, + last_gc_check: 0, + gc_check_interval: 1000, + } + } + + /** + * 启用性能监控 + */ + pub fn enable(&mut self) { + self.is_enabled = true; + } + + /** + * 禁用性能监控 + */ + pub fn disable(&mut self) { + self.is_enabled = false; + } + + /** + * 检查是否启用了性能监控 + */ + pub fn is_enabled(&self) -> bool { + self.is_enabled + } + + /** + * 开始监控系统性能 + * 返回开始时间戳(用于endMonitoring) + */ + pub fn start_monitoring(&self, _system_name: &str) -> Option { + if !self.is_enabled { + return None; + } + Some(Instant::now()) + } + + /** + * 结束监控并记录性能数据 + */ + pub fn end_monitoring( + &mut self, + system_name: &str, + start_time: Option, + entity_count: usize + ) { + if !self.is_enabled || start_time.is_none() { + return; + } + + let end_time = Instant::now(); + let execution_time = end_time.duration_since(start_time.unwrap()).as_secs_f64() * 1000.0; + let average_time_per_entity = if entity_count > 0 { + execution_time / entity_count as f64 + } else { + 0.0 + }; + + // 更新当前性能数据 + let data = PerformanceData { + name: system_name.to_string(), + execution_time, + entity_count, + average_time_per_entity, + last_update_time: current_timestamp(), + memory_usage: None, + cpu_usage: None, + }; + + self.system_data.insert(system_name.to_string(), data); + + // 更新统计信息 + self.update_stats(system_name, execution_time); + + // 检查警告 + self.check_warnings(system_name, execution_time, entity_count); + } + + /** + * 更新系统统计信息 + */ + fn update_stats(&mut self, system_name: &str, execution_time: f64) { + { + let stats = self.system_stats.entry(system_name.to_string()).or_insert_with(PerformanceStats::default); + + // 更新基本统计 + stats.total_time += execution_time; + stats.execution_count += 1; + stats.average_time = stats.total_time / stats.execution_count as f64; + stats.min_time = stats.min_time.min(execution_time); + stats.max_time = stats.max_time.max(execution_time); + + // 更新最近时间列表 + stats.recent_times.push_back(execution_time); + if stats.recent_times.len() > self.max_recent_samples { + stats.recent_times.pop_front(); + } + } + + // 计算高级统计信息 + if let Some(stats) = self.system_stats.get_mut(system_name) { + Self::calculate_advanced_stats_static(stats); + } + } + + /** + * 计算高级统计信息 + */ + fn calculate_advanced_stats_static(stats: &mut PerformanceStats) { + if stats.recent_times.is_empty() { + return; + } + + // 计算标准差 + let mean: f64 = stats.recent_times.iter().sum::() / stats.recent_times.len() as f64; + let variance: f64 = stats.recent_times.iter() + .map(|&time| (time - mean).powi(2)) + .sum::() / stats.recent_times.len() as f64; + stats.standard_deviation = variance.sqrt(); + + // 计算百分位数 + let mut sorted_times: Vec = stats.recent_times.iter().cloned().collect(); + sorted_times.sort_by(|a, b| a.partial_cmp(b).unwrap()); + let len = sorted_times.len(); + + if len > 0 { + let index_95 = ((len as f64 * 0.95) as usize).min(len - 1); + let index_99 = ((len as f64 * 0.99) as usize).min(len - 1); + + stats.percentile_95 = sorted_times[index_95]; + stats.percentile_99 = sorted_times[index_99]; + } + } + + /** + * 检查性能警告 + */ + fn check_warnings(&mut self, system_name: &str, execution_time: f64, entity_count: usize) { + // 检查执行时间 + if execution_time > self.thresholds.execution_time.critical { + self.add_warning(PerformanceWarning { + warning_type: PerformanceWarningType::HighExecutionTime, + system_name: system_name.to_string(), + message: format!("System {} execution time is critically high: {:.2}ms", system_name, execution_time), + severity: WarningSeverity::Critical, + timestamp: current_timestamp(), + value: execution_time, + threshold: self.thresholds.execution_time.critical, + suggestion: Some("Consider optimizing system logic or reducing entity count".to_string()), + }); + } else if execution_time > self.thresholds.execution_time.warning { + self.add_warning(PerformanceWarning { + warning_type: PerformanceWarningType::HighExecutionTime, + system_name: system_name.to_string(), + message: format!("System {} execution time is high: {:.2}ms", system_name, execution_time), + severity: WarningSeverity::Medium, + timestamp: current_timestamp(), + value: execution_time, + threshold: self.thresholds.execution_time.warning, + suggestion: Some("Monitor system performance and consider optimization".to_string()), + }); + } + + // 检查实体数量 + let entity_count_f64 = entity_count as f64; + if entity_count_f64 > self.thresholds.entity_count.critical { + self.add_warning(PerformanceWarning { + warning_type: PerformanceWarningType::HighEntityCount, + system_name: system_name.to_string(), + message: format!("System {} processing critically high entity count: {}", system_name, entity_count), + severity: WarningSeverity::Critical, + timestamp: current_timestamp(), + value: entity_count_f64, + threshold: self.thresholds.entity_count.critical, + suggestion: Some("Consider entity pooling or batch processing".to_string()), + }); + } else if entity_count_f64 > self.thresholds.entity_count.warning { + self.add_warning(PerformanceWarning { + warning_type: PerformanceWarningType::HighEntityCount, + system_name: system_name.to_string(), + message: format!("System {} processing high entity count: {}", system_name, entity_count), + severity: WarningSeverity::Medium, + timestamp: current_timestamp(), + value: entity_count_f64, + threshold: self.thresholds.entity_count.warning, + suggestion: Some("Monitor entity count and consider optimization if it continues growing".to_string()), + }); + } + } + + /** + * 添加警告 + */ + fn add_warning(&mut self, warning: PerformanceWarning) { + self.warnings.push(warning); + + // 限制警告数量 + if self.warnings.len() > self.max_warnings { + self.warnings.remove(0); + } + } + + /** + * 获取系统的当前性能数据 + */ + pub fn get_system_data(&self, system_name: &str) -> Option<&PerformanceData> { + self.system_data.get(system_name) + } + + /** + * 获取系统的统计信息 + */ + pub fn get_system_stats(&self, system_name: &str) -> Option<&PerformanceStats> { + self.system_stats.get(system_name) + } + + /** + * 获取所有系统的性能数据 + */ + pub fn get_all_system_data(&self) -> &FxHashMap { + &self.system_data + } + + /** + * 获取所有系统的统计信息 + */ + pub fn get_all_system_stats(&self) -> &FxHashMap { + &self.system_stats + } + + /** + * 获取性能报告 + */ + pub fn get_performance_report(&self) -> String { + if !self.is_enabled { + return "Performance monitoring is disabled.".to_string(); + } + + let mut lines = Vec::new(); + lines.push("=== ECS Performance Report ===".to_string()); + lines.push("".to_string()); + + // 按平均执行时间排序 + let mut sorted_systems: Vec<_> = self.system_stats.iter().collect(); + sorted_systems.sort_by(|a, b| b.1.average_time.partial_cmp(&a.1.average_time).unwrap()); + + for (system_name, stats) in sorted_systems { + if let Some(data) = self.system_data.get(system_name) { + lines.push(format!("System: {}", system_name)); + lines.push(format!(" Current: {:.2}ms ({} entities)", data.execution_time, data.entity_count)); + lines.push(format!(" Average: {:.2}ms", stats.average_time)); + lines.push(format!(" Min/Max: {:.2}ms / {:.2}ms", stats.min_time, stats.max_time)); + lines.push(format!(" Total: {:.2}ms ({} calls)", stats.total_time, stats.execution_count)); + + if data.average_time_per_entity > 0.0 { + lines.push(format!(" Per Entity: {:.4}ms", data.average_time_per_entity)); + } + + lines.push("".to_string()); + } + } + + // 总体统计 + let total_current_time: f64 = self.system_data.values() + .map(|data| data.execution_time) + .sum(); + + lines.push(format!("Total Frame Time: {:.2}ms", total_current_time)); + lines.push(format!("Systems Count: {}", self.system_data.len())); + lines.push(format!("Current FPS: {:.1}", self.current_fps)); + + lines.join("\n") + } + + /** + * 获取性能警告 + */ + pub fn get_performance_warnings(&self, threshold_ms: Option) -> Vec { + let threshold = threshold_ms.unwrap_or(16.67); // 默认60fps阈值 + let mut warnings = Vec::new(); + + for (system_name, data) in &self.system_data { + if data.execution_time > threshold { + warnings.push(format!("{}: {:.2}ms (>{:.0}ms)", + system_name, data.execution_time, threshold)); + } + } + + warnings + } + + /** + * 获取所有警告 + */ + pub fn get_warnings(&self) -> &[PerformanceWarning] { + &self.warnings + } + + /** + * 清除所有警告 + */ + pub fn clear_warnings(&mut self) { + self.warnings.clear(); + } + + /** + * 重置所有性能数据 + */ + pub fn reset(&mut self) { + self.system_data.clear(); + self.system_stats.clear(); + self.warnings.clear(); + } + + /** + * 重置指定系统的性能数据 + */ + pub fn reset_system(&mut self, system_name: &str) { + self.system_data.remove(system_name); + self.system_stats.remove(system_name); + } + + /** + * 设置最大保留样本数 + */ + pub fn set_max_recent_samples(&mut self, max_samples: usize) { + self.max_recent_samples = max_samples; + + // 裁剪现有数据 + for stats in self.system_stats.values_mut() { + while stats.recent_times.len() > max_samples { + stats.recent_times.pop_front(); + } + } + } + + /** + * 设置性能阈值 + */ + pub fn set_thresholds(&mut self, thresholds: PerformanceThresholds) { + self.thresholds = thresholds; + } + + /** + * 获取性能阈值 + */ + pub fn get_thresholds(&self) -> &PerformanceThresholds { + &self.thresholds + } + + /** + * 更新FPS + */ + pub fn update_fps(&mut self) { + let now = Instant::now(); + + if let Some(last_time) = self.last_frame_time { + let frame_time = now.duration_since(last_time).as_secs_f64() * 1000.0; + self.fps_history.push_back(1000.0 / frame_time); + + // 保持历史记录在合理范围内 + if self.fps_history.len() > self.max_recent_samples { + self.fps_history.pop_front(); + } + + // 每秒更新一次平均FPS + let current_time = current_timestamp(); + if current_time - self.last_fps_update > self.fps_update_interval { + if !self.fps_history.is_empty() { + self.current_fps = self.fps_history.iter().sum::() / self.fps_history.len() as f64; + } + self.last_fps_update = current_time; + } + } + + self.last_frame_time = Some(now); + self.frame_count += 1; + } + + /** + * 获取当前FPS + */ + pub fn get_current_fps(&self) -> f64 { + self.current_fps + } + + /** + * 获取平均FPS + */ + pub fn get_average_fps(&self) -> f64 { + if self.fps_history.is_empty() { + 60.0 + } else { + self.fps_history.iter().sum::() / self.fps_history.len() as f64 + } + } +} + +// 辅助函数 + +/** + * 获取当前时间戳(毫秒) + */ +fn current_timestamp() -> u64 { + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default() + .as_millis() as u64 +} + +#[cfg(test)] +mod tests { + use super::*; + use std::thread; + use std::time::Duration; + + #[test] + fn test_performance_monitor_creation() { + let monitor = PerformanceMonitor::new(); + assert!(!monitor.enabled()); + assert_eq!(monitor.get_current_fps(), 60.0); + assert!(monitor.get_all_system_data().is_empty()); + } + + #[test] + fn test_performance_monitor_enable_disable() { + let mut monitor = PerformanceMonitor::new(); + + assert!(!monitor.enabled()); + + monitor.enable(); + assert!(monitor.enabled()); + + monitor.disable(); + assert!(!monitor.enabled()); + } + + #[test] + fn test_performance_monitoring_disabled() { + let mut monitor = PerformanceMonitor::new(); + let start_time = monitor.start_monitoring("TestSystem"); + + assert!(start_time.is_none()); + + monitor.end_monitoring("TestSystem", start_time, 10); + assert!(monitor.get_system_data("TestSystem").is_none()); + } + + #[test] + fn test_performance_monitoring_enabled() { + let mut monitor = PerformanceMonitor::new(); + monitor.enable(); + + let start_time = monitor.start_monitoring("TestSystem"); + assert!(start_time.is_some()); + + thread::sleep(Duration::from_millis(10)); + + monitor.end_monitoring("TestSystem", start_time, 5); + + let data = monitor.get_system_data("TestSystem"); + assert!(data.is_some()); + + let data = data.unwrap(); + assert_eq!(data.name, "TestSystem"); + assert_eq!(data.entity_count, 5); + assert!(data.execution_time >= 10.0); + assert!(data.average_time_per_entity > 0.0); + } + + #[test] + fn test_performance_stats_update() { + let mut monitor = PerformanceMonitor::new(); + monitor.enable(); + + // 模拟多次执行 + for i in 0..3 { + let start_time = monitor.start_monitoring("TestSystem"); + thread::sleep(Duration::from_millis(5 + i)); // 不同的执行时间 + monitor.end_monitoring("TestSystem", start_time, 10); + } + + let stats = monitor.get_system_stats("TestSystem"); + assert!(stats.is_some()); + + let stats = stats.unwrap(); + assert_eq!(stats.execution_count, 3); + assert!(stats.total_time > 0.0); + assert!(stats.average_time > 0.0); + assert!(stats.min_time > 0.0); + assert!(stats.max_time > 0.0); + assert_eq!(stats.recent_times.len(), 3); + } + + #[test] + fn test_performance_warnings() { + let mut monitor = PerformanceMonitor::new(); + monitor.enable(); + + // 设置较低的阈值以触发警告 + let mut thresholds = PerformanceThresholds::default(); + thresholds.execution_time.warning = 1.0; + thresholds.execution_time.critical = 2.0; + monitor.set_thresholds(thresholds); + + let start_time = monitor.start_monitoring("TestSystem"); + thread::sleep(Duration::from_millis(5)); // 足够触发警告 + monitor.end_monitoring("TestSystem", start_time, 10); + + let warnings = monitor.get_warnings(); + assert!(!warnings.is_empty()); + assert_eq!(warnings[0].system_name, "TestSystem"); + assert_eq!(warnings[0].warning_type, PerformanceWarningType::HighExecutionTime); + } + + #[test] + fn test_performance_report() { + let mut monitor = PerformanceMonitor::new(); + monitor.enable(); + + let start_time = monitor.start_monitoring("TestSystem"); + thread::sleep(Duration::from_millis(5)); + monitor.end_monitoring("TestSystem", start_time, 10); + + let report = monitor.get_performance_report(); + assert!(report.contains("ECS Performance Report")); + assert!(report.contains("TestSystem")); + } + + #[test] + fn test_fps_monitoring() { + let mut monitor = PerformanceMonitor::new(); + + // 模拟几帧 + for _ in 0..3 { + monitor.update_fps(); + thread::sleep(Duration::from_millis(16)); // ~60fps + } + + let fps = monitor.get_current_fps(); + assert!(fps > 0.0); + } + + #[test] + fn test_reset_functionality() { + let mut monitor = PerformanceMonitor::new(); + monitor.enable(); + + let start_time = monitor.start_monitoring("TestSystem"); + monitor.end_monitoring("TestSystem", start_time, 10); + + assert!(monitor.get_system_data("TestSystem").is_some()); + + monitor.reset(); + assert!(monitor.get_system_data("TestSystem").is_none()); + assert!(monitor.get_warnings().is_empty()); + } + + #[test] + fn test_max_recent_samples() { + let mut monitor = PerformanceMonitor::new(); + monitor.enable(); + monitor.set_max_recent_samples(2); + + // 执行3次,但只应该保留最近2次的数据 + for _ in 0..3 { + let start_time = monitor.start_monitoring("TestSystem"); + monitor.end_monitoring("TestSystem", start_time, 10); + } + + let stats = monitor.get_system_stats("TestSystem").unwrap(); + assert_eq!(stats.recent_times.len(), 2); + assert_eq!(stats.execution_count, 3); // 总次数应该还是3 + } + + #[test] + fn test_system_reset() { + let mut monitor = PerformanceMonitor::new(); + monitor.enable(); + + let start_time1 = monitor.start_monitoring("TestSystem1"); + monitor.end_monitoring("TestSystem1", start_time1, 10); + + let start_time2 = monitor.start_monitoring("TestSystem2"); + monitor.end_monitoring("TestSystem2", start_time2, 20); + + assert!(monitor.get_system_data("TestSystem1").is_some()); + assert!(monitor.get_system_data("TestSystem2").is_some()); + + monitor.reset_system("TestSystem1"); + + assert!(monitor.get_system_data("TestSystem1").is_none()); + assert!(monitor.get_system_data("TestSystem2").is_some()); + } + + #[test] + fn test_percentile_calculations() { + let mut monitor = PerformanceMonitor::new(); + monitor.enable(); + + // 添加一些已知的执行时间 + let times = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]; + + for &time in × { + // 直接设置执行时间进行测试 + monitor.update_stats("TestSystem", time); + } + + let stats = monitor.get_system_stats("TestSystem").unwrap(); + + // 95%应该是9.5左右,99%应该是9.9左右 + assert!(stats.percentile_95 >= 9.0); + assert!(stats.percentile_99 >= 9.0); + + // 标准差应该大于0 + assert!(stats.standard_deviation > 0.0); + } +} \ No newline at end of file diff --git a/packages/core-rust/src/utils/pool.rs b/packages/core-rust/src/utils/pool.rs new file mode 100644 index 00000000..1d3058df --- /dev/null +++ b/packages/core-rust/src/utils/pool.rs @@ -0,0 +1,871 @@ +use rustc_hash::FxHashMap; +use std::any::Any; + +/** + * 可池化对象trait + */ +pub trait Poolable: Send + Sync { + /** + * 重置对象状态,准备重用 + */ + fn reset(&mut self); + + /** + * 获取对象的估算大小(字节) + */ + fn estimated_size(&self) -> usize { + std::mem::size_of_val(self) + } +} + +/** + * 对象池统计信息 + */ +#[derive(Debug, Clone)] +pub struct PoolStats { + /// 池中对象数量 + pub size: usize, + /// 池的最大大小 + pub max_size: usize, + /// 总共创建的对象数量 + pub total_created: u64, + /// 总共获取的次数 + pub total_obtained: u64, + /// 总共释放的次数 + pub total_released: u64, + /// 命中率(从池中获取的比例) + pub hit_rate: f64, + /// 内存使用估算(字节) + pub estimated_memory_usage: usize, +} + +impl Default for PoolStats { + fn default() -> Self { + Self { + size: 0, + max_size: 0, + total_created: 0, + total_obtained: 0, + total_released: 0, + hit_rate: 0.0, + estimated_memory_usage: 0, + } + } +} + +/** + * 高性能通用对象池 + * 支持任意类型的对象池化,包含详细的统计信息 + */ +pub struct Pool { + /// 池中的对象 + objects: Vec, + /// 创建对象的函数 + create_fn: Box T + Send + Sync>, + /// 池的最大大小 + max_size: usize, + /// 统计信息 + stats: PoolStats, + /// 估算的单个对象大小 + object_size: usize, +} + +impl Pool { + /** + * 创建新的对象池 + */ + pub fn new(create_fn: F, max_size: usize, estimated_object_size: usize) -> Self + where + F: Fn() -> T + Send + Sync + 'static, + { + Self { + objects: Vec::new(), + create_fn: Box::new(create_fn), + max_size, + stats: PoolStats { + max_size, + ..Default::default() + }, + object_size: estimated_object_size, + } + } + + /** + * 从池中获取对象 + */ + pub fn obtain(&mut self) -> T { + self.stats.total_obtained += 1; + + if let Some(mut obj) = self.objects.pop() { + self.stats.size -= 1; + self.update_hit_rate(); + self.update_memory_usage(); + obj.reset(); // 重置对象状态 + obj + } else { + // 池中没有可用对象,创建新对象 + self.stats.total_created += 1; + self.update_hit_rate(); + (self.create_fn)() + } + } + + /** + * 释放对象回池中 + */ + pub fn release(&mut self, mut obj: T) { + self.stats.total_released += 1; + + // 如果池未满,将对象放回池中 + if self.stats.size < self.max_size { + obj.reset(); + self.objects.push(obj); + self.stats.size += 1; + self.update_memory_usage(); + } + // 如果池已满,让对象被drop + } + + /** + * 获取池统计信息 + */ + pub fn get_stats(&self) -> &PoolStats { + &self.stats + } + + /** + * 清空池 + */ + pub fn clear(&mut self) { + self.objects.clear(); + self.stats.size = 0; + self.update_memory_usage(); + } + + /** + * 压缩池(移除多余的对象) + */ + pub fn compact(&mut self, target_size: Option) { + let target = target_size.unwrap_or(self.objects.len() / 2); + + while self.objects.len() > target { + self.objects.pop(); + self.stats.size -= 1; + } + + self.update_memory_usage(); + } + + /** + * 预填充池 + */ + pub fn prewarm(&mut self, count: usize) { + let actual_count = count.min(self.max_size - self.objects.len()); + + for _ in 0..actual_count { + let mut obj = (self.create_fn)(); + obj.reset(); + self.objects.push(obj); + self.stats.total_created += 1; + self.stats.size += 1; + } + + self.update_memory_usage(); + } + + /** + * 设置最大池大小 + */ + pub fn set_max_size(&mut self, max_size: usize) { + self.max_size = max_size; + self.stats.max_size = max_size; + + // 如果当前池大小超过新的最大值,进行压缩 + if self.objects.len() > max_size { + self.compact(Some(max_size)); + } + } + + /** + * 获取池中可用对象数量 + */ + pub fn get_available_count(&self) -> usize { + self.objects.len() + } + + /** + * 检查池是否为空 + */ + pub fn is_empty(&self) -> bool { + self.objects.is_empty() + } + + /** + * 检查池是否已满 + */ + pub fn is_full(&self) -> bool { + self.objects.len() >= self.max_size + } + + /** + * 获取池的最大大小 + */ + pub fn max_size(&self) -> usize { + self.max_size + } + + /** + * 更新命中率 + */ + fn update_hit_rate(&mut self) { + if self.stats.total_obtained == 0 { + self.stats.hit_rate = 0.0; + } else { + let hits = self.stats.total_obtained - self.stats.total_created; + self.stats.hit_rate = hits as f64 / self.stats.total_obtained as f64; + } + } + + /** + * 更新内存使用估算 + */ + fn update_memory_usage(&mut self) { + self.stats.estimated_memory_usage = self.stats.size * self.object_size; + } +} + +/** + * Pool trait object for heterogeneous storage + */ +trait AnyPool: Send + Sync { + fn clear(&mut self); + fn compact(&mut self); + fn get_stats(&self) -> PoolStats; + fn as_any(&self) -> &dyn Any; + fn as_any_mut(&mut self) -> &mut dyn Any; +} + +impl AnyPool for Pool { + fn clear(&mut self) { + Pool::clear(self); + } + + fn compact(&mut self) { + Pool::compact(self, None); + } + + fn get_stats(&self) -> PoolStats { + self.stats.clone() + } + + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } +} + +/** + * 池管理器 + * 统一管理所有对象池 + */ +pub struct PoolManager { + /// 池映射 + pools: FxHashMap>, + /// 自动压缩间隔(毫秒) + auto_compact_interval: u64, + /// 上次压缩时间 + last_compact_time: u64, +} + +impl PoolManager { + /** + * 创建新的池管理器 + */ + pub fn new() -> Self { + Self { + pools: FxHashMap::default(), + auto_compact_interval: 60000, // 60秒 + last_compact_time: 0, + } + } + + /** + * 注册池 + */ + pub fn register_pool(&mut self, name: String, pool: Pool) { + self.pools.insert(name, Box::new(pool)); + } + + /** + * 获取池 + */ + pub fn get_pool(&mut self, name: &str) -> Option<&mut Pool> { + if let Some(pool) = self.pools.get_mut(name) { + pool.as_any_mut().downcast_mut::>() + } else { + None + } + } + + /** + * 创建或获取池 + */ + pub fn create_pool( + &mut self, + name: String, + create_fn: F, + max_size: usize, + estimated_object_size: usize, + ) -> &mut Pool + where + T: Poolable + 'static, + F: Fn() -> T + Send + Sync + 'static, + { + if !self.pools.contains_key(&name) { + let pool = Pool::new(create_fn, max_size, estimated_object_size); + self.pools.insert(name.clone(), Box::new(pool)); + } + + self.get_pool(&name).unwrap() + } + + /** + * 更新池管理器(应在游戏循环中调用) + */ + pub fn update(&mut self) { + let now = current_timestamp(); + + if now - self.last_compact_time > self.auto_compact_interval { + self.compact_all_pools(); + self.last_compact_time = now; + } + } + + /** + * 移除池 + */ + pub fn remove_pool(&mut self, name: &str) -> bool { + if let Some(mut pool) = self.pools.remove(name) { + pool.clear(); + true + } else { + false + } + } + + /** + * 获取所有池名称 + */ + pub fn get_pool_names(&self) -> Vec { + self.pools.keys().cloned().collect() + } + + /** + * 获取池数量 + */ + pub fn get_pool_count(&self) -> usize { + self.pools.len() + } + + /** + * 压缩所有池 + */ + pub fn compact_all_pools(&mut self) { + for pool in self.pools.values_mut() { + pool.compact(); + } + } + + /** + * 清空所有池 + */ + pub fn clear_all_pools(&mut self) { + for pool in self.pools.values_mut() { + pool.clear(); + } + } + + /** + * 获取所有池的统计信息 + */ + pub fn get_all_stats(&self) -> FxHashMap { + let mut stats = FxHashMap::default(); + + for (name, pool) in &self.pools { + stats.insert(name.clone(), pool.get_stats()); + } + + stats + } + + /** + * 获取总体统计信息 + */ + pub fn get_global_stats(&self) -> PoolStats { + let mut total_size = 0; + let mut total_max_size = 0; + let mut total_created = 0; + let mut total_obtained = 0; + let mut total_released = 0; + let mut total_memory_usage = 0; + + for pool in self.pools.values() { + let stats = pool.get_stats(); + total_size += stats.size; + total_max_size += stats.max_size; + total_created += stats.total_created; + total_obtained += stats.total_obtained; + total_released += stats.total_released; + total_memory_usage += stats.estimated_memory_usage; + } + + let hit_rate = if total_obtained == 0 { + 0.0 + } else { + (total_obtained - total_created) as f64 / total_obtained as f64 + }; + + PoolStats { + size: total_size, + max_size: total_max_size, + total_created, + total_obtained, + total_released, + hit_rate, + estimated_memory_usage: total_memory_usage, + } + } + + /** + * 获取格式化的统计信息字符串 + */ + pub fn get_stats_string(&self) -> String { + let mut lines = vec![ + "=== Pool Manager Statistics ===".to_string(), + "".to_string(), + ]; + + if self.pools.is_empty() { + lines.push("No pools registered".to_string()); + return lines.join("\n"); + } + + let global_stats = self.get_global_stats(); + lines.push(format!("Total Pools: {}", self.pools.len())); + lines.push(format!("Global Hit Rate: {:.1}%", global_stats.hit_rate * 100.0)); + lines.push(format!( + "Global Memory Usage: {:.1} KB", + global_stats.estimated_memory_usage as f64 / 1024.0 + )); + lines.push("".to_string()); + + for (name, pool) in &self.pools { + let stats = pool.get_stats(); + lines.push(format!("{}:", name)); + lines.push(format!(" Size: {}/{}", stats.size, stats.max_size)); + lines.push(format!(" Hit Rate: {:.1}%", stats.hit_rate * 100.0)); + lines.push(format!( + " Memory: {:.1} KB", + stats.estimated_memory_usage as f64 / 1024.0 + )); + lines.push("".to_string()); + } + + lines.join("\n") + } + + /** + * 设置自动压缩间隔 + */ + pub fn set_auto_compact_interval(&mut self, interval_ms: u64) { + self.auto_compact_interval = interval_ms; + } + + /** + * 预填充所有池 + */ + pub fn prewarm_all_pools(&mut self) { + for pool in self.pools.values_mut() { + let stats = pool.get_stats(); + let prewarm_count = (stats.max_size as f64 * 0.2) as usize; // 预填充20% + // 注意:这里需要访问具体的池类型来调用prewarm + // 在实际使用中,可能需要为AnyPool trait添加prewarm方法 + } + } + + /** + * 重置池管理器 + */ + pub fn reset(&mut self) { + self.clear_all_pools(); + self.pools.clear(); + self.last_compact_time = 0; + } +} + +impl Default for PoolManager { + fn default() -> Self { + Self::new() + } +} + +// 辅助函数 +fn current_timestamp() -> u64 { + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap_or_default() + .as_millis() as u64 +} + +#[cfg(test)] +mod tests { + use super::*; + + // 测试对象 + #[derive(Debug, Clone)] + struct TestObject { + value: i32, + data: String, + } + + impl TestObject { + fn new() -> Self { + Self { + value: 0, + data: String::new(), + } + } + + fn with_value(value: i32) -> Self { + Self { + value, + data: format!("data_{}", value), + } + } + } + + impl Poolable for TestObject { + fn reset(&mut self) { + self.value = 0; + self.data.clear(); + } + + fn estimated_size(&self) -> usize { + std::mem::size_of::() + self.data.capacity() + } + } + + #[test] + fn test_pool_creation() { + let pool: Pool = Pool::new(TestObject::new, 10, 64); + + assert_eq!(pool.get_available_count(), 0); + assert_eq!(pool.max_size(), 10); + assert!(pool.is_empty()); + assert!(!pool.is_full()); + } + + #[test] + fn test_pool_obtain_release() { + let mut pool: Pool = Pool::new(TestObject::new, 10, 64); + + // 获取对象(池为空,应该创建新对象) + let obj = pool.obtain(); + assert_eq!(obj.value, 0); + + let stats = pool.get_stats(); + assert_eq!(stats.total_created, 1); + assert_eq!(stats.total_obtained, 1); + + // 释放对象 + pool.release(obj); + + let stats = pool.get_stats(); + assert_eq!(stats.total_released, 1); + assert_eq!(stats.size, 1); + assert_eq!(pool.get_available_count(), 1); + } + + #[test] + fn test_pool_reuse() { + let mut pool: Pool = Pool::new(TestObject::new, 10, 64); + + // 创建并释放一个对象 + let mut obj = pool.obtain(); + obj.value = 42; + obj.data = "test".to_string(); + pool.release(obj); + + // 再次获取应该得到重置后的对象 + let obj = pool.obtain(); + assert_eq!(obj.value, 0); + assert!(obj.data.is_empty()); + + let stats = pool.get_stats(); + assert_eq!(stats.total_created, 1); // 只创建了一次 + assert_eq!(stats.total_obtained, 2); // 获取了两次 + assert!(stats.hit_rate > 0.0); // 有命中率 + } + + #[test] + fn test_pool_max_size() { + let mut pool: Pool = Pool::new(TestObject::new, 2, 64); + + // 释放3个对象,但池最大大小为2 + pool.release(TestObject::new()); + pool.release(TestObject::new()); + pool.release(TestObject::new()); // 这个应该被丢弃 + + assert_eq!(pool.get_available_count(), 2); + assert!(pool.is_full()); + } + + #[test] + fn test_pool_prewarm() { + let mut pool: Pool = Pool::new(TestObject::new, 10, 64); + + pool.prewarm(5); + + assert_eq!(pool.get_available_count(), 5); + + let stats = pool.get_stats(); + assert_eq!(stats.total_created, 5); + assert_eq!(stats.size, 5); + } + + #[test] + fn test_pool_compact() { + let mut pool: Pool = Pool::new(TestObject::new, 10, 64); + + // 预填充 + pool.prewarm(8); + assert_eq!(pool.get_available_count(), 8); + + // 压缩到一半 + pool.compact(Some(4)); + assert_eq!(pool.get_available_count(), 4); + + // 默认压缩 + pool.compact(None); + assert_eq!(pool.get_available_count(), 2); + } + + #[test] + fn test_pool_clear() { + let mut pool: Pool = Pool::new(TestObject::new, 10, 64); + + pool.prewarm(5); + assert_eq!(pool.get_available_count(), 5); + + pool.clear(); + assert_eq!(pool.get_available_count(), 0); + assert!(pool.is_empty()); + } + + #[test] + fn test_pool_set_max_size() { + let mut pool: Pool = Pool::new(TestObject::new, 10, 64); + + pool.prewarm(8); + assert_eq!(pool.get_available_count(), 8); + + // 减小最大大小应该自动压缩 + pool.set_max_size(5); + assert_eq!(pool.max_size(), 5); + assert_eq!(pool.get_available_count(), 5); + } + + #[test] + fn test_pool_stats() { + let mut pool: Pool = Pool::new(TestObject::new, 10, 64); + + // 获取和释放一些对象 + let obj1 = pool.obtain(); + let obj2 = pool.obtain(); + pool.release(obj1); + + let obj3 = pool.obtain(); // 应该重用obj1 + pool.release(obj2); + pool.release(obj3); + + let stats = pool.get_stats(); + assert_eq!(stats.total_created, 2); + assert_eq!(stats.total_obtained, 3); + assert_eq!(stats.total_released, 3); + assert!(stats.hit_rate > 0.0); + assert_eq!(stats.size, 2); + } + + #[test] + fn test_pool_manager_creation() { + let manager = PoolManager::new(); + assert_eq!(manager.get_pool_count(), 0); + assert!(manager.get_pool_names().is_empty()); + } + + #[test] + fn test_pool_manager_register_get() { + let mut manager = PoolManager::new(); + let pool: Pool = Pool::new(TestObject::new, 10, 64); + + manager.register_pool("test_objects".to_string(), pool); + assert_eq!(manager.get_pool_count(), 1); + + let retrieved_pool = manager.get_pool::("test_objects"); + assert!(retrieved_pool.is_some()); + + let non_existent = manager.get_pool::("non_existent"); + assert!(non_existent.is_none()); + } + + #[test] + fn test_pool_manager_create_pool() { + let mut manager = PoolManager::new(); + + let pool = manager.create_pool( + "test_objects".to_string(), + TestObject::new, + 10, + 64, + ); + + assert_eq!(pool.max_size(), 10); + assert_eq!(manager.get_pool_count(), 1); + } + + #[test] + fn test_pool_manager_remove_pool() { + let mut manager = PoolManager::new(); + let pool: Pool = Pool::new(TestObject::new, 10, 64); + + manager.register_pool("test_objects".to_string(), pool); + assert_eq!(manager.get_pool_count(), 1); + + assert!(manager.remove_pool("test_objects")); + assert_eq!(manager.get_pool_count(), 0); + + assert!(!manager.remove_pool("non_existent")); + } + + #[test] + fn test_pool_manager_global_stats() { + let mut manager = PoolManager::new(); + + let pool1: Pool = Pool::new(TestObject::new, 10, 64); + let pool2: Pool = Pool::new(TestObject::new, 20, 128); + + manager.register_pool("pool1".to_string(), pool1); + manager.register_pool("pool2".to_string(), pool2); + + let global_stats = manager.get_global_stats(); + assert_eq!(global_stats.max_size, 30); // 10 + 20 + } + + #[test] + fn test_pool_manager_clear_all() { + let mut manager = PoolManager::new(); + + let mut pool: Pool = Pool::new(TestObject::new, 10, 64); + pool.prewarm(5); + + manager.register_pool("test_objects".to_string(), pool); + + manager.clear_all_pools(); + + if let Some(pool) = manager.get_pool::("test_objects") { + assert!(pool.is_empty()); + } + } + + #[test] + fn test_pool_manager_compact_all() { + let mut manager = PoolManager::new(); + + let mut pool: Pool = Pool::new(TestObject::new, 10, 64); + pool.prewarm(8); + + manager.register_pool("test_objects".to_string(), pool); + + manager.compact_all_pools(); + + if let Some(pool) = manager.get_pool::("test_objects") { + assert!(pool.get_available_count() <= 4); // 压缩后应该减少 + } + } + + #[test] + fn test_pool_manager_stats_string() { + let mut manager = PoolManager::new(); + + let pool: Pool = Pool::new(TestObject::new, 10, 64); + manager.register_pool("test_objects".to_string(), pool); + + let stats_string = manager.get_stats_string(); + assert!(stats_string.contains("Pool Manager Statistics")); + assert!(stats_string.contains("test_objects")); + } + + #[test] + fn test_pool_manager_reset() { + let mut manager = PoolManager::new(); + + let pool: Pool = Pool::new(TestObject::new, 10, 64); + manager.register_pool("test_objects".to_string(), pool); + + assert_eq!(manager.get_pool_count(), 1); + + manager.reset(); + + assert_eq!(manager.get_pool_count(), 0); + assert_eq!(manager.last_compact_time, 0); + } + + // 测试不同类型的Poolable对象 + #[derive(Debug)] + struct AnotherTestObject { + id: u32, + active: bool, + } + + impl AnotherTestObject { + fn new() -> Self { + Self { + id: 0, + active: false, + } + } + } + + impl Poolable for AnotherTestObject { + fn reset(&mut self) { + self.id = 0; + self.active = false; + } + } + + #[test] + fn test_pool_manager_multiple_types() { + let mut manager = PoolManager::new(); + + let pool1: Pool = Pool::new(TestObject::new, 10, 64); + let pool2: Pool = Pool::new(AnotherTestObject::new, 5, 32); + + manager.register_pool("test_objects".to_string(), pool1); + manager.register_pool("another_objects".to_string(), pool2); + + assert_eq!(manager.get_pool_count(), 2); + + let pool1 = manager.get_pool::("test_objects"); + assert!(pool1.is_some()); + + let pool2 = manager.get_pool::("another_objects"); + assert!(pool2.is_some()); + + // 尝试用错误的类型获取池 + let wrong_pool = manager.get_pool::("test_objects"); + assert!(wrong_pool.is_none()); + } +} \ No newline at end of file diff --git a/packages/core-rust/src/utils/sparse_set.rs b/packages/core-rust/src/utils/sparse_set.rs new file mode 100644 index 00000000..c79e1421 --- /dev/null +++ b/packages/core-rust/src/utils/sparse_set.rs @@ -0,0 +1,238 @@ +/** + * 高性能稀疏集合数据结构 + * + * SparseSet是ECS系统中常用的数据结构,提供O(1)的插入、删除和查找操作 + * 同时支持密集数组迭代,非常适合存储稀疏的实体组件数据 + */ +pub struct SparseSet { + /// 稀疏数组,索引到密集数组的映射 + sparse: Vec>, + + /// 密集数组,存储实际的值 + dense: Vec, + + /// 当前元素数量 + size: usize, +} + +impl SparseSet { + /** + * 创建新的稀疏集合 + */ + pub fn new() -> Self { + Self { + sparse: Vec::new(), + dense: Vec::new(), + size: 0, + } + } + + /** + * 创建指定容量的稀疏集合 + */ + pub fn with_capacity(sparse_capacity: usize, dense_capacity: usize) -> Self { + Self { + sparse: vec![None; sparse_capacity], + dense: Vec::with_capacity(dense_capacity), + size: 0, + } + } + + /** + * 插入值 + */ + pub fn insert(&mut self, value: u32) -> bool { + let sparse_index = value as usize; + + // 确保稀疏数组足够大 + if sparse_index >= self.sparse.len() { + self.sparse.resize(sparse_index + 1, None); + } + + // 检查值是否已存在 + if self.sparse[sparse_index].is_some() { + return false; + } + + // 插入到密集数组 + let dense_index = self.size; + if dense_index >= self.dense.len() { + self.dense.push(value); + } else { + self.dense[dense_index] = value; + } + + // 建立稀疏数组映射 + self.sparse[sparse_index] = Some(dense_index); + self.size += 1; + + true + } + + /** + * 移除值 + */ + pub fn remove(&mut self, value: u32) -> bool { + let sparse_index = value as usize; + + // 检查边界和存在性 + if sparse_index >= self.sparse.len() { + return false; + } + + let Some(dense_index) = self.sparse[sparse_index] else { + return false; + }; + + // 移除稀疏数组映射 + self.sparse[sparse_index] = None; + + // 将最后一个元素移动到被删除位置(保持密集性) + let last_index = self.size - 1; + if dense_index != last_index { + let last_value = self.dense[last_index]; + self.dense[dense_index] = last_value; + + // 更新被移动元素的稀疏数组映射 + self.sparse[last_value as usize] = Some(dense_index); + } + + self.size -= 1; + true + } + + /** + * 检查值是否存在 + */ + pub fn contains(&self, value: u32) -> bool { + let sparse_index = value as usize; + sparse_index < self.sparse.len() && self.sparse[sparse_index].is_some() + } + + /** + * 获取元素数量 + */ + pub fn len(&self) -> usize { + self.size + } + + /** + * 检查是否为空 + */ + pub fn is_empty(&self) -> bool { + self.size == 0 + } + + /** + * 清空集合 + */ + pub fn clear(&mut self) { + self.sparse.clear(); + self.dense.clear(); + self.size = 0; + } + + /** + * 获取密集数组的引用 + */ + pub fn dense(&self) -> &[u32] { + &self.dense[0..self.size] + } + + /** + * 获取密集数组的可变引用 + */ + pub fn dense_mut(&mut self) -> &mut [u32] { + &mut self.dense[0..self.size] + } + + /** + * 迭代所有值 + */ + pub fn iter(&self) -> impl Iterator + '_ { + self.dense[0..self.size].iter().copied() + } + + /** + * 批量插入 + */ + pub fn insert_batch(&mut self, values: &[u32]) { + for &value in values { + self.insert(value); + } + } + + /** + * 获取值在密集数组中的索引 + */ + pub fn get_dense_index(&self, value: u32) -> Option { + let sparse_index = value as usize; + if sparse_index < self.sparse.len() { + self.sparse[sparse_index] + } else { + None + } + } + + /** + * 预分配容量 + */ + pub fn reserve(&mut self, sparse_capacity: usize, dense_capacity: usize) { + if sparse_capacity > self.sparse.len() { + self.sparse.resize(sparse_capacity, None); + } + if dense_capacity > self.dense.capacity() { + self.dense.reserve(dense_capacity - self.dense.capacity()); + } + } + + /** + * 与另一个稀疏集合取交集 + */ + pub fn intersection(&self, other: &SparseSet) -> SparseSet { + let mut result = SparseSet::new(); + + for value in self.iter() { + if other.contains(value) { + result.insert(value); + } + } + + result + } + + /** + * 与另一个稀疏集合取并集 + */ + pub fn union(&self, other: &SparseSet) -> SparseSet { + let mut result = SparseSet::new(); + + // 添加当前集合的所有元素 + for value in self.iter() { + result.insert(value); + } + + // 添加另一个集合的所有元素 + for value in other.iter() { + result.insert(value); + } + + result + } +} + +impl Default for SparseSet { + fn default() -> Self { + Self::new() + } +} + +impl std::fmt::Debug for SparseSet { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("SparseSet") + .field("size", &self.size) + .field("sparse_len", &self.sparse.len()) + .field("dense_elements", &self.dense[0..self.size].to_vec()) + .finish() + } +} \ No newline at end of file diff --git a/packages/core-rust/src/utils/time.rs b/packages/core-rust/src/utils/time.rs new file mode 100644 index 00000000..c39f6890 --- /dev/null +++ b/packages/core-rust/src/utils/time.rs @@ -0,0 +1,124 @@ +use std::sync::{Mutex, OnceLock}; + +/** + * 时间管理工具类 + * 提供游戏时间相关的功能,包括帧时间、总时间、时间缩放等 + */ +pub struct Time { + /// 上一帧到当前帧的时间间隔(秒) + delta_time: f64, + + /// 未缩放的帧时间间隔(秒) + unscaled_delta_time: f64, + + /// 游戏开始以来的总时间(秒) + total_time: f64, + + /// 未缩放的总时间(秒) + unscaled_total_time: f64, + + /// 时间缩放比例 + time_scale: f64, + + /// 当前帧数 + frame_count: u64, +} + +impl Time { + pub fn new() -> Self { + Self { + delta_time: 0.0, + unscaled_delta_time: 0.0, + total_time: 0.0, + unscaled_total_time: 0.0, + time_scale: 1.0, + frame_count: 0, + } + } + + /** + * 获取全局Time实例 + */ + pub fn instance() -> &'static Mutex