From 06157bf15cb3610fc9fe1044c202388933e0563e Mon Sep 17 00:00:00 2001 From: cneicy Date: Wed, 26 Aug 2026 02:49:45 +0800 Subject: [PATCH] chore: initialize standalone UPM package --- .gitea/workflows/publish.yml | 49 ++++ .gitea/workflows/unity-verify.yml | 39 ++++ .gitignore | 10 + .npmignore | 8 + CHANGELOG.md | 16 ++ CHANGELOG.md.meta | 7 + Development~/UnityProject/.gitignore | 6 + Development~/UnityProject/Assets/.gitkeep | 0 .../UnityProject/Packages/manifest.json | 15 ++ .../ProjectSettings/ProjectVersion.txt | 2 + README.md | 37 +++ README.md.meta | 7 + ShrinkCommand.Integration.EventBus.asmdef | 19 ++ ...nkCommand.Integration.EventBus.asmdef.meta | 7 + ShrinkCommandEventBusBridge.cs | 219 ++++++++++++++++++ ShrinkCommandEventBusBridge.cs.meta | 11 + ShrinkCommandEventBusBridgeEvents.cs | 52 +++++ ShrinkCommandEventBusBridgeEvents.cs.meta | 11 + ShrinkCommandEventBusBridgeExtensions.cs | 29 +++ ShrinkCommandEventBusBridgeExtensions.cs.meta | 11 + ShrinkCommandEventBusBridgeOptions.cs | 10 + ShrinkCommandEventBusBridgeOptions.cs.meta | 11 + ShrinkCommandEventBusComponent.cs | 36 +++ ShrinkCommandEventBusComponent.cs.meta | 11 + package.json | 24 ++ package.json.meta | 7 + 26 files changed, 654 insertions(+) create mode 100644 .gitea/workflows/publish.yml create mode 100644 .gitea/workflows/unity-verify.yml create mode 100644 .gitignore create mode 100644 .npmignore create mode 100644 CHANGELOG.md create mode 100644 CHANGELOG.md.meta create mode 100644 Development~/UnityProject/.gitignore create mode 100644 Development~/UnityProject/Assets/.gitkeep create mode 100644 Development~/UnityProject/Packages/manifest.json create mode 100644 Development~/UnityProject/ProjectSettings/ProjectVersion.txt create mode 100644 README.md create mode 100644 README.md.meta create mode 100644 ShrinkCommand.Integration.EventBus.asmdef create mode 100644 ShrinkCommand.Integration.EventBus.asmdef.meta create mode 100644 ShrinkCommandEventBusBridge.cs create mode 100644 ShrinkCommandEventBusBridge.cs.meta create mode 100644 ShrinkCommandEventBusBridgeEvents.cs create mode 100644 ShrinkCommandEventBusBridgeEvents.cs.meta create mode 100644 ShrinkCommandEventBusBridgeExtensions.cs create mode 100644 ShrinkCommandEventBusBridgeExtensions.cs.meta create mode 100644 ShrinkCommandEventBusBridgeOptions.cs create mode 100644 ShrinkCommandEventBusBridgeOptions.cs.meta create mode 100644 ShrinkCommandEventBusComponent.cs create mode 100644 ShrinkCommandEventBusComponent.cs.meta create mode 100644 package.json create mode 100644 package.json.meta diff --git a/.gitea/workflows/publish.yml b/.gitea/workflows/publish.yml new file mode 100644 index 0000000..18e675f --- /dev/null +++ b/.gitea/workflows/publish.yml @@ -0,0 +1,49 @@ +name: Publish UPM package + +on: + push: + tags: + - 'v*' + workflow_dispatch: + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + env: + NODE_AUTH_TOKEN: ${{ secrets.SHRINKSDK_PACKAGE_TOKEN }} + steps: + - name: Fetch tagged revision + shell: bash + run: | + set -eu + ref="${{ gitea.sha }}" + test -n "$ref" + git init . + git remote add origin "https://git.crash.work/ShrinkSDK/ShrinkCommand.Integration.EventBus.git" + git fetch --depth=1 origin "$ref" + git checkout --detach FETCH_HEAD + + - name: Validate immutable release version + shell: bash + run: | + set -eu + tag="$(git describe --exact-match --tags HEAD)" + version="$(node -p "require('./package.json').version")" + test "$tag" = "v$version" + npm pack --dry-run + + - name: Publish to ShrinkSDK registry + shell: bash + run: | + set -eu + : "${NODE_AUTH_TOKEN:?SHRINKSDK_PACKAGE_TOKEN is required}" + npmrc="$HOME/.npmrc" + cleanup() { rm -f "$npmrc"; } + trap cleanup EXIT + printf '%s\n' \ + 'registry=https://git.crash.work/api/packages/ShrinkSDK/npm/' \ + '//git.crash.work/api/packages/ShrinkSDK/npm/:_authToken=${NODE_AUTH_TOKEN}' > "$npmrc" + npm publish --registry=https://git.crash.work/api/packages/ShrinkSDK/npm/ \ No newline at end of file diff --git a/.gitea/workflows/unity-verify.yml b/.gitea/workflows/unity-verify.yml new file mode 100644 index 0000000..3069c15 --- /dev/null +++ b/.gitea/workflows/unity-verify.yml @@ -0,0 +1,39 @@ +name: Verify standalone Unity package + +on: + workflow_dispatch: + +jobs: + editmode: + runs-on: unity-2022.3.62f3 + container: + image: docker.1panel.live/unityci/editor:ubuntu-2022.3.62f3-windows-mono-3 + volumes: + - /www/dk_project/bt-recovery/gitea/runner/seedskey-unity-license:/root/.local/share/unity3d/Unity + - /www/dk_project/bt-recovery/gitea/runner/seedskey-unity-entitlements:/root/.config/unity3d/Unity/licenses + steps: + - name: Fetch selected revision + shell: bash + run: | + set -eu + ref="${{ gitea.sha }}" + git init . + git remote add origin "https://git.crash.work/ShrinkSDK/ShrinkCommand.Integration.EventBus.git" + git fetch --depth=1 origin "$ref" + git checkout --detach FETCH_HEAD + + - name: Run package EditMode tests + shell: bash + run: | + set -eu + unity_bin="$(command -v unity-editor || command -v unity || command -v Unity || true)" + test -n "$unity_bin" + "$unity_bin" \ + -batchmode \ + -nographics \ + -quit \ + -projectPath "$PWD/Development~/UnityProject" \ + -runTests \ + -testPlatform EditMode \ + -testResults "$PWD/TestResults/editmode.xml" \ + -logFile "$PWD/TestResults/unity.log" \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..246935d --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +/Development~/UnityProject/[Ll]ibrary/ +/Development~/UnityProject/[Tt]emp/ +/Development~/UnityProject/[Oo]bj/ +/Development~/UnityProject/[Ll]ogs/ +/Development~/UnityProject/[Uu]ser[Ss]ettings/ +/Development~/UnityProject/TestResults/ +/Tools~/**/[Bb]in/ +/Tools~/**/[Oo]bj/ +*.user +*.DotSettings.user diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..700f03d --- /dev/null +++ b/.npmignore @@ -0,0 +1,8 @@ +.git/ +.gitea/ +Development~/ +Tools~/ +*.csproj +*.sln +*.user +*.DotSettings.user diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..47aadef --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,16 @@ +# Changelog + +本文件记录 `ShrinkCommand.Integration.EventBus` 在当前工作区中的包内变更。 + +## [0.1.1] - 2026-04-07 + +### Added + +- 提供 `UseEventBusBridge(...)` 扩展,可把命令服务接到 EventBus。 +- 提供 `RequestCommandAsync(...)` 扩展,支持通过事件请求式执行命令。 +- 建立命令桥接事件:`ShrinkCommandExecuteRequestEvent`、`ShrinkCommandExecutingEvent`、`ShrinkCommandExecutedEvent`、`ShrinkCommandFailedEvent`。 + +### Changed + +- 桥接公共类型补齐 `#nullable enable`,统一可空语义。 +- 请求结果字段统一使用 `ExecutionResult`,避免与 `EventBase.Result` 命名冲突。 diff --git a/CHANGELOG.md.meta b/CHANGELOG.md.meta new file mode 100644 index 0000000..8658c7f --- /dev/null +++ b/CHANGELOG.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ca7f23ed84bf7aa409d36b858591a823 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Development~/UnityProject/.gitignore b/Development~/UnityProject/.gitignore new file mode 100644 index 0000000..aa2eb00 --- /dev/null +++ b/Development~/UnityProject/.gitignore @@ -0,0 +1,6 @@ +[Ll]ibrary/ +[Tt]emp/ +[Oo]bj/ +[Ll]ogs/ +[Uu]ser[Ss]ettings/ +TestResults/ \ No newline at end of file diff --git a/Development~/UnityProject/Assets/.gitkeep b/Development~/UnityProject/Assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Development~/UnityProject/Packages/manifest.json b/Development~/UnityProject/Packages/manifest.json new file mode 100644 index 0000000..33a5941 --- /dev/null +++ b/Development~/UnityProject/Packages/manifest.json @@ -0,0 +1,15 @@ +{ + "scopedRegistries": [ + { + "name": "ShrinkSDK", + "url": "https://git.crash.work/api/packages/ShrinkSDK/npm/", + "scopes": [ + "com.cneicy" + ] + } + ], + "dependencies": { + "com.unity.test-framework": "1.1.33", + "com.cneicy.shrink-command-integration-eventbus": "file:../../.." + } +} diff --git a/Development~/UnityProject/ProjectSettings/ProjectVersion.txt b/Development~/UnityProject/ProjectSettings/ProjectVersion.txt new file mode 100644 index 0000000..587f809 --- /dev/null +++ b/Development~/UnityProject/ProjectSettings/ProjectVersion.txt @@ -0,0 +1,2 @@ +m_EditorVersion: 2022.3.62f3 +m_EditorVersionWithRevision: 2022.3.62f3 (96770f904ca7) diff --git a/README.md b/README.md new file mode 100644 index 0000000..9594d40 --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +# ShrinkCommand.Integration.EventBus + +`ShrinkCommand` 与 `ShrinkEventBus` 的桥接层。 + +## 能力 + +- 通过事件请求执行命令 +- 把命令执行过程发布为 EventBus 生命周期事件 +- 保持 `ShrinkCommand` 核心不依赖 `ShrinkEventBus` + +## 事件 + +- `ShrinkCommandExecuteRequestEvent` +- `ShrinkCommandExecutingEvent` +- `ShrinkCommandExecutedEvent` +- `ShrinkCommandFailedEvent` + +## 接入 + +`ShrinkApp.Starter.Basic` 的 ContextLoader 组合根会注册 `ShrinkCommandEventBusComponent`:它注入 +`shrink.service.command`,激活时接桥,依赖撤回时自动拆桥。独立使用本包时再显式注册: + +```csharp +var service = new ShrinkCommandService(); +service.AutoRegisterAll(); +service.UseEventBusBridge(new ShrinkCommandEventBusBridgeOptions +{ + ServiceName = "default", + DefaultSource = source +}); +``` + +请求执行: + +```csharp +var result = await ShrinkCommandEventBusBridge.RequestCommandAsync("help", source); +``` diff --git a/README.md.meta b/README.md.meta new file mode 100644 index 0000000..a84ca10 --- /dev/null +++ b/README.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f5b03f228e6ccef4e8225c62b96bd4a8 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/ShrinkCommand.Integration.EventBus.asmdef b/ShrinkCommand.Integration.EventBus.asmdef new file mode 100644 index 0000000..8beb363 --- /dev/null +++ b/ShrinkCommand.Integration.EventBus.asmdef @@ -0,0 +1,19 @@ +{ + "name": "ShrinkCommand.Integration.EventBus", + "rootNamespace": "ShrinkCommand.Integration", + "references": [ + "ShrinkCommand.Runtime", + "ShrinkContext.Core.Runtime", + "ShrinkEventBus.Runtime", + "UniTask" + ], + "optionalUnityReferences": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} diff --git a/ShrinkCommand.Integration.EventBus.asmdef.meta b/ShrinkCommand.Integration.EventBus.asmdef.meta new file mode 100644 index 0000000..d272bb6 --- /dev/null +++ b/ShrinkCommand.Integration.EventBus.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 63b0366d1e731824bb0900fbb820d543 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/ShrinkCommandEventBusBridge.cs b/ShrinkCommandEventBusBridge.cs new file mode 100644 index 0000000..78d8889 --- /dev/null +++ b/ShrinkCommandEventBusBridge.cs @@ -0,0 +1,219 @@ +#nullable enable +using System; +using System.Collections.Generic; +using Cysharp.Threading.Tasks; +using ShrinkEventBus; + +namespace ShrinkCommand.Integration +{ + public static class ShrinkCommandEventBusBridge + { + [ShrinkEventSubscriber(OwnerId = "shrink.command", DefaultBus = "game")] + private sealed class CommandRequestSubscriber + { + [ShrinkSubscribe(Priority = ShrinkEventPriority.Lowest)] + private UniTask OnExecuteRequest(ShrinkCommandExecuteRequestEvent eventArgs) + { + return HandleExecuteRequestAsync(eventArgs); + } + } + + private sealed class ServiceRegistration + { + public string ServiceName = ShrinkCommandConstants.DefaultServiceName; + public ShrinkCommandService Service = null!; + public IShrinkCommandSource? DefaultSource; + public Action? ExecutingHandler; + public Action? ExecutedHandler; + } + + private static readonly object SyncRoot = new(); + private static readonly Dictionary RegisteredByName = new(StringComparer.OrdinalIgnoreCase); + private static readonly Dictionary RegisteredByService = new(); + private static IDisposable? _requestHandlerBinding; + + [UnityEngine.RuntimeInitializeOnLoadMethod(UnityEngine.RuntimeInitializeLoadType.SubsystemRegistration)] + private static void ResetStaticState() + { + lock (SyncRoot) + { + foreach (var registration in RegisteredByService.Values) + { + if (registration.ExecutingHandler != null) + registration.Service.OnCommandExecuting -= registration.ExecutingHandler; + if (registration.ExecutedHandler != null) + registration.Service.OnCommandExecuted -= registration.ExecutedHandler; + } + + RegisteredByService.Clear(); + RegisteredByName.Clear(); + _requestHandlerBinding?.Dispose(); + _requestHandlerBinding = null; + } + } + + public static void RegisterService( + ShrinkCommandService service, + ShrinkCommandEventBusBridgeOptions? options = null) + { + if (service == null) + throw new ArgumentNullException(nameof(service)); + + EnsureInitialized(); + options ??= new ShrinkCommandEventBusBridgeOptions(); + + lock (SyncRoot) + { + if (RegisteredByService.TryGetValue(service, out var existing)) + { + existing.DefaultSource = options.DefaultSource; + if (!string.Equals(existing.ServiceName, options.ServiceName, StringComparison.OrdinalIgnoreCase)) + { + RegisteredByName.Remove(existing.ServiceName); + existing.ServiceName = NormalizeServiceName(options.ServiceName); + RegisteredByName[existing.ServiceName] = existing; + } + + return; + } + + var registration = new ServiceRegistration + { + ServiceName = NormalizeServiceName(options.ServiceName), + Service = service, + DefaultSource = options.DefaultSource + }; + registration.ExecutingHandler = info => PublishExecuting(registration, info); + registration.ExecutedHandler = info => PublishExecuted(registration, info); + service.OnCommandExecuting += registration.ExecutingHandler; + service.OnCommandExecuted += registration.ExecutedHandler; + RegisteredByService[service] = registration; + RegisteredByName[registration.ServiceName] = registration; + } + } + + public static void UnregisterService(ShrinkCommandService service) + { + if (service == null) + return; + + lock (SyncRoot) + { + if (!RegisteredByService.TryGetValue(service, out var registration)) + return; + + if (registration.ExecutingHandler != null) + service.OnCommandExecuting -= registration.ExecutingHandler; + if (registration.ExecutedHandler != null) + service.OnCommandExecuted -= registration.ExecutedHandler; + + RegisteredByService.Remove(service); + RegisteredByName.Remove(registration.ServiceName); + } + } + + public static async UniTask RequestCommandAsync( + string rawInput, + IShrinkCommandSource? source = null, + string? serviceName = null) + { + var requestEvent = new ShrinkCommandExecuteRequestEvent + { + ServiceName = NormalizeServiceName(serviceName), + RawInput = rawInput ?? string.Empty, + Source = source + }; + + await EventBus.PostAsync(requestEvent); + return requestEvent.ExecutionResult ?? ShrinkCommandExecutionResult.Failure("没有命令桥处理该请求。"); + } + + private static void EnsureInitialized() + { + if (_requestHandlerBinding != null) + return; + + _requestHandlerBinding = EventBus.Attach(new CommandRequestSubscriber()); + } + + private static async UniTask HandleExecuteRequestAsync(ShrinkCommandExecuteRequestEvent eventArgs) + { + if (eventArgs == null || eventArgs.IsHandled || eventArgs.IsCanceled) + return; + + ServiceRegistration? registration; + lock (SyncRoot) + { + RegisteredByName.TryGetValue(NormalizeServiceName(eventArgs.ServiceName), out registration); + } + + if (registration == null) + { + eventArgs.IsHandled = true; + eventArgs.ExecutionResult = ShrinkCommandExecutionResult.Failure( + $"未找到命令服务: {NormalizeServiceName(eventArgs.ServiceName)}"); + return; + } + + var source = eventArgs.Source ?? registration.DefaultSource; + if (source == null) + { + eventArgs.IsHandled = true; + eventArgs.ExecutionResult = ShrinkCommandExecutionResult.Failure("命令请求缺少来源对象。"); + return; + } + + eventArgs.ExecutionResult = await registration.Service.ExecuteAsync(source, eventArgs.RawInput); + eventArgs.IsHandled = true; + } + + private static void PublishExecuting(ServiceRegistration registration, ShrinkCommandExecutingInfo info) + { + EventBus.Post(new ShrinkCommandExecutingEvent + { + ServiceName = registration.ServiceName, + RawInput = info.RawInput, + CommandPath = info.Command.Path, + SourceId = info.Source.SourceId, + SourceDisplayName = info.Source.DisplayName, + Arguments = new Dictionary(info.Arguments, StringComparer.OrdinalIgnoreCase) + }); + } + + private static void PublishExecuted(ServiceRegistration registration, ShrinkCommandExecutedInfo info) + { + var commandPath = info.Command?.Path ?? string.Empty; + var arguments = new Dictionary(info.Arguments, StringComparer.OrdinalIgnoreCase); + EventBus.Post(new ShrinkCommandExecutedEvent + { + ServiceName = registration.ServiceName, + RawInput = info.RawInput, + CommandPath = commandPath, + SourceId = info.Source.SourceId, + SourceDisplayName = info.Source.DisplayName, + Arguments = arguments, + IsSuccess = info.Result.IsSuccess, + Message = info.Result.Message + }); + + if (info.Result.IsSuccess) + return; + + EventBus.Post(new ShrinkCommandFailedEvent + { + ServiceName = registration.ServiceName, + RawInput = info.RawInput, + CommandPath = commandPath, + SourceId = info.Source.SourceId, + SourceDisplayName = info.Source.DisplayName, + Arguments = arguments, + ErrorMessage = info.Result.Message + }); + } + + private static string NormalizeServiceName(string? serviceName) + { + return string.IsNullOrWhiteSpace(serviceName) ? ShrinkCommandConstants.DefaultServiceName : serviceName.Trim(); + } + } +} diff --git a/ShrinkCommandEventBusBridge.cs.meta b/ShrinkCommandEventBusBridge.cs.meta new file mode 100644 index 0000000..956da06 --- /dev/null +++ b/ShrinkCommandEventBusBridge.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: de2d897c6d6fa1f419101a2c04ad57e1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/ShrinkCommandEventBusBridgeEvents.cs b/ShrinkCommandEventBusBridgeEvents.cs new file mode 100644 index 0000000..05f4621 --- /dev/null +++ b/ShrinkCommandEventBusBridgeEvents.cs @@ -0,0 +1,52 @@ +#nullable enable +using System.Collections.Generic; +using ShrinkEventBus; + +namespace ShrinkCommand.Integration +{ + public sealed class ShrinkCommandExecuteRequestEvent : IShrinkCancelableEvent + { + private bool _isCanceled; + + public string ServiceName { get; set; } = ShrinkCommandConstants.DefaultServiceName; + public string RawInput { get; set; } = string.Empty; + public IShrinkCommandSource? Source { get; set; } + public bool IsHandled { get; set; } + public ShrinkCommandExecutionResult? ExecutionResult { get; set; } + public bool IsCanceled => _isCanceled; + public void SetCanceled(bool value) => _isCanceled = value; + } + + public sealed class ShrinkCommandExecutingEvent : IShrinkEvent + { + public string ServiceName { get; set; } = ShrinkCommandConstants.DefaultServiceName; + public string RawInput { get; set; } = string.Empty; + public string CommandPath { get; set; } = string.Empty; + public string SourceId { get; set; } = string.Empty; + public string SourceDisplayName { get; set; } = string.Empty; + public Dictionary Arguments { get; set; } = new(); + } + + public sealed class ShrinkCommandExecutedEvent : IShrinkEvent + { + public string ServiceName { get; set; } = ShrinkCommandConstants.DefaultServiceName; + public string RawInput { get; set; } = string.Empty; + public string CommandPath { get; set; } = string.Empty; + public string SourceId { get; set; } = string.Empty; + public string SourceDisplayName { get; set; } = string.Empty; + public Dictionary Arguments { get; set; } = new(); + public bool IsSuccess { get; set; } + public string Message { get; set; } = string.Empty; + } + + public sealed class ShrinkCommandFailedEvent : IShrinkEvent + { + public string ServiceName { get; set; } = ShrinkCommandConstants.DefaultServiceName; + public string RawInput { get; set; } = string.Empty; + public string CommandPath { get; set; } = string.Empty; + public string SourceId { get; set; } = string.Empty; + public string SourceDisplayName { get; set; } = string.Empty; + public Dictionary Arguments { get; set; } = new(); + public string ErrorMessage { get; set; } = string.Empty; + } +} diff --git a/ShrinkCommandEventBusBridgeEvents.cs.meta b/ShrinkCommandEventBusBridgeEvents.cs.meta new file mode 100644 index 0000000..5cca210 --- /dev/null +++ b/ShrinkCommandEventBusBridgeEvents.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7f8b986a535559d41a2ab05a20708b28 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/ShrinkCommandEventBusBridgeExtensions.cs b/ShrinkCommandEventBusBridgeExtensions.cs new file mode 100644 index 0000000..5fc3831 --- /dev/null +++ b/ShrinkCommandEventBusBridgeExtensions.cs @@ -0,0 +1,29 @@ +#nullable enable +using System; +using Cysharp.Threading.Tasks; + +namespace ShrinkCommand.Integration +{ + public static class ShrinkCommandEventBusBridgeExtensions + { + public static ShrinkCommandService UseEventBusBridge( + this ShrinkCommandService service, + ShrinkCommandEventBusBridgeOptions? options = null) + { + if (service == null) + throw new ArgumentNullException(nameof(service)); + + ShrinkCommandEventBusBridge.RegisterService(service, options); + return service; + } + + public static UniTask RequestCommandAsync( + this ShrinkCommandService service, + string rawInput, + IShrinkCommandSource? source = null, + string? serviceName = null) + { + return ShrinkCommandEventBusBridge.RequestCommandAsync(rawInput, source, serviceName); + } + } +} diff --git a/ShrinkCommandEventBusBridgeExtensions.cs.meta b/ShrinkCommandEventBusBridgeExtensions.cs.meta new file mode 100644 index 0000000..afe3fa4 --- /dev/null +++ b/ShrinkCommandEventBusBridgeExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b0ed31dba396b6d4ab075e75a16b00d5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/ShrinkCommandEventBusBridgeOptions.cs b/ShrinkCommandEventBusBridgeOptions.cs new file mode 100644 index 0000000..7245a40 --- /dev/null +++ b/ShrinkCommandEventBusBridgeOptions.cs @@ -0,0 +1,10 @@ +#nullable enable + +namespace ShrinkCommand.Integration +{ + public sealed class ShrinkCommandEventBusBridgeOptions + { + public string ServiceName { get; set; } = ShrinkCommandConstants.DefaultServiceName; + public IShrinkCommandSource? DefaultSource { get; set; } + } +} diff --git a/ShrinkCommandEventBusBridgeOptions.cs.meta b/ShrinkCommandEventBusBridgeOptions.cs.meta new file mode 100644 index 0000000..5d31f14 --- /dev/null +++ b/ShrinkCommandEventBusBridgeOptions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c6de8286e0b74a54398432828ae503fb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/ShrinkCommandEventBusComponent.cs b/ShrinkCommandEventBusComponent.cs new file mode 100644 index 0000000..1c1ccd3 --- /dev/null +++ b/ShrinkCommandEventBusComponent.cs @@ -0,0 +1,36 @@ +#nullable enable + +using System.Collections.Generic; +using Cysharp.Threading.Tasks; +using ShrinkContext; + +namespace ShrinkCommand.Integration +{ + /// 通过命令服务键管理 Command ↔ EventBus 桥的可逆生命周期。 + public sealed class ShrinkCommandEventBusComponent : IShrinkComponent + { + public const string CommandServiceKey = "shrink.service.command"; + public const string ProvideKey = "shrink.integration.command-eventbus"; + + private static readonly string[] InjectKeys = { CommandServiceKey }; + private static readonly string[] ProvideKeys = { ProvideKey }; + + public string Name => "shrink.integration.command-eventbus"; + public IReadOnlyList Inject => InjectKeys; + public IReadOnlyList Provide => ProvideKeys; + + public UniTask ApplyAsync(ShrinkCtx ctx, object? config) + { + var service = ctx.Get(CommandServiceKey); + var options = config as ShrinkCommandEventBusBridgeOptions; + ShrinkCommandEventBusBridge.RegisterService(service, options); + ctx.EffectInverse(() => + { + ShrinkCommandEventBusBridge.UnregisterService(service); + return UniTask.CompletedTask; + }); + ctx.Set(ProvideKey, Name); + return UniTask.CompletedTask; + } + } +} diff --git a/ShrinkCommandEventBusComponent.cs.meta b/ShrinkCommandEventBusComponent.cs.meta new file mode 100644 index 0000000..2242a62 --- /dev/null +++ b/ShrinkCommandEventBusComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 078a765d611231c478ac77312b44c444 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package.json b/package.json new file mode 100644 index 0000000..31f1498 --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "name": "com.cneicy.shrink-command-integration-eventbus", + "version": "0.1.1", + "displayName": "ShrinkCommand - EventBus Integration", + "description": "ShrinkCommand 与 ShrinkEventBus 的桥接层,支持事件请求执行命令,以及命令执行生命周期事件发布。", + "unity": "2022.3", + "dependencies": { + "com.cneicy.shrink-command": "0.2.0", + "com.cneicy.shrink-context-core": "0.1.0", + "com.cneicy.shrink-eventbus": "2.0.0" + }, + "keywords": [ + "command", + "eventbus", + "integration", + "bridge" + ], + "author": { + "name": "cneicy", + "url": "https://git.crash.work/ShrinkSDK" + }, + "documentationUrl": "https://git.crash.work/ShrinkSDK/ShrinkCommand.Integration.EventBus", + "changelogUrl": "https://git.crash.work/ShrinkSDK/ShrinkCommand.Integration.EventBus/src/branch/main/CHANGELOG.md" +} diff --git a/package.json.meta b/package.json.meta new file mode 100644 index 0000000..8342f93 --- /dev/null +++ b/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 63114b97f96b400469a77b9701d8ffbc +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: