diff --git a/docs/.vitepress/cache/deps/_metadata.json b/docs/.vitepress/cache/deps/_metadata.json index 10267af..430a30f 100644 --- a/docs/.vitepress/cache/deps/_metadata.json +++ b/docs/.vitepress/cache/deps/_metadata.json @@ -1,25 +1,25 @@ { - "hash": "6e3217ee", - "configHash": "ff691e50", + "hash": "2500e5b1", + "configHash": "3af8c6da", "lockfileHash": "42b6a898", - "browserHash": "d5f41485", + "browserHash": "36f3405c", "optimized": { "vue": { "src": "../../../node_modules/vue/dist/vue.runtime.esm-bundler.js", "file": "vue.js", - "fileHash": "ed53cbd8", + "fileHash": "d870a771", "needsInterop": false }, "vitepress > @vue/devtools-api": { "src": "../../../node_modules/@vue/devtools-api/dist/index.js", "file": "vitepress___@vue_devtools-api.js", - "fileHash": "e7446b18", + "fileHash": "d4c69f44", "needsInterop": false }, "vitepress > @vueuse/core": { "src": "../../../node_modules/@vueuse/core/dist/index.js", "file": "vitepress___@vueuse_core.js", - "fileHash": "6dc472ff", + "fileHash": "05ae35d2", "needsInterop": false } }, diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index d999b03..33e2bda 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -8,7 +8,7 @@ export default defineConfig({ /** GitHub Pages / 子路径部署 */ base: '/GFramework/', vite: { - plugins: [markdownEscapePlugin()] + plugins: [safeGenericEscapePlugin()] }, /** 多语言 */ locales: { @@ -172,33 +172,48 @@ export default defineConfig({ }) import { defineConfig } from 'vitepress' -function markdownEscapePlugin() { +function safeGenericEscapePlugin() { return { - name: 'markdown-escape-plugin', - enforce: 'pre', // 在 vitepress 之前执行 + name: 'safe-generic-escape', + enforce: 'pre', + transform(code: string, id: string) { if (!id.endsWith('.md')) return const codeBlocks: string[] = [] + const htmlBlocks: string[] = [] - // 1️⃣ 替换代码块 - const replaced = code.replace(/```[\s\S]*?```/g, (match) => { - const index = codeBlocks.length + // 1️⃣ 保护代码块 ``` ``` + let processed = code.replace(/```[\s\S]*?```/g, (match) => { + const i = codeBlocks.length codeBlocks.push(match) - return `__CODE_BLOCK_${index}__` + return `__CODE_BLOCK_${i}__` }) - // 2️⃣ 转义普通文本中的 < > - let escaped = replaced - .replace(//g, '>') - - // 3️⃣ 恢复代码块 - codeBlocks.forEach((block, index) => { - escaped = escaped.replace(`__CODE_BLOCK_${index}__`, block) + // 2️⃣ 保护 HTML 标签(避免破坏 Vue SFC) + processed = processed.replace(/<\/?[a-zA-Z][^>]*>/g, (match) => { + const i = htmlBlocks.length + htmlBlocks.push(match) + return `__HTML_BLOCK_${i}__` }) - return escaped + // 3️⃣ 只转义“泛型形式”的 + processed = processed.replace( + /<([A-Z][A-Za-z0-9_,\s]*)>/g, + (_, inner) => `<${inner}>` + ) + + // 4️⃣ 恢复 HTML + htmlBlocks.forEach((block, i) => { + processed = processed.replace(`__HTML_BLOCK_${i}__`, block) + }) + + // 5️⃣ 恢复代码块 + codeBlocks.forEach((block, i) => { + processed = processed.replace(`__CODE_BLOCK_${i}__`, block) + }) + + return processed } } } diff --git a/docs/zh-CN/core/events.md b/docs/zh-CN/core/events.md index d1f4158..5a08c3b 100644 --- a/docs/zh-CN/core/events.md +++ b/docs/zh-CN/core/events.md @@ -73,7 +73,7 @@ onClicked.Trigger(); unregister.UnRegister(); ``` -### 2. [Event](EasyEvent.cs) +### 2. [Event``](EasyEvent.cs) 单参数泛型事件类,支持一个参数的事件。 @@ -99,7 +99,7 @@ onScoreChanged.Trigger(100); **使用示例:** -``` +```csharp // 伤害事件:攻击者、伤害值 var onDamageDealt = new Event(); @@ -117,7 +117,7 @@ onDamageDealt.Trigger("Player", 50); **使用示例:** -``csharp +```csharp // 注册全局事件类型 EasyEvents.Register(); @@ -140,7 +140,7 @@ gameStartEvent.Trigger(); **使用示例:** -``csharp +```csharp // 使用全局事件系统 var eventBus = new EventBus(); @@ -166,7 +166,7 @@ eventBus.Send(); **使用示例:** -``csharp +```csharp Action onUnregister = () => GD.Print("Unregistered"); var unregister = new DefaultUnRegister(onUnregister); @@ -180,7 +180,7 @@ unregister.UnRegister(); **使用示例:** -``csharp +```csharp var onAnyInput = new OrEvent() .Or(onKeyPressed) .Or(onMouseClicked) @@ -199,7 +199,7 @@ onAnyInput.Register(() => **使用示例:** -``csharp +```csharp var unregisterList = new UnRegisterList(); // 添加到列表 @@ -224,7 +224,7 @@ unregisterList.UnRegisterAll(); ### 定义事件类 -``csharp +```csharp // 简单事件 public struct GameStartedEvent { } @@ -247,7 +247,7 @@ public struct LevelCompletedEvent ### Model 中发送事件 -``csharp +```csharp public class PlayerModel : AbstractModel { public BindableProperty Health { get; } = new(100); @@ -273,7 +273,7 @@ public class PlayerModel : AbstractModel ### System 中发送事件 -``csharp +```csharp public class CombatSystem : AbstractSystem { protected override void OnInit() { } @@ -295,7 +295,7 @@ public class CombatSystem : AbstractSystem ### Controller 中注册事件 -``csharp +```csharp public partial class GameController : Node, IController { private IUnRegisterList _unregisterList = new UnRegisterList(); @@ -343,7 +343,7 @@ public partial class GameController : Node, IController ### 1. 事件链式组合 -``csharp +```csharp // 使用 Or 组合多个事件 var onAnyDamage = new OrEvent() .Or(onPhysicalDamage) @@ -358,7 +358,7 @@ onAnyDamage.Register(() => ### 2. 事件过滤 -``csharp +```csharp // 只处理高伤害事件 this.RegisterEvent(e => { @@ -371,7 +371,7 @@ this.RegisterEvent(e => ### 3. 事件转发 -``csharp +```csharp public class EventBridge : AbstractSystem { protected override void OnInit() @@ -391,7 +391,7 @@ public class EventBridge : AbstractSystem ### 4. 临时事件监听 -``csharp +```csharp public class TutorialController : Node, IController { public override void _Ready() @@ -409,7 +409,7 @@ public class TutorialController : Node, IController ### 5. 条件事件 -``csharp +```csharp public class AchievementSystem : AbstractSystem { private int _killCount = 0; @@ -437,7 +437,7 @@ public class AchievementSystem : AbstractSystem ### 使用 UnRegisterList -``csharp +```csharp public class MyController : Node, IController { // 统一管理所有注销对象 @@ -463,7 +463,7 @@ public class MyController : Node, IController ### 使用 Godot 节点生命周期 -``csharp +```csharp public override void _Ready() { // 当节点退出场景树时自动注销 diff --git a/docs/zh-CN/core/query.md b/docs/zh-CN/core/query.md index e80ebd9..3c5abc4 100644 --- a/docs/zh-CN/core/query.md +++ b/docs/zh-CN/core/query.md @@ -121,7 +121,7 @@ public GetItemCountQuery(string itemId) : base(new GetItemCountQueryInput(itemId ``` -### 2. 发送查询(在 Controller 中) +### 2. 发送查询 ```csharp public partial class ShopUI : Control, IController @@ -156,7 +156,7 @@ public partial class ShopUI : Control, IController ### 3. 在 System 中使用 -``csharp +```csharp public class CombatSystem : AbstractSystem { protected override void OnInit() @@ -185,7 +185,7 @@ this.RegisterEvent(OnEnemyAttack); ### 1. 带参数的复杂查询 -``csharp +```csharp // 查询指定范围内的敌人列表 public class GetEnemiesInRangeQuery : AbstractQuery> { @@ -209,7 +209,7 @@ var enemies = this.SendQuery(new GetEnemiesInRangeQuery ### 2. 组合查询 -``csharp +```csharp // 查询玩家是否可以使用技能 public class CanUseSkillQuery : AbstractQuery { @@ -256,7 +256,7 @@ public string SkillId { get; set; } ### 3. 聚合数据查询 -``csharp +```csharp // 查询玩家战斗力 public class GetPlayerPowerQuery : AbstractQuery { @@ -295,7 +295,7 @@ public class GetPlayerInfoQuery : AbstractQuery ### 4. 跨 System 查询 -``csharp +```csharp // 在 AI System 中查询玩家状态 public class EnemyAISystem : AbstractSystem { @@ -346,7 +346,7 @@ protected override void OnInit() { } - **返回值**:有返回值 - **示例**:获取金币数量、检查技能冷却、查询玩家位置 -``csharp +```csharp // ❌ 错误:在 Query 中修改状态 public class BadQuery : AbstractQuery { @@ -392,7 +392,7 @@ public class AddGoldCommand : AbstractCommand ### 1. 缓存查询结果 -``csharp +```csharp // 在 Model 中缓存复杂计算 public class PlayerModel : AbstractModel { @@ -424,7 +424,7 @@ private int? _cachedPower; ### 2. 批量查询 -``csharp +```csharp // 一次查询多个数据,而不是多次单独查询 public class GetMultipleItemCountsQuery : AbstractQuery> { diff --git a/docs/zh-CN/core/rule.md b/docs/zh-CN/core/rule.md index c644b6a..6eaf3ac 100644 --- a/docs/zh-CN/core/rule.md +++ b/docs/zh-CN/core/rule.md @@ -77,7 +77,7 @@ IContextAware (上下文感知接口) ### 1. Component 继承 ContextAwareBase -``csharp +```csharp // 组件通过继承 ContextAwareBase 获得架构上下文访问能力 public partial class PlayerController : Node, IController { @@ -99,7 +99,7 @@ public partial class PlayerController : Node, IController ### 2. Command 继承 AbstractCommand (IContextAware) -``csharp +```csharp // Command 继承 AbstractCommand,自动成为 IContextAware public class BuyItemCommand : AbstractCommand { @@ -124,7 +124,7 @@ public class BuyItemCommand : AbstractCommand ### 3. 自定义组件遵循规则 -``csharp +```csharp // 自定义管理器遵循框架规则,继承 ContextAwareBase public class SaveManager : ContextAwareBase { @@ -151,7 +151,7 @@ public class SaveManager : ContextAwareBase ### 1. 组件注册规则 -``csharp +```csharp public class GameArchitecture : Architecture { protected override void Init() @@ -166,7 +166,7 @@ public class GameArchitecture : Architecture ### 2. Command/Query 自动注入规则 -``csharp +```csharp // Controller 中发送 Command public class ShopUI : Control, IController { @@ -200,7 +200,7 @@ public class BuyItemCommand : AbstractCommand Rule 接口体现了依赖注入(DI)的思想: -``csharp +```csharp // 接口定义了"需要什么" public interface IContextAware { @@ -225,7 +225,7 @@ public static class CanSendExtensions Rule 接口遵循接口隔离原则,每个接口职责单一: -``csharp +```csharp // ❌ 不好的设计:一个大接口包含所有能力 public interface IBigInterface { @@ -247,7 +247,7 @@ public interface ICanSendCommand { ... } // 只负责发送 Command 通过接口组合实现不同能力: -``csharp +```csharp // Controller 需要获取 Model 和发送 Command public interface IController : ICanGetModel, ICanGetSystem, ICanSendCommand, ICanSendQuery, ICanRegisterEvent @@ -271,7 +271,7 @@ public interface ISystem : IContextAware, ICanGetModel, ICanGetUtility, ICanGetS ### 自定义规则接口 -``csharp +```csharp // 定义新的规则接口 public interface ICanAccessDatabase : IBelongToArchitecture { diff --git a/docs/zh-CN/core/utility.md b/docs/zh-CN/core/utility.md index 92ecc2c..f7ff3bf 100644 --- a/docs/zh-CN/core/utility.md +++ b/docs/zh-CN/core/utility.md @@ -13,7 +13,7 @@ Utility 标记接口,所有工具类都应实现此接口。 **接口定义:** -``csharp +```csharp public interface IUtility { // 标记接口,无方法定义 @@ -26,7 +26,7 @@ public interface IUtility **接口定义:** -``csharp +```csharp public interface IContextUtility : IUtility { void Init(); // 初始化上下文工具 @@ -139,7 +139,7 @@ public class TimeUtility : IUtility ### 2. 注册 Utility -``csharp +```csharp public class GameArchitecture : Architecture { protected override void Init() @@ -154,7 +154,7 @@ public class GameArchitecture : Architecture ### 3. 使用 Utility -``csharp +```csharp // 在 System 中使用 public class SaveSystem : AbstractSystem { @@ -223,7 +223,7 @@ public class MovePlayerCommand : AbstractCommand ### 1. 序列化/反序列化工具 -``csharp +```csharp public class JsonUtility : IUtility { public string Serialize(T obj) @@ -254,7 +254,7 @@ public class JsonUtility : IUtility ### 2. 随机数工具 -``csharp +```csharp public class RandomUtility : IUtility { private Random _random = new Random(); @@ -294,7 +294,7 @@ public class RandomUtility : IUtility ### 3. 字符串工具 -``csharp +```csharp public class StringUtility : IUtility { public string Truncate(string text, int maxLength, string suffix = "...") @@ -327,7 +327,7 @@ public class StringUtility : IUtility ### 4. 加密工具 -``csharp +```csharp public class EncryptionUtility : IUtility { private const string EncryptionKey = "YourSecretKey123"; @@ -367,7 +367,7 @@ public class EncryptionUtility : IUtility ### 5. 对象池工具 -``csharp +```csharp public class ObjectPoolUtility : IUtility { private Dictionary> _pools = new(); @@ -410,7 +410,7 @@ public class ObjectPoolUtility : IUtility ### 6. 日志工具 -``csharp +```csharp public class LogUtility : IUtility { public enum LogLevel @@ -503,7 +503,7 @@ public class CombatSystem : AbstractSystem ## 错误示例 -``csharp +```csharp // ❌ 错误:Utility 中存储状态 public class BadUtility : IUtility { @@ -543,7 +543,7 @@ public class IdGeneratorSystem : AbstractSystem ### 1. 缓存计算结果 -``csharp +```csharp public class PathfindingUtility : IUtility { private Dictionary<(Vector3, Vector3), List> _pathCache = new(); @@ -582,7 +582,7 @@ public class PathfindingUtility : IUtility ### 2. 对象复用 -``csharp +```csharp public class CollectionUtility : IUtility { private List _tempList = new(); diff --git a/docs/zh-CN/getting-started/architecture-overview.md b/docs/zh-CN/getting-started/architecture-overview.md index 9dcc52b..3da6efb 100644 --- a/docs/zh-CN/getting-started/architecture-overview.md +++ b/docs/zh-CN/getting-started/architecture-overview.md @@ -95,7 +95,7 @@ public class PlayerModel : AbstractModel 应用的业务逻辑处理层。 -``csharp +```csharp public class CombatSystem : AbstractSystem { protected override void OnInit() @@ -136,7 +136,7 @@ this.GetEvent().Register(OnAttack); 连接 UI 和业务逻辑的桥梁。 -``csharp +```csharp public class PlayerController : IController { private IArchitecture _architecture; @@ -176,7 +176,7 @@ public class PlayerController : IController 提供无状态的辅助功能。 -``csharp +```csharp public class StorageUtility : IUtility { public void SaveData(string key, T data) @@ -205,7 +205,7 @@ public class StorageUtility : IUtility 用于修改应用状态的操作: -``csharp +```csharp public class MovePlayerCommand : AbstractCommand { public Vector2 Direction { get; set; } @@ -222,7 +222,7 @@ public class MovePlayerCommand : AbstractCommand 用于查询应用状态:` -``csharp +```csharp public class GetPlayerHealthQuery : AbstractQuery { protected override int OnDo() @@ -249,7 +249,7 @@ this.RegisterEvent(OnPlayerDied); ### BindableProperty -``csharp +```csharp public class PlayerModel : AbstractModel { public BindableProperty Health { get; } = new(100); @@ -274,7 +274,7 @@ playerModel.Health.Register(newValue => { ### 1. 分层职责明确 -``csharp +```csharp // ✅ 正确:Model 只存储数据 public class PlayerModel : AbstractModel { @@ -293,7 +293,7 @@ public class PlayerModel : AbstractModel ### 2. 事件驱动设计 -``csharp +```csharp // ✅ 正确:使用事件解耦 public class CombatSystem : AbstractSystem { @@ -317,7 +317,7 @@ public class CombatSystem : AbstractSystem ### 3. 命令查询分离 -``csharp +```csharp // ✅ 正确:明确区分命令和查询 public class MovePlayerCommand : AbstractCommand { } // 修改状态 public class GetPlayerPositionQuery : AbstractQuery { } // 查询状态 diff --git a/docs/zh-CN/godot/setting.md b/docs/zh-CN/godot/setting.md index 12e6161..c4c9a59 100644 --- a/docs/zh-CN/godot/setting.md +++ b/docs/zh-CN/godot/setting.md @@ -86,7 +86,7 @@ graph TD #### 基本音频设置 -``csharp +```csharp // 创建音频配置数据 var settings = new AudioSettings { @@ -104,7 +104,7 @@ audioSettings.Apply(); #### 自定义音频总线映射 -``csharp +```csharp // 自定义音频总线映射 var customBusMap = new AudioBusMap { @@ -128,7 +128,7 @@ await audioSettings.Apply(); #### 通过设置系统使用 -``csharp +```csharp // 注册音频设置到设置模型 var settingsModel = this.GetModel(); var audioSettingsData = settingsModel.Get(); @@ -145,7 +145,7 @@ await godotAudioSettings.Apply(); #### 基本图形设置 -``csharp +```csharp // 创建图形设置 var graphicsSettings = new GodotGraphicsSettings { @@ -160,7 +160,7 @@ await graphicsSettings.Apply(); #### 窗口模式切换 -``csharp +```csharp public class DisplayManager : Node { private GodotGraphicsSettings _graphicsSettings; @@ -188,7 +188,7 @@ public class DisplayManager : Node #### 预设分辨率配置 -``csharp +```csharp public class ResolutionPresets { public static readonly (int width, int height)[] CommonResolutions = @@ -214,7 +214,7 @@ public class ResolutionPresets ### AudioBusMap -``csharp +```csharp public sealed class AudioBusMap { public string Master { get; init; } = "Master"; @@ -231,7 +231,7 @@ public sealed class AudioBusMap ### GodotAudioSettings -``csharp +```csharp public class GodotAudioSettings(AudioSettings settings, AudioBusMap busMap) : IApplyAbleSettings { public Task Apply(); @@ -245,7 +245,7 @@ public class GodotAudioSettings(AudioSettings settings, AudioBusMap busMap) : IA **Apply 方法实现:** -``csharp +```csharp public Task Apply() { SetBus(busMap.Master, settings.MasterVolume); @@ -257,7 +257,7 @@ public Task Apply() ### GodotGraphicsSettings -``csharp +```csharp public class GodotGraphicsSettings : GraphicsSettings, IApplyAbleSettings { public Task Apply(); @@ -277,7 +277,7 @@ public class GodotGraphicsSettings : GraphicsSettings, IApplyAbleSettings Godot 音频系统使用分贝(dB)作为音量单位,而我们通常使用线性值(0-1): -``csharp +```csharp // 线性值到分贝转换 float linearVolume = 0.5f; // 50% 音量 float dbVolume = Mathf.LinearToDb(linearVolume); // 转换为分贝 @@ -290,7 +290,7 @@ AudioServer.SetBusVolumeDb(busIndex, dbVolume); 为避免完全静音(-inf dB),应用了最小音量限制: -``csharp +```csharp float clampedVolume = Mathf.Clamp(linear, 0.0001f, 1f); float dbVolume = Mathf.LinearToDb(clampedVolume); ``` @@ -299,7 +299,7 @@ float dbVolume = Mathf.LinearToDb(clampedVolume); #### 全屏模式 -``csharp +```csharp // 设置全屏 DisplayServer.WindowSetMode(DisplayServer.WindowMode.ExclusiveFullscreen); DisplayServer.WindowSetFlag(DisplayServer.WindowFlags.Borderless, true); @@ -307,7 +307,7 @@ DisplayServer.WindowSetFlag(DisplayServer.WindowFlags.Borderless, true); #### 窗口化模式 -``csharp +```csharp // 设置窗口化 DisplayServer.WindowSetMode(DisplayServer.WindowMode.Windowed); DisplayServer.WindowSetSize(newSize); @@ -325,7 +325,7 @@ DisplayServer.WindowSetPosition(position); #### 音量变化平滑过渡 -``csharp +```csharp public class AudioManager : Node { private Tween _volumeTween; @@ -398,7 +398,7 @@ public class CustomAudioManager : Node #### 音频设置验证 -``csharp +```csharp public static class AudioSettingsValidator { public static bool ValidateBusNames(AudioBusMap busMap) @@ -428,7 +428,7 @@ public static class AudioSettingsValidator #### 分辨率变更安全检查 -``csharp +```csharp public static class DisplayValidator { public static bool IsResolutionSupported(int width, int height) @@ -451,7 +451,7 @@ public static class DisplayValidator #### 图形设置持久化 -``csharp +```csharp public class GraphicsSettingsManager : Node { private const string SettingsKey = "graphics_settings"; @@ -545,7 +545,7 @@ public class GraphicsSettingsManager : Node #### 音频调试 -``csharp +```csharp // 打印所有音频总线信息 for (int i = 0; i < AudioServer.GetBusCount(); i++) { @@ -557,7 +557,7 @@ for (int i = 0; i < AudioServer.GetBusCount(); i++) #### 图形调试 -``csharp +```csharp // 打印当前显示信息 var screen = DisplayServer.GetPrimaryScreen(); var screenSize = DisplayServer.ScreenGetSize(screen);