Compare commits
11 Commits
24f23b9385
...
tap2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04334691d0
|
||
|
|
ebd5dafa2d
|
||
|
fdd81aef19
|
|||
|
d98253e7ff
|
|||
|
2b9f134e5f
|
|||
|
97c9fba14e
|
|||
|
d7d15569c5
|
|||
|
1d6d908a2b
|
|||
|
69ce880d05
|
|||
|
379ac3fbd2
|
|||
|
|
00c4432007 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -41,3 +41,7 @@ sysinfo.txt
|
|||||||
# Crashlytics generated file
|
# Crashlytics generated file
|
||||||
Assets/StreamingAssets/crashlytics-build.properties
|
Assets/StreamingAssets/crashlytics-build.properties
|
||||||
|
|
||||||
|
.vscode
|
||||||
|
.vsconfig
|
||||||
|
.opencode
|
||||||
|
Assets/WwiseSettings.xml
|
||||||
63
.omo/boulder.json
Normal file
63
.omo/boulder.json
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
{
|
||||||
|
"schema_version": 2,
|
||||||
|
"active_work_id": "api-auth-fix-fb81d2ac",
|
||||||
|
"works": {
|
||||||
|
"api-auth-fix-fb81d2ac": {
|
||||||
|
"work_id": "api-auth-fix-fb81d2ac",
|
||||||
|
"active_plan": "/mnt/d/Projects/ichni_Official/.omo/plans/api-auth-fix.md",
|
||||||
|
"plan_name": "api-auth-fix",
|
||||||
|
"status": "active",
|
||||||
|
"started_at": "2026-06-17T09:10:43.670Z",
|
||||||
|
"updated_at": "2026-06-17T09:22:23.705Z",
|
||||||
|
"session_ids": [
|
||||||
|
"opencode:ses_12b516164ffekTIOv7bJsDWp4s"
|
||||||
|
],
|
||||||
|
"session_origins": {
|
||||||
|
"opencode:ses_12b516164ffekTIOv7bJsDWp4s": "direct"
|
||||||
|
},
|
||||||
|
"agent": "atlas",
|
||||||
|
"task_sessions": {
|
||||||
|
"todo:1": {
|
||||||
|
"task_key": "todo:1",
|
||||||
|
"task_label": "1",
|
||||||
|
"task_title": "Fix ApiResponse.cs + ApiClient.cs — GlobalResponse<T> camelCase + BaseUrl port",
|
||||||
|
"session_id": "opencode:ses_12b25b8bcffeXO77tLYyh5N2BA",
|
||||||
|
"agent": "Sisyphus-Junior",
|
||||||
|
"category": "quick",
|
||||||
|
"updated_at": "2026-06-17T09:22:23.705Z",
|
||||||
|
"started_at": "2026-06-17T09:20:19.050Z",
|
||||||
|
"status": "completed",
|
||||||
|
"ended_at": "2026-06-17T09:22:23.705Z",
|
||||||
|
"elapsed_ms": 124655
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"active_plan": "/mnt/d/Projects/ichni_Official/.omo/plans/api-auth-fix.md",
|
||||||
|
"started_at": "2026-06-17T09:10:43.670Z",
|
||||||
|
"status": "active",
|
||||||
|
"updated_at": "2026-06-17T09:22:23.705Z",
|
||||||
|
"session_ids": [
|
||||||
|
"opencode:ses_12b516164ffekTIOv7bJsDWp4s"
|
||||||
|
],
|
||||||
|
"session_origins": {
|
||||||
|
"opencode:ses_12b516164ffekTIOv7bJsDWp4s": "direct"
|
||||||
|
},
|
||||||
|
"plan_name": "api-auth-fix",
|
||||||
|
"task_sessions": {
|
||||||
|
"todo:1": {
|
||||||
|
"task_key": "todo:1",
|
||||||
|
"task_label": "1",
|
||||||
|
"task_title": "Fix ApiResponse.cs + ApiClient.cs — GlobalResponse<T> camelCase + BaseUrl port",
|
||||||
|
"session_id": "opencode:ses_12b25b8bcffeXO77tLYyh5N2BA",
|
||||||
|
"agent": "Sisyphus-Junior",
|
||||||
|
"category": "quick",
|
||||||
|
"updated_at": "2026-06-17T09:22:23.705Z",
|
||||||
|
"started_at": "2026-06-17T09:20:19.050Z",
|
||||||
|
"status": "completed",
|
||||||
|
"ended_at": "2026-06-17T09:22:23.705Z",
|
||||||
|
"elapsed_ms": 124655
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"agent": "atlas"
|
||||||
|
}
|
||||||
316
.omo/plans/api-auth-fix.md
Normal file
316
.omo/plans/api-auth-fix.md
Normal file
@@ -0,0 +1,316 @@
|
|||||||
|
# API Auth Access Fix — Unity Client
|
||||||
|
|
||||||
|
## TL;DR
|
||||||
|
|
||||||
|
> **Quick Summary**: Fix 3 critical bugs preventing the Unity client from successfully authenticating with the IchniOnline backend: wrong server port, GlobalResponse<T> field name mismatch (PascalCase vs camelCase) causing silent deserialization failure, and null pointer in third-party login flow.
|
||||||
|
>
|
||||||
|
> **Deliverables**:
|
||||||
|
> - `ApiResponse.cs` + `ApiClient.cs` — Atomic fix: fields renamed to camelCase, BaseUrl port corrected
|
||||||
|
> - `AuthService.cs` — null check added for third-party login response
|
||||||
|
>
|
||||||
|
> **Estimated Effort**: Quick (3 files, targeted changes)
|
||||||
|
> **Parallel Execution**: YES — all 3 tasks can run in parallel (independent files)
|
||||||
|
> **Critical Path**: None (no dependencies between tasks)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
### Original Request
|
||||||
|
用户要求结合后端工程和 Apifox API 文档来对 `Assets/Scripts/Online` 目录里的 API 访问进行检查和修复,仅处理认证相关接口。
|
||||||
|
|
||||||
|
### Interview Summary
|
||||||
|
**Key Discussions**:
|
||||||
|
- Only auth-related endpoints in scope: login, register, session-key, third-party login
|
||||||
|
- Ignore beatmap and other APIs for now
|
||||||
|
- Only modify files within `Assets/Scripts/Online/`
|
||||||
|
|
||||||
|
**Research Findings**:
|
||||||
|
- Server (ASP.NET Core) uses `System.Text.Json` with camelCase policy → JSON keys: `code`, `message`, `data`
|
||||||
|
- Unity client uses `JsonUtility.FromJson` which is **case-sensitive** → C# field names must exactly match JSON keys
|
||||||
|
- Current `GlobalResponse<T>` has PascalCase `Code`/`Message`/`Data` → **silent deserialization failure**
|
||||||
|
- Server runs on `http://localhost:5308` (launchSettings.json) but Unity client has `http://localhost:60887` → **all requests fail**
|
||||||
|
- Third-party login can return `data: null` (unbound account) → **NullReferenceException** when accessing `result.Data.token`
|
||||||
|
|
||||||
|
### Metis Review
|
||||||
|
*Skipped — clear scope, direct bugs, user confirmed approach.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Work Objectives
|
||||||
|
|
||||||
|
### Core Objective
|
||||||
|
Fix the Unity client's auth API access so that all 4 auth endpoints (session-key, login, register, third-party login) successfully communicate with the IchniOnline backend.
|
||||||
|
|
||||||
|
### Concrete Deliverables
|
||||||
|
- `Assets/Scripts/Online/Network/Models/ApiResponse.cs` — GlobalResponse field names corrected
|
||||||
|
- `Assets/Scripts/Online/Network/ApiClient.cs` — BaseUrl port fixed, field access updated
|
||||||
|
- `Assets/Scripts/Online/Logic/AuthService.cs` — null-safe third-party login handling
|
||||||
|
|
||||||
|
### Definition of Done
|
||||||
|
- `IchniOnlineApiClient.Instance.BaseUrl` returns `http://localhost:5308`
|
||||||
|
- `JsonUtility.FromJson` correctly populates `GlobalResponse<T>.code`/`message`/`data`
|
||||||
|
- Third-party login with unbound account does not throw NullReferenceException
|
||||||
|
- All 3 auth flows (password login, TapTap login, register) return correct `ApiResult`
|
||||||
|
|
||||||
|
### Must Have
|
||||||
|
- Fix BaseUrl port from 60887 to 5308
|
||||||
|
- Fix `GlobalResponse<T>` field names to match JSON camelCase
|
||||||
|
- Add null check for `result.Data` in third-party login flow
|
||||||
|
- All changes within `Assets/Scripts/Online/` only
|
||||||
|
|
||||||
|
### Must NOT Have (Guardrails)
|
||||||
|
- Do NOT touch beatmap or non-auth API code
|
||||||
|
- Do NOT modify files outside `Assets/Scripts/Online/`
|
||||||
|
- Do NOT add Newtonsoft.Json or other new dependencies
|
||||||
|
- Do NOT refactor architecture (stay minimal, targeted fixes)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Verification Strategy (MANDATORY)
|
||||||
|
|
||||||
|
> **ZERO HUMAN INTERVENTION** — ALL verification is agent-executed.
|
||||||
|
|
||||||
|
### Test Decision
|
||||||
|
- **Infrastructure exists**: NO
|
||||||
|
- **Automated tests**: None
|
||||||
|
- **Framework**: N/A
|
||||||
|
|
||||||
|
### QA Policy
|
||||||
|
Every task MUST include agent-executed QA scenarios. Evidence saved to `.omo/evidence/task-{N}-{scenario-slug}.{ext}`.
|
||||||
|
|
||||||
|
- **Library/Module verification**: Use Bash (bun/node REPL style) with `script-execute` to run C# test snippets that directly verify `JsonUtility.FromJson` deserialization behavior
|
||||||
|
- **Code review verification**: Read modified files and verify correctness by cross-referencing with server API contracts
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Execution Strategy
|
||||||
|
|
||||||
|
```
|
||||||
|
Wave 1 (Start Immediately):
|
||||||
|
├── Task 1: Fix ApiResponse.cs + ApiClient.cs — GlobalResponse camelCase + BaseUrl port [quick]
|
||||||
|
└── Task 2: Fix AuthService.cs — third-party login null check [quick]
|
||||||
|
|
||||||
|
Wave FINAL (After ALL tasks):
|
||||||
|
├── Task F1: QA verification (oracle)
|
||||||
|
└── Task F2: Scope fidelity check (deep)
|
||||||
|
|
||||||
|
Critical Path: Task 1 → F1, F2 (independent from Task 2)
|
||||||
|
Parallel Speedup: ~50% faster than sequential (Task 1 and Task 2 run in parallel)
|
||||||
|
Max Concurrent: 2 (both in Wave 1)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## TODOs
|
||||||
|
|
||||||
|
- [x] 1. Fix ApiResponse.cs + ApiClient.cs — GlobalResponse<T> camelCase + BaseUrl port
|
||||||
|
|
||||||
|
**What to do**:
|
||||||
|
- In `ApiResponse.cs`: Rename field `Code` → `code`, `Message` → `message`, `Data` → `data`
|
||||||
|
- In `ApiClient.cs`:
|
||||||
|
- Change `BaseUrl` default from `"http://localhost:60887"` to `"http://localhost:5308"`
|
||||||
|
- Update all references to `GlobalResponse<T>` fields from PascalCase to camelCase:
|
||||||
|
- `response.Code` → `response.code`
|
||||||
|
- `response.Message` → `response.message`
|
||||||
|
- `response.Data` → `response.data`
|
||||||
|
- `errorResponse.Code` → `errorResponse.code`
|
||||||
|
- `errorResponse.Message` → `errorResponse.message`
|
||||||
|
- Verify: `ResponseCode` enum values remain unchanged (Ok=10000, etc.)
|
||||||
|
- Verify no other PascalCase field access patterns exist in ApiClient.cs
|
||||||
|
|
||||||
|
> **Rationale for merging**: ApiResponse.cs declares the fields, ApiClient.cs consumes them. Both files must be changed atomically — if committed separately, the codebase is broken regardless of order. A single agent handles both files in one task to guarantee correctness.
|
||||||
|
|
||||||
|
**Must NOT do**:
|
||||||
|
- Do not change `ResponseCode` enum values or names
|
||||||
|
- Do not change `ApiResult<T>` class structure
|
||||||
|
- Do not add `[JsonProperty]` or other attributes
|
||||||
|
- Do not change the `BuildUrl`, `AddAuthHeader`, or `SendAsync` methods
|
||||||
|
- Do not change the method signatures of `GetAsync<T>` or `PostAsync<T>`
|
||||||
|
|
||||||
|
**Recommended Agent Profile**:
|
||||||
|
> - **Category**: `quick`
|
||||||
|
> - Reason: Two files, simple field rename + port change, no logic changes
|
||||||
|
> - **Skills**: none required
|
||||||
|
> - **Skills Evaluated but Omitted**: N/A
|
||||||
|
|
||||||
|
**Parallelization**:
|
||||||
|
> - **Can Run In Parallel**: NO (merged from previous Tasks 1+2 due to compilation dependency)
|
||||||
|
> - **Parallel Group**: Wave 1 (with Task 2)
|
||||||
|
> - **Blocks**: None
|
||||||
|
> - **Blocked By**: None (can start immediately)
|
||||||
|
|
||||||
|
**References**:
|
||||||
|
- `Assets/Scripts/Online/Network/Models/ApiResponse.cs` — Field declaration site
|
||||||
|
- `Assets/Scripts/Online/Network/ApiClient.cs` — Field usage site + BaseUrl
|
||||||
|
- Server `GlobalResponse.cs` at `/mnt/d/Projects/IchniOnline/IchniOnline.Server/Models/Responses/GlobalResponse.cs` — Reference (PascalCase with System.Text.Json camelCase policy)
|
||||||
|
- Backend `launchSettings.json` at `/mnt/d/Projects/IchniOnline/IchniOnline.Server/Properties/launchSettings.json` — Confirms port 5308
|
||||||
|
- Current JSON wire format: `{"code":10000,"message":"Success","data":{...}}` — JSON keys are lowercase
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- `ApiResponse.cs` field declarations use camelCase: `code`, `message`, `data`
|
||||||
|
- `ApiClient.cs` field references use camelCase: `response.code`, `response.message`, `response.data`
|
||||||
|
- `ApiClient.cs` BaseUrl line 20: `"http://localhost:5308"`
|
||||||
|
- `script-execute` confirms `JsonUtility.FromJson<GlobalResponse<string>>` correctly deserializes `{"code":10000,"message":"OK","data":"test"}`
|
||||||
|
|
||||||
|
**QA Scenarios (MANDATORY)**:
|
||||||
|
```
|
||||||
|
Scenario: Verify GlobalResponse deserialization works with camelCase JSON
|
||||||
|
Tool: script-execute (C# Roslyn)
|
||||||
|
Preconditions: Both files have been modified
|
||||||
|
Steps:
|
||||||
|
1. Use script-execute to run: string json = "{\\\"code\\\":10000,\\\"message\\\":\\\"OK\\\",\\\"data\\\":\\\"test\\\"}";
|
||||||
|
2. Deserialize: var obj = UnityEngine.JsonUtility.FromJson<GlobalResponse<string>>(json);
|
||||||
|
3. Assert: obj.code == (ResponseCode)10000
|
||||||
|
4. Assert: obj.message == "OK"
|
||||||
|
5. Assert: obj.data == "test"
|
||||||
|
Expected Result: All 3 fields are correctly populated from camelCase JSON keys
|
||||||
|
Failure Indicators: Any field remains default (0/null)
|
||||||
|
Evidence: .omo/evidence/task-1-globalresponse-deserialize.txt
|
||||||
|
|
||||||
|
Scenario: Verify GlobalResponseBase error deserialization
|
||||||
|
Tool: script-execute
|
||||||
|
Preconditions: Both files have been modified
|
||||||
|
Steps:
|
||||||
|
1. Use script-execute to run: string json = "{\\\"code\\\":10400,\\\"message\\\":\\\"Bad request\\\"}";
|
||||||
|
2. Deserialize as base: var obj = UnityEngine.JsonUtility.FromJson<GlobalResponseBase>(json);
|
||||||
|
3. Assert: obj.code == (ResponseCode)10400
|
||||||
|
4. Assert: obj.message == "Bad request"
|
||||||
|
Expected Result: Error response fields are correctly populated
|
||||||
|
Evidence: .omo/evidence/task-1-globalresponsebase-deserialize.txt
|
||||||
|
|
||||||
|
Scenario: Verify BaseUrl port is corrected
|
||||||
|
Tool: script-read
|
||||||
|
Preconditions: ApiClient.cs has been updated
|
||||||
|
Steps:
|
||||||
|
1. Read line 20 of ApiClient.cs
|
||||||
|
2. Assert: BaseUrl default value is "http://localhost:5308"
|
||||||
|
Expected Result: Port is corrected to 5308
|
||||||
|
Evidence: .omo/evidence/task-1-baseurl.txt
|
||||||
|
|
||||||
|
Scenario: Verify all GlobalResponse field references use camelCase in ApiClient.cs
|
||||||
|
Tool: grep
|
||||||
|
Preconditions: ApiClient.cs has been updated
|
||||||
|
Steps:
|
||||||
|
1. Search for pattern: "response\.Code" in ApiClient.cs — should return 0 matches
|
||||||
|
2. Search for pattern: "response\.code" — should return 2+ matches
|
||||||
|
3. Search for pattern: "errorResponse\.Code" — should return 0 matches
|
||||||
|
4. Search for pattern: "errorResponse\.code" — should return 2+ matches
|
||||||
|
Expected Result: All PascalCase field references replaced with camelCase
|
||||||
|
Evidence: .omo/evidence/task-1-field-access.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
**Evidence to Capture**:
|
||||||
|
- [ ] script-execute output for deserialization test
|
||||||
|
- [ ] Line 20 read output
|
||||||
|
- [ ] grep results for field access patterns
|
||||||
|
|
||||||
|
**Commit**: YES
|
||||||
|
- Message: `fix(api): rename GlobalResponse<T> fields to camelCase, correct BaseUrl port to 5308`
|
||||||
|
- Files: `Assets/Scripts/Online/Network/Models/ApiResponse.cs`, `Assets/Scripts/Online/Network/ApiClient.cs`
|
||||||
|
- Pre-commit: Verify build compiles
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
- [x] 2. Fix AuthService.cs — third-party login null check
|
||||||
|
|
||||||
|
**What to do**:
|
||||||
|
- In `CompleteTapTapLoginAsync` method (~line 109): Add null check for `result.Data` before accessing `.token`
|
||||||
|
- Handle the case where third-party login succeeds (code=10000) but data is null (unbound account):
|
||||||
|
- If `result.IsSuccess && result.Data != null`: proceed normally (save session, set JWT, fire success)
|
||||||
|
- If `result.IsSuccess && result.Data == null`: fire `OnLoginFailed` with a clear message about account not being bound/linked
|
||||||
|
|
||||||
|
**Must NOT do**:
|
||||||
|
- Do not change the password login flow (LoginWithPasswordAsync)
|
||||||
|
- Do not change register flow
|
||||||
|
- Do not change the encryption logic
|
||||||
|
- Do not modify ThirdPartyServiceManager
|
||||||
|
|
||||||
|
**Recommended Agent Profile**:
|
||||||
|
> - **Category**: `quick`
|
||||||
|
> - Reason: Single null check addition in one method
|
||||||
|
> - **Skills**: none required
|
||||||
|
> - **Skills Evaluated but Omitted**: N/A
|
||||||
|
|
||||||
|
**Parallelization**:
|
||||||
|
> - **Can Run In Parallel**: YES
|
||||||
|
> - **Parallel Group**: Wave 1 (with Tasks 1, 2)
|
||||||
|
> - **Blocks**: None
|
||||||
|
> - **Blocked By**: None
|
||||||
|
|
||||||
|
**References**:
|
||||||
|
- `Assets/Scripts/Online/Logic/AuthService.cs` — File to edit
|
||||||
|
- Server `AuthController.cs` at `/mnt/d/Projects/IchniOnline/IchniOnline.Server/Controller/AuthController.cs` lines 70-77 — Shows the `ThirdPartyLogin` can return `GlobalResponse<LoginResponse>.Ok(null, "Account not bound")`
|
||||||
|
- `ApiResponse.cs` `ApiResult<T>` class — For understanding `IsSuccess`, `Data` properties
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- `CompleteTapTapLoginAsync` method has null guard before `result.Data.token` access
|
||||||
|
- When `result.IsSuccess && result.Data == null`: calls `OnLoginFailed` with message containing "not bound" or "unbound"
|
||||||
|
- When `result.IsSuccess && result.Data != null`: saves auth session, sets JWT, fires `OnLoginSuccess`
|
||||||
|
- Password login flow (`LoginWithPasswordAsync`) is unchanged
|
||||||
|
|
||||||
|
**QA Scenarios (MANDATORY)**:
|
||||||
|
```
|
||||||
|
Scenario: Verify null data handling for third-party login
|
||||||
|
Tool: script-read
|
||||||
|
Preconditions: AuthService.cs has been updated
|
||||||
|
Steps:
|
||||||
|
1. Read the CompleteTapTapLoginAsync method
|
||||||
|
2. Verify: there is a null check for result.Data before result.Data.token access
|
||||||
|
3. Verify: null case calls OnLoginFailed with appropriate message
|
||||||
|
Expected Result: NullReferenceException is prevented
|
||||||
|
Evidence: .omo/evidence/task-2-null-check.txt
|
||||||
|
|
||||||
|
Scenario: Verify password login flow is unchanged
|
||||||
|
Tool: grep
|
||||||
|
Preconditions: AuthService.cs has been updated
|
||||||
|
Steps:
|
||||||
|
1. Search for "result\.Data\.token" in AuthService.cs — should only appear in the TapTap completion method
|
||||||
|
2. Verify all occurrences have null guards
|
||||||
|
Expected Result: No unprotected access to result.Data.token
|
||||||
|
Evidence: .omo/evidence/task-2-password-flow.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
**Evidence to Capture**:
|
||||||
|
- [ ] Read output showing the null check code
|
||||||
|
- [ ] grep results
|
||||||
|
|
||||||
|
**Commit**: YES
|
||||||
|
- Message: `fix(auth): add null check for third-party login response data`
|
||||||
|
- Files: `Assets/Scripts/Online/Logic/AuthService.cs`
|
||||||
|
- Pre-commit: Verify build compiles
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Final Verification Wave
|
||||||
|
|
||||||
|
- [ ] F1. **Plan Compliance Audit** — `oracle`
|
||||||
|
Read the plan end-to-end. For each "Must Have": verify implementation exists (read file, check values). For each "Must NOT Have": search codebase for forbidden patterns — reject with file:line if found. Check evidence files exist in .omo/evidence/. Compare deliverables against plan.
|
||||||
|
Output: `Must Have [N/N] | Must NOT Have [N/N] | Tasks [N/N] | VERDICT: APPROVE/REJECT`
|
||||||
|
|
||||||
|
- [ ] F2. **Scope Fidelity Check** — `deep`
|
||||||
|
For each task: read "What to do", read actual diff (git log/diff). Verify 1:1 — everything in spec was built (no missing), nothing beyond spec was built (no creep). Check "Must NOT do" compliance. Detect cross-task contamination.
|
||||||
|
Output: `Tasks [N/N compliant] | Contamination [CLEAN/N issues] | VERDICT`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Commit Strategy
|
||||||
|
|
||||||
|
- **1**: `fix(api): rename GlobalResponse<T> fields to camelCase, correct BaseUrl port to 5308`
|
||||||
|
- Files: `ApiResponse.cs`, `ApiClient.cs`
|
||||||
|
- **2**: `fix(auth): add null check for third-party login response data`
|
||||||
|
- Files: `AuthService.cs`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Success Criteria
|
||||||
|
|
||||||
|
### Verification Scenarios
|
||||||
|
1. `script-execute` confirms `JsonUtility.FromJson<GlobalResponse<string>>` correctly parses `{"code":10000,"message":"OK","data":"test"}`
|
||||||
|
2. `ApiClient.cs` line 20 shows `BaseUrl = "http://localhost:5308"`
|
||||||
|
3. `AuthService.cs` has null guard before `result.Data.token` access
|
||||||
|
|
||||||
|
### Final Checklist
|
||||||
|
- [ ] All "Must Have" present
|
||||||
|
- [ ] All "Must NOT Have" absent
|
||||||
|
- [ ] All 3 files modified correctly
|
||||||
918
.omo/plans/online-api-integration.md
Normal file
918
.omo/plans/online-api-integration.md
Normal file
@@ -0,0 +1,918 @@
|
|||||||
|
# Plan: IchniOnline API Integration
|
||||||
|
|
||||||
|
## TL;DR
|
||||||
|
|
||||||
|
> **Quick Summary**: Create an HTTP API client layer using BestHTTP and implement full auth flows (TapTap third-party login, password login, registration) to connect the Unity game client to the IchniOnline backend server.
|
||||||
|
>
|
||||||
|
> **Deliverables**:
|
||||||
|
> - BestHTTP-based API client with JSON serialization, JWT injection, error handling
|
||||||
|
> - Request/Response DTOs matching server contracts
|
||||||
|
> - Auth orchestration service (TapTap login, password login, register, logout)
|
||||||
|
> - Extended LoginCacheData with JWT + server user data
|
||||||
|
> - Updated LoginPage/StartUIPage to use new auth service
|
||||||
|
>
|
||||||
|
> **Estimated Effort**: Medium
|
||||||
|
> **Parallel Execution**: YES — 4 waves
|
||||||
|
> **Critical Path**: asmdef → ApiClient → AuthService → UI Integration
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
### Original Request
|
||||||
|
对接 IchniOnline 后端的 API 接口,使用 BestHTTP 进行 HTTP 通信,编写详细计划。所有代码写在 `Scripts/Online` 目录内(IchniOnline.asmdef)。
|
||||||
|
|
||||||
|
### Interview Summary
|
||||||
|
**Key Discussions**:
|
||||||
|
- 服务器开发地址: `localhost:5433`,可配置 Base URL
|
||||||
|
- ThirdParty.Unbound: 暂时跳过,当做登录失败处理
|
||||||
|
- JWT 存储: 扩展 LoginCacheData,加入 JWT + 用户数据,取代纯 TapTap 缓存
|
||||||
|
- 计划范围: TapTap 登录 + 密码登录/注册 + 基础 API 框架
|
||||||
|
|
||||||
|
**Research Findings**:
|
||||||
|
- **BestHTTP** 已安装为 embedded package (`com.tivadar.best.http`),GUID: `9069ac25d95ca17448a247f3bb1c769f`,支持 async/await via `Task<T>`
|
||||||
|
- **TapTap SDK** 登录返回 `TapTapAccount.accessToken`(kid/tokenType/macKey/macAlgorithm),可直接映射到 `ThirdPartyLoginRequest`
|
||||||
|
- **服务端密码加密**: XOR with session key(见 `UserService.DecryptPassword`)
|
||||||
|
- **服务端响应格式**: `GlobalResponse<T> { Code, Message, Data }`,Code 10000=Ok
|
||||||
|
- **JWT 验证**: 服务端使用 JWT Bearer,后续 API 请求需在 Header 注入 `Authorization: Bearer {token}`
|
||||||
|
|
||||||
|
### Metis Review
|
||||||
|
*(Skipped per user request — direct exploration used instead)*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Work Objectives
|
||||||
|
|
||||||
|
### Core Objective
|
||||||
|
为 Unity 客户端创建 IchniOnline 后端 API 对接层,实现完整的认证流程(TapTap 第三方登录、密码登录、注册),让客户端和服务端互通。
|
||||||
|
|
||||||
|
### Concrete Deliverables
|
||||||
|
- `Scripts/Online/IchniOnline.asmdef` — 添加 BestHTTP 引用
|
||||||
|
- `Scripts/Online/Network/ApiClient.cs` — BestHTTP 封装单例
|
||||||
|
- `Scripts/Online/Network/Models/ApiResponse.cs` — 响应模型
|
||||||
|
- `Scripts/Online/Network/Models/AuthDtos.cs` — 请求/响应 DTO
|
||||||
|
- `Scripts/Online/Logic/AuthService.cs` — 认证编排服务
|
||||||
|
- `Scripts/Online/Logic/ThirdPartyServiceManager.cs` — 修改:集成 AuthService
|
||||||
|
- `Scripts/Online/Logic/LoginCacheManager.cs` — 修改:扩展 JWT 支持
|
||||||
|
- `Scripts/Online/Models/LoginCacheData.cs` — 修改:添加 JWT 字段
|
||||||
|
|
||||||
|
### Definition of Done
|
||||||
|
- [ ] 编译零错误,无警告
|
||||||
|
- [ ] TapTap 登录后 JWT Token 成功写入本地缓存
|
||||||
|
- [ ] 密码登录流程完整(session key → XOR 加密 → login → JWT)
|
||||||
|
- [ ] 注册流程完整
|
||||||
|
- [ ] LoginPage 使用新 AuthService 驱动流程
|
||||||
|
- [ ] StartUIPage 校验会话有效性
|
||||||
|
|
||||||
|
### Must Have
|
||||||
|
- ApiClient 支持 Base URL 配置(运行时可修改)
|
||||||
|
- ApiClient 自动注入 JWT Bearer 到 Authorization Header
|
||||||
|
- 所有 DTO 映射与服务器 `GlobalResponse<T>` 完全匹配
|
||||||
|
- 密码 XOR 加密算法与服务器端一致
|
||||||
|
- AuthService 对外暴露事件(OnLoginSuccess/OnLoginFailed/etc.)
|
||||||
|
- LoginCacheData 向后兼容(旧缓存不报错)
|
||||||
|
|
||||||
|
### Must NOT Have (Guardrails)
|
||||||
|
- 不要引入新的第三方 HTTP 库(只用 BestHTTP)
|
||||||
|
- 不要修改 `LoginCacheEditor.cs`(但可扩展)
|
||||||
|
- 不要修改 `UI/Base/UIPageBase.cs`
|
||||||
|
- 不要引入 Newtonsoft.Json(用 BestHTTP 内置的 LitJson 或 UnityEngine.JsonUtility)
|
||||||
|
- 不要阻塞主线程(所有 HTTP 请求必须异步)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Verification Strategy
|
||||||
|
|
||||||
|
### Test Decision
|
||||||
|
- **Infrastructure exists**: YES (Unity Test Framework)
|
||||||
|
- **Automated tests**: None for network layer (needs running server)
|
||||||
|
- **Agent-Executed QA**: ALWAYS — each task verified via Playwright/browser or manual Unity Editor play mode evidence
|
||||||
|
|
||||||
|
### QA Policy
|
||||||
|
Every task MUST include agent-executed QA scenarios.
|
||||||
|
- C# compilation through Unity Editor domain reload (verify zero compilation errors)
|
||||||
|
- Evidence: Unity Editor console logs, screenshots of play mode, runtime log output
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Execution Strategy
|
||||||
|
|
||||||
|
### Parallel Execution Waves
|
||||||
|
|
||||||
|
```
|
||||||
|
Wave 1 (Foundation — all parallel):
|
||||||
|
├── Task 1: IchniOnline.asmdef — 添加 BestHTTP 引用 [quick]
|
||||||
|
├── Task 2: ApiResponse.cs — GlobalResponse<T> 响应模型 [quick]
|
||||||
|
├── Task 3: AuthDtos.cs — 请求/响应 DTO [quick]
|
||||||
|
└── Task 4: LoginCacheData.cs — 扩展 JWT 字段 [quick]
|
||||||
|
|
||||||
|
Wave 2 (Core Client — depends on Wave 1):
|
||||||
|
├── Task 5: ApiClient.cs — BestHTTP 封装单例 [unspecified-high]
|
||||||
|
└── Task 6: LoginCacheManager.cs — 扩展 JWT 存取 [quick]
|
||||||
|
Note: Task 5+6 can run in parallel
|
||||||
|
|
||||||
|
Wave 3 (Auth Service — depends on Task 5+6):
|
||||||
|
├── Task 7: AuthService.cs — 认证编排服务 [unspecified-high]
|
||||||
|
Note: Depends on ApiClient + LoginCacheManager
|
||||||
|
|
||||||
|
Wave 4 (UI Integration — depends on Task 7):
|
||||||
|
├── Task 8: ThirdPartyServiceManager.cs — 集成 AuthService [quick]
|
||||||
|
├── Task 9: LoginPage.cs — 使用新 AuthService [visual-engineering]
|
||||||
|
└── Task 10: StartUIPage.cs — 校验会话有效性 [visual-engineering]
|
||||||
|
|
||||||
|
Wave FINAL:
|
||||||
|
├── F1: Plan Compliance Audit (oracle)
|
||||||
|
├── F2: Code Quality Review (unspecified-high)
|
||||||
|
├── F3: Real Manual QA (unspecified-high)
|
||||||
|
└── F4: Scope Fidelity Check (deep)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dependency Matrix
|
||||||
|
- **Task 1-4**: - → 5, 6 → Wave 2
|
||||||
|
- **Task 5, 6**: 1-4 → 7 → Wave 3
|
||||||
|
- **Task 7**: 5, 6 → 8-10 → Wave 4
|
||||||
|
- **Task 8-10**: 7 → F1-F4 → Final
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## TODOs
|
||||||
|
|
||||||
|
- [x] 1. IchniOnline.asmdef — 添加 BestHTTP 引用
|
||||||
|
|
||||||
|
**What to do**:
|
||||||
|
- 在 `IchniOnline.asmdef` 的 `references` 数组中追加 BestHTTP 的 GUID
|
||||||
|
- BestHTTP Runtime asmdef GUID: `9069ac25d95ca17448a247f3bb1c769f`
|
||||||
|
- 验证 Unity 编译无误,IchniOnline 程序集可以 `using Best.HTTP;`
|
||||||
|
|
||||||
|
**Must NOT do**:
|
||||||
|
- 不要修改其他 asmdef
|
||||||
|
- 不要修改 IchniOnline.Editor.asmdef
|
||||||
|
|
||||||
|
**Recommended Agent Profile**:
|
||||||
|
- **Category**: `quick`
|
||||||
|
- Reason: 单行 asmdef 修改,极简单的任务
|
||||||
|
- **Skills**: None needed
|
||||||
|
|
||||||
|
**Parallelization**:
|
||||||
|
- **Can Run In Parallel**: YES
|
||||||
|
- **Parallel Group**: Wave 1 (with Tasks 2, 3, 4)
|
||||||
|
- **Blocks**: Tasks 5, 6
|
||||||
|
- **Blocked By**: None
|
||||||
|
|
||||||
|
**References**:
|
||||||
|
- `Assets/Scripts/Online/IchniOnline.asmdef` — 目标文件
|
||||||
|
- `Packages/com.tivadar.best.http/Runtime/com.Tivadar.Best.HTTP.asmdef.meta:L1-7` — GUID: `9069ac25d95ca17448a247f3bb1c769f`
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] `IchniOnline.asmdef` 的 `references` 数组包含 `"GUID:9069ac25d95ca17448a247f3bb1c769f"`
|
||||||
|
- [ ] Unity 编译完成后,IchniOnline 程序集内可以 `using Best.HTTP;` 无报错
|
||||||
|
|
||||||
|
**QA Scenarios**:
|
||||||
|
```
|
||||||
|
Scenario: asmdef 引用验证
|
||||||
|
Tool: Bash (配合 Unity Editor)
|
||||||
|
Preconditions: Unity Editor 已打开,IchniOnline.asmdef 已修改
|
||||||
|
Steps:
|
||||||
|
1. 在 Unity 中等待编译完成(AssetDatabase.Refresh 或观察 Console 无红错)
|
||||||
|
2. 打开 `Assets/Scripts/Online/IchniOnline.asmdef` 确认 references 包含 BestHTTP GUID
|
||||||
|
Expected Result: 编译零错误,无 warning
|
||||||
|
Evidence: .omo/evidence/task-1-asmdef-refs.png (Editor 无错误截图)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Commit**: YES (group with Tasks 2-4)
|
||||||
|
- Message: `feat(online): add BestHTTP reference to IchniOnline.asmdef`
|
||||||
|
- Files: `Assets/Scripts/Online/IchniOnline.asmdef`
|
||||||
|
- Pre-commit: 验证 Unity 编译通过
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
- [x] 2. ApiResponse.cs — 创建服务端响应模型
|
||||||
|
|
||||||
|
**What to do**:
|
||||||
|
- 新建文件: `Assets/Scripts/Online/Network/Models/ApiResponse.cs`
|
||||||
|
- 定义 `ResponseCode` enum(匹配服务端 `Models/Responses/ResponseCode.cs`)
|
||||||
|
- 定义 `GlobalResponse<T>` class(匹配服务端 `GlobalResponse<T>`)
|
||||||
|
- 定义 `ApiResult<T>` 封装类,包含成功/失败状态 + 错误信息
|
||||||
|
- 使用 `System.Text.Json` 或 `UnityEngine.JsonUtility` 做序列化(优先 JsonUtility 避免额外依赖)
|
||||||
|
- 命名空间: `IchniOnline.Online.Network.Models`
|
||||||
|
|
||||||
|
**关键映射**:
|
||||||
|
```csharp
|
||||||
|
// 服务端 ResponseCode
|
||||||
|
public enum ResponseCode {
|
||||||
|
Ok = 10000,
|
||||||
|
BadRequest = 10400,
|
||||||
|
Unauthorized = 10401,
|
||||||
|
Forbidden = 10403,
|
||||||
|
NotFound = 10404,
|
||||||
|
InternalServerError = 10500
|
||||||
|
}
|
||||||
|
|
||||||
|
// 服务端 GlobalResponse<T>
|
||||||
|
// 注意: Unity JsonUtility 不支持泛型直接反序列化,需要包装或使用封装层
|
||||||
|
// 方案: 实现一个非泛型的 ApiResponse 做中间反序列化,再通过 ApiResult<T> 取 Data
|
||||||
|
```
|
||||||
|
|
||||||
|
**Must NOT do**:
|
||||||
|
- 不要引入 Newtonsoft.Json(项目中已无引用)
|
||||||
|
- 不要将序列化逻辑写死到 ApiClient 之外
|
||||||
|
|
||||||
|
**Recommended Agent Profile**:
|
||||||
|
- **Category**: `quick`
|
||||||
|
- Reason: 纯数据模型定义,无复杂逻辑
|
||||||
|
- **Skills**: None
|
||||||
|
|
||||||
|
**Parallelization**:
|
||||||
|
- **Can Run In Parallel**: YES
|
||||||
|
- **Parallel Group**: Wave 1 (with Tasks 1, 3, 4)
|
||||||
|
- **Blocks**: Tasks 5, 6
|
||||||
|
- **Blocked By**: None
|
||||||
|
|
||||||
|
**References**:
|
||||||
|
- `D:\Projects\IchniOnline\IchniOnline.Server\Models\Responses\GlobalResponse.cs` — 服务端 GlobalResponse 实现
|
||||||
|
- `D:\Projects\IchniOnline\IchniOnline.Server\Models\Responses\ResponseCode.cs` — 服务端 ResponseCode enum
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] `ApiResponse.cs` 中定义 `ResponseCode` enum(Ok/BadRequest/Unauthorized/Forbidden/NotFound/InternalServerError)
|
||||||
|
- [ ] `GlobalResponse<T>` class 包含 Code/Message/Data 三个字段
|
||||||
|
- [ ] Unity 编译通过,无错误
|
||||||
|
|
||||||
|
**QA Scenarios**:
|
||||||
|
```
|
||||||
|
Scenario: 编译验证
|
||||||
|
Tool: Unity Editor
|
||||||
|
Preconditions: 文件创建完成,Unity 编译通过
|
||||||
|
Steps:
|
||||||
|
1. 在任意脚本中添加 `using IchniOnline.Online.Network.Models;`
|
||||||
|
2. 使用 `ResponseCode.Ok` 确认 enum 可用
|
||||||
|
Expected Result: 编译零错误
|
||||||
|
Evidence: .omo/evidence/task-2-compile.png
|
||||||
|
```
|
||||||
|
|
||||||
|
**Commit**: YES (group with Tasks 1, 3, 4)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
- [x] 3. AuthDtos.cs — 创建认证请求/响应 DTO
|
||||||
|
|
||||||
|
**What to do**:
|
||||||
|
- 新建文件: `Assets/Scripts/Online/Network/Models/AuthDtos.cs`
|
||||||
|
- 定义以下 DTO(匹配服务端 Models):
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 请求 DTO
|
||||||
|
[System.Serializable]
|
||||||
|
public class ThirdPartyLoginRequestDto {
|
||||||
|
public string Token; // accessToken.kid
|
||||||
|
public string TokenType; // accessToken.tokenType ("mac")
|
||||||
|
public string MacKey; // accessToken.macKey
|
||||||
|
public string MacAlgorithm; // accessToken.macAlgorithm ("hmac-sha-1")
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.Serializable]
|
||||||
|
public class LoginRequestDto {
|
||||||
|
public string Username;
|
||||||
|
public string EncryptedPassword; // Base64 of XOR'd bytes
|
||||||
|
public string SessionKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.Serializable]
|
||||||
|
public class RegisterRequestDto {
|
||||||
|
public string Username;
|
||||||
|
public string Password;
|
||||||
|
public string DisplayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 响应 DTO(与服务端 AuthResponse.cs 对应)
|
||||||
|
[System.Serializable]
|
||||||
|
public class SessionKeyResponseDto {
|
||||||
|
public string sessionKey;
|
||||||
|
public string expiresAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.Serializable]
|
||||||
|
public class LoginResponseDto {
|
||||||
|
public string Token; // JWT
|
||||||
|
public UserResponseDto User;
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.Serializable]
|
||||||
|
public class UserResponseDto {
|
||||||
|
public string UserId;
|
||||||
|
public string Username;
|
||||||
|
public string DisplayName;
|
||||||
|
public string AvatarUrl;
|
||||||
|
public int Permission; // 0=Guest, 1=Player, 2=Admin
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Must NOT do**:
|
||||||
|
- 不要包含非认证相关的 DTO(如 Beatmap 相关)
|
||||||
|
|
||||||
|
**Recommended Agent Profile**:
|
||||||
|
- **Category**: `quick`
|
||||||
|
- Reason: 纯数据结构定义
|
||||||
|
- **Skills**: None
|
||||||
|
|
||||||
|
**Parallelization**:
|
||||||
|
- **Can Run In Parallel**: YES
|
||||||
|
- **Parallel Group**: Wave 1 (with Tasks 1, 2, 4)
|
||||||
|
- **Blocks**: Tasks 5, 7
|
||||||
|
- **Blocked By**: None
|
||||||
|
|
||||||
|
**References**:
|
||||||
|
- `D:\Projects\IchniOnline\IchniOnline.Server\Models\Requests\ThirdPartyLoginRequest.cs`
|
||||||
|
- `D:\Projects\IchniOnline\IchniOnline.Server\Models\Requests\LoginRequest.cs`
|
||||||
|
- `D:\Projects\IchniOnline\IchniOnline.Server\Models\Requests\RegisterRequest.cs`
|
||||||
|
- `D:\Projects\IchniOnline\IchniOnline.Server\Models\Responses\AuthResponse.cs`
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] 所有 DTO 定义为 `[System.Serializable]`
|
||||||
|
- [ ] Unity 编译通过
|
||||||
|
- [ ] 字段名小写(JSON 反序列化兼容服务端 PascalCase → JsonUtility 需字段名匹配)
|
||||||
|
|
||||||
|
**QA Scenarios**:
|
||||||
|
```
|
||||||
|
Scenario: 编译验证
|
||||||
|
Tool: Unity Editor
|
||||||
|
Preconditions: 文件创建完成
|
||||||
|
Steps: Unity 编译自动触发
|
||||||
|
Expected Result: 无编译错误
|
||||||
|
Evidence: .omo/evidence/task-3-compile.png
|
||||||
|
```
|
||||||
|
|
||||||
|
**Commit**: YES (group with Tasks 1, 2, 4)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
- [x] 4. LoginCacheData.cs — 扩展 JWT 和服务器用户数据字段
|
||||||
|
|
||||||
|
**What to do**:
|
||||||
|
- 编辑 `Assets/Scripts/Online/Models/LoginCacheData.cs`
|
||||||
|
- 添加以下字段:
|
||||||
|
```csharp
|
||||||
|
public string jwtToken; // JWT Bearer token
|
||||||
|
public string userId; // 服务端返回的 UserId (Guid 字符串)
|
||||||
|
public string displayName; // 服务端返回的 DisplayName
|
||||||
|
public string avatarUrl; // 服务端返回的 AvatarUrl
|
||||||
|
public int permission; // 服务端返回的 Permission
|
||||||
|
public bool hasServerSession; // 标记是否已完成服务端认证
|
||||||
|
```
|
||||||
|
- 更新 `IsValid` 逻辑:`hasServerSession && !string.IsNullOrEmpty(jwtToken)`
|
||||||
|
- 保持向后兼容:构造旧字段保留,无 session 时 `hasServerSession=false`
|
||||||
|
- 添加 `UpdateFromServerResponse(LoginResponseDto response)` 方法
|
||||||
|
- 添加 `ClearServerSession()` 方法(仅清除 JWT 系列字段,保留 TapTap 原始信息)
|
||||||
|
|
||||||
|
**Must NOT do**:
|
||||||
|
- 不要删除已有字段 (openId/unionId/name/avatar/email/cacheTimestamp)
|
||||||
|
- 不要破坏 `LoginCacheEditor.cs` 中使用的公开接口
|
||||||
|
|
||||||
|
**Recommended Agent Profile**:
|
||||||
|
- **Category**: `quick`
|
||||||
|
- Reason: 小幅度字段扩展,结构简单
|
||||||
|
- **Skills**: None
|
||||||
|
|
||||||
|
**Parallelization**:
|
||||||
|
- **Can Run In Parallel**: YES
|
||||||
|
- **Parallel Group**: Wave 1 (with Tasks 1, 2, 3)
|
||||||
|
- **Blocks**: Task 6
|
||||||
|
- **Blocked By**: None
|
||||||
|
|
||||||
|
**References**:
|
||||||
|
- `Assets/Scripts/Online/Models/LoginCacheData.cs` — 当前文件
|
||||||
|
- `D:\Projects\IchniOnline\IchniOnline.Server\Models\Responses\AuthResponse.cs` — 服务端 LoginResponse/UserResponse
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] `LoginCacheData` 包含新字段 `jwtToken`, `userId`, `displayName`, `avatarUrl`, `permission`, `hasServerSession`
|
||||||
|
- [ ] 旧 ES3 缓存数据加载后不会报错(缺失字段为默认值,`hasServerSession=false`)
|
||||||
|
- [ ] `IsValid` 在 `hasServerSession` 为 true 时检查 `jwtToken` 非空
|
||||||
|
- [ ] Unity 编译通过
|
||||||
|
|
||||||
|
**QA Scenarios**:
|
||||||
|
```
|
||||||
|
Scenario: 向后兼容测试
|
||||||
|
Tool: Unity Editor + Bash (ES3 操作)
|
||||||
|
Preconditions: LoginCacheData 已修改,Unity 已编译
|
||||||
|
Steps:
|
||||||
|
1. 用 LoginCacheEditor.GenerateMockData 写入旧格式数据
|
||||||
|
2. 读取 LoginCacheManager.CachedData
|
||||||
|
3. 确认 hasServerSession=false,旧字段值正确
|
||||||
|
Expected Result: 旧缓存被正确加载,不丢失数据,不报错
|
||||||
|
Evidence: .omo/evidence/task-4-backward-compat.png
|
||||||
|
```
|
||||||
|
|
||||||
|
**Commit**: YES (group with Tasks 1, 2, 3)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
- [x] 5. ApiClient.cs — BestHTTP 封装单例
|
||||||
|
|
||||||
|
**What to do**:
|
||||||
|
- 新建文件: `Assets/Scripts/Online/Network/ApiClient.cs`
|
||||||
|
- 创建 `IchniOnlineApiClient` 类(非 MonoBehaviour 单例,或挂载到 DontDestroyOnLoad 对象)
|
||||||
|
- 核心功能:
|
||||||
|
1. **Base URL 配置**: `public string BaseUrl { get; set; }`,初始值 `http://localhost:5433`
|
||||||
|
2. **JWT 管理**: `public string JwtToken { get; set; }`,设置后自动在请求头注入
|
||||||
|
3. **GET 请求**: `Task<ApiResult<T>> GetAsync<T>(string endpoint)`
|
||||||
|
4. **POST 请求**: `Task<ApiResult<T>> PostAsync<T>(string endpoint, object body)`
|
||||||
|
5. **内部实现**: 使用 BestHTTP 的 `HTTPRequest` + `GetHTTPResponseAsync()`
|
||||||
|
- POST body 序列化: `request.RawData = Encoding.UTF8.GetBytes(JsonUtility.ToJson(body))`
|
||||||
|
- Header 设置: `request.SetHeader("Content-Type", "application/json")`
|
||||||
|
- JWT 注入: `request.SetHeader("Authorization", $"Bearer {JwtToken}")`
|
||||||
|
6. **响应解析**: 从 `resp.DataAsText` 反序列化为 `GlobalResponse<T>`,提取 Data
|
||||||
|
7. **错误处理**:
|
||||||
|
- HTTP 状态码错误 → ApiResult 含错误信息
|
||||||
|
- 解析失败 → ApiResult 含异常信息
|
||||||
|
- 网络超时 → ApiResult.Timeout
|
||||||
|
- 服务器返回失败码 → 按 Code 分类处理
|
||||||
|
|
||||||
|
**Error Handling Design**:
|
||||||
|
```csharp
|
||||||
|
public class ApiResult<T> {
|
||||||
|
public bool IsSuccess;
|
||||||
|
public T Data;
|
||||||
|
public int Code; // ResponseCode
|
||||||
|
public string Message; // 服务端返回的 Message
|
||||||
|
public string ErrorDetail; // 客户端错误详情
|
||||||
|
|
||||||
|
public static ApiResult<T> Ok(T data) => ...;
|
||||||
|
public static ApiResult<T> Fail(int code, string msg, string detail = null) => ...;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Must NOT do**:
|
||||||
|
- 不要阻塞 Unity 主线程(所有请求使用 async/await)
|
||||||
|
- 不要硬编码 URL(BaseUrl 必须可配置)
|
||||||
|
- 不要在 ApiClient 内处理业务逻辑(仅做 HTTP 通信)
|
||||||
|
|
||||||
|
**Recommended Agent Profile**:
|
||||||
|
- **Category**: `unspecified-high`
|
||||||
|
- Reason: 需要理解 BestHTTP API、异步模式、JSON 序列化,有较多细节
|
||||||
|
- **Skills**: None (BestHTTP API 文档已通过前期研究覆盖)
|
||||||
|
|
||||||
|
**Parallelization**:
|
||||||
|
- **Can Run In Parallel**: YES (with Task 6)
|
||||||
|
- **Parallel Group**: Wave 2 (with Task 6)
|
||||||
|
- **Blocks**: Task 7
|
||||||
|
- **Blocked By**: Tasks 1, 2, 3
|
||||||
|
|
||||||
|
**References**:
|
||||||
|
- `Packages/com.tivadar.best.http/Runtime/HTTP/HTTPRequestAsyncExtensions.cs` — BestHTTP async extension methods
|
||||||
|
- `Packages/com.tivadar.best.http/Runtime/HTTP/HTTPRequest.cs` — HTTPRequest class API
|
||||||
|
- `D:\Projects\IchniOnline\IchniOnline.Server\Models\Responses\GlobalResponse.cs` — 服务端响应格式
|
||||||
|
- `Assets/Scripts/Online/Network/Models/ApiResponse.cs` — 客户端响应模型(同 Wave 1 Task 2)
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] `IchniOnlineApiClient` 可配置 `BaseUrl`
|
||||||
|
- [ ] `GetAsync<T>` 发送 GET 请求并正确解析 `GlobalResponse<T>`
|
||||||
|
- [ ] `PostAsync<T>` 发送 POST 请求,body 序列化为 JSON
|
||||||
|
- [ ] JWT Token 自动注入到 Authorization Header
|
||||||
|
- [ ] 网络错误/服务端错误被正确封装为 `ApiResult<T>`
|
||||||
|
- [ ] Unity 编译通过
|
||||||
|
|
||||||
|
**QA Scenarios**:
|
||||||
|
```
|
||||||
|
Scenario: GET 请求 + 响应解析
|
||||||
|
Tool: Unity Editor + Bash (可启动测试后端或 mock)
|
||||||
|
Preconditions: IchniOnline 后端在 localhost:5433 运行(或 mock 端点)
|
||||||
|
Steps:
|
||||||
|
1. 在 Unity Start() 中调用 ApiClient.GetAsync<object>("/api/test/health")
|
||||||
|
2. 检查 Console 输出请求/响应日志
|
||||||
|
Expected Result: 请求发送成功,响应被正确解析
|
||||||
|
Evidence: .omo/evidence/task-5-get-request.png
|
||||||
|
|
||||||
|
Scenario: JWT 注入验证
|
||||||
|
Tool: Unity Editor
|
||||||
|
Preconditions: ApiClient.JwtToken 设置为 "test-token"
|
||||||
|
Steps:
|
||||||
|
1. 发起 PostAsync 请求
|
||||||
|
2. 检查请求 Header 包含 "Authorization: Bearer test-token"
|
||||||
|
Expected Result: Authorization Header 正确注入
|
||||||
|
Evidence: .omo/evidence/task-5-jwt-header.png
|
||||||
|
```
|
||||||
|
|
||||||
|
**Commit**: YES (group with Task 6)
|
||||||
|
- Message: `feat(online): implement API client and extend login cache`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
- [x] 6. LoginCacheManager.cs — 扩展 JWT 存取方法
|
||||||
|
|
||||||
|
**What to do**:
|
||||||
|
- 编辑 `Assets/Scripts/Online/Logic/LoginCacheManager.cs`
|
||||||
|
- 添加新方法:
|
||||||
|
```csharp
|
||||||
|
// 保存完整认证会话(JWT + 用户数据)
|
||||||
|
public static void SaveAuthSession(string jwtToken, LoginResponseDto response)
|
||||||
|
|
||||||
|
// 清除会话(保留 TapTap 原始数据,清除 JWT/服务端数据)
|
||||||
|
public static void ClearSession()
|
||||||
|
|
||||||
|
// 获取缓存的 JWT Token
|
||||||
|
public static string CachedJwtToken { get; }
|
||||||
|
|
||||||
|
// 检查是否有有效的服务端会话
|
||||||
|
public static bool HasValidSession { get; }
|
||||||
|
```
|
||||||
|
- ES3 key 保持不变: `Ichni_LoginCache`
|
||||||
|
- `HasCachedLogin` → 改为检查 `HasValidSession`
|
||||||
|
- `CachedData` → 保持返回完整数据
|
||||||
|
- `SaveFromTapTapAccount` → 保持原有行为(只存 TapTap 数据,不清除已有 JWT)
|
||||||
|
|
||||||
|
**Must NOT do**:
|
||||||
|
- 不要修改 ES3 key 名称
|
||||||
|
- 不要改变已有方法的签名
|
||||||
|
|
||||||
|
**Recommended Agent Profile**:
|
||||||
|
- **Category**: `quick`
|
||||||
|
- Reason: 简单的方法扩展
|
||||||
|
- **Skills**: None
|
||||||
|
|
||||||
|
**Parallelization**:
|
||||||
|
- **Can Run In Parallel**: YES (with Task 5)
|
||||||
|
- **Parallel Group**: Wave 2 (with Task 5)
|
||||||
|
- **Blocks**: Task 7
|
||||||
|
- **Blocked By**: Tasks 1, 4
|
||||||
|
|
||||||
|
**References**:
|
||||||
|
- `Assets/Scripts/Online/Logic/LoginCacheManager.cs` — 当前文件
|
||||||
|
- `Assets/Scripts/Online/Models/LoginCacheData.cs` — 扩展后的数据模型
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] `SaveAuthSession(jwt, response)` 正确写入 ES3
|
||||||
|
- [ ] `CachedJwtToken` 从 ES3 读取正确
|
||||||
|
- [ ] `HasValidSession` 在 jwt 为空或无 session 时返回 false
|
||||||
|
- [ ] 编辑器中 `Ichni/Login Cache` 菜单仍正常工作
|
||||||
|
- [ ] Unity 编译通过
|
||||||
|
|
||||||
|
**QA Scenarios**:
|
||||||
|
```
|
||||||
|
Scenario: 保存/读取 JWT 会话
|
||||||
|
Tool: Unity Editor
|
||||||
|
Preconditions: 已有 LoginCacheData 模型扩展
|
||||||
|
Steps:
|
||||||
|
1. LoginCacheManager.SaveAuthSession("test-jwt", mockLoginResponse)
|
||||||
|
2. 读取 LoginCacheManager.CachedJwtToken
|
||||||
|
3. 读取 LoginCacheManager.HasValidSession
|
||||||
|
Expected Result: jwt="test-jwt", HasValidSession=true
|
||||||
|
Evidence: .omo/evidence/task-6-save-jwt.png
|
||||||
|
|
||||||
|
Scenario: 清除会话
|
||||||
|
Steps:
|
||||||
|
1. LoginCacheManager.ClearSession()
|
||||||
|
2. 检查 HasValidSession
|
||||||
|
Expected Result: HasValidSession=false, TapTap 原始数据保留
|
||||||
|
Evidence: .omo/evidence/task-6-clear.png
|
||||||
|
```
|
||||||
|
|
||||||
|
**Commit**: YES (group with Task 5)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
- [x] 7. AuthService.cs — 认证编排服务
|
||||||
|
|
||||||
|
**What to do**:
|
||||||
|
- 新建文件: `Assets/Scripts/Online/Logic/AuthService.cs`
|
||||||
|
- 创建 `IchniOnlineAuthService` 类(非 MonoBehaviour 静态类 或 通过 ThirdPartyServiceManager 实例管理)
|
||||||
|
- 核心接口:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public static class IchniOnlineAuthService {
|
||||||
|
// 事件
|
||||||
|
public static event Action<LoginResponseDto> OnLoginSuccess;
|
||||||
|
public static event Action<string> OnLoginFailed; // error message
|
||||||
|
public static event Action OnLoginCanceled;
|
||||||
|
|
||||||
|
// 属性
|
||||||
|
public static bool IsLoggingIn { get; }
|
||||||
|
public static bool IsLoggedIn { get; } // HasValidSession
|
||||||
|
|
||||||
|
// TapTap 第三方登录流程
|
||||||
|
// 1. 调用 ThirdPartyServiceManager.StartTapTapLogin()
|
||||||
|
// 2. 在 OnLoginSuccess 回调中:
|
||||||
|
// a. 从 TapTapAccount 取出 accessToken
|
||||||
|
// b. 构造 ThirdPartyLoginRequestDto
|
||||||
|
// c. 调用 ApiClient.PostAsync<LoginResponseDto>("/api/auth/third-party/login", body)
|
||||||
|
// d. 成功 → LoginCacheManager.SaveAuthSession(jwt, response)
|
||||||
|
// e. 失败 → 抛 OnLoginFailed
|
||||||
|
// f. ThirdParty.Unbound → 抛 OnLoginFailed("TapTap account not bound")
|
||||||
|
public static void LoginWithTapTap();
|
||||||
|
|
||||||
|
// 密码登录流程
|
||||||
|
// 1. GET /api/auth/session-key → 得到 sessionKey
|
||||||
|
// 2. 密码 XOR 加密:
|
||||||
|
// byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
|
||||||
|
// byte[] sessionBytes = Encoding.UTF8.GetBytes(sessionKey);
|
||||||
|
// byte[] encrypted = new byte[passwordBytes.Length];
|
||||||
|
// for (int i = 0; i < passwordBytes.Length; i++)
|
||||||
|
// encrypted[i] = (byte)(passwordBytes[i] ^ sessionBytes[i % sessionBytes.Length]);
|
||||||
|
// string encryptedPassword = Convert.ToBase64String(encrypted);
|
||||||
|
// 3. POST /api/auth/login with { Username, EncryptedPassword, SessionKey }
|
||||||
|
// 4. 成功 → LoginCacheManager.SaveAuthSession(jwt, response)
|
||||||
|
public static async void LoginWithPassword(string username, string password);
|
||||||
|
|
||||||
|
// 注册流程
|
||||||
|
// POST /api/auth/register with { Username, Password, DisplayName }
|
||||||
|
// 注意: 注册后不自动返回 JWT,需要用户手动登录
|
||||||
|
public static async void Register(string username, string password, string displayName);
|
||||||
|
|
||||||
|
// 登出
|
||||||
|
public static void Logout();
|
||||||
|
|
||||||
|
// 密码 XOR 加密工具方法(可复用)
|
||||||
|
public static string EncryptPassword(string password, string sessionKey);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Must NOT do**:
|
||||||
|
- 不要直接调用 TapTap SDK 的 LoginWithScopes(由 ThirdPartyServiceManager 封装)
|
||||||
|
- 不要在 AuthService 中管理 UI 状态(只触发事件,由 LoginPage 处理 UI)
|
||||||
|
- 不要硬编码 API 路径(用字符串常量集中管理)
|
||||||
|
|
||||||
|
**Recommended Agent Profile**:
|
||||||
|
- **Category**: `unspecified-high`
|
||||||
|
- Reason: 涉及多步异步流程编排、事件管理、加密算法实现
|
||||||
|
- **Skills**: None
|
||||||
|
|
||||||
|
**Parallelization**:
|
||||||
|
- **Can Run In Parallel**: NO
|
||||||
|
- **Parallel Group**: Wave 3 (sequential)
|
||||||
|
- **Blocks**: Tasks 8, 9, 10
|
||||||
|
- **Blocked By**: Tasks 5, 6
|
||||||
|
|
||||||
|
**References**:
|
||||||
|
- `Assets/Scripts/Online/Logic/ThirdPartyServiceManager.cs` — TapTap SDK 调用封装
|
||||||
|
- `Assets/Scripts/Online/Network/ApiClient.cs` — HTTP 通信(Task 5)
|
||||||
|
- `Assets/Scripts/Online/Logic/LoginCacheManager.cs` — 缓存管理(Task 6)
|
||||||
|
- `D:\Projects\IchniOnline\IchniOnline.Server\Service\UserService.cs:213-225` — 服务端 XOR 解密算法(客户端需反转实现加密)
|
||||||
|
- `D:\Projects\IchniOnline\IchniOnline.Server\Controller\AuthController.cs` — 服务端 API 端点定义
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] `LoginWithTapTap()` 完整流程: TapTap SDK → API call → JWT → 事件
|
||||||
|
- [ ] `LoginWithPassword()` 完整流程: session key → XOR 加密 → API call → JWT → 事件
|
||||||
|
- [ ] `Register()` 调用 POST /api/auth/register
|
||||||
|
- [ ] `Logout()` 清除 JWT + TapTap 登出
|
||||||
|
- [ ] `EncryptPassword()` 与服务端 `DecryptPassword` 互为逆运算
|
||||||
|
- [ ] 所有事件正确触发(OnLoginSuccess/OnLoginFailed/OnLoginCanceled)
|
||||||
|
- [ ] Unity 编译通过
|
||||||
|
|
||||||
|
**QA Scenarios**:
|
||||||
|
```
|
||||||
|
Scenario: 密码 XOR 加密验证
|
||||||
|
Tool: C# 脚本验证
|
||||||
|
Preconditions: AuthService.EncryptPassword 已实现
|
||||||
|
Steps:
|
||||||
|
1. 设 password="test123", sessionKey="base64encodedkey=="
|
||||||
|
2. 调用 EncryptPassword 得到 encrypted
|
||||||
|
3. 用服务端 DecryptPassword 逻辑解密: 取 encrypted Base64 → XOR with sessionKey bytes → 得到明文
|
||||||
|
Expected Result: 解密后明文等于原始 password
|
||||||
|
Evidence: .omo/evidence/task-7-xor-verify.png
|
||||||
|
|
||||||
|
Scenario: TapTap 登录流程(模拟)
|
||||||
|
Tool: Unity Editor Play Mode
|
||||||
|
Preconditions: ThirdPartyServiceManager 已初始化
|
||||||
|
Steps:
|
||||||
|
1. AuthService.LoginWithTapTap()
|
||||||
|
2. Console 观察: TapTap SDK 登录 → API POST 请求 → JWT 缓存
|
||||||
|
Expected Result: 流程完整无异常
|
||||||
|
Evidence: .omo/evidence/task-7-taaptap-flow.png
|
||||||
|
```
|
||||||
|
|
||||||
|
**Commit**: YES
|
||||||
|
- Message: `feat(online): implement auth service with TapTap/password/register flows`
|
||||||
|
- Files: `Assets/Scripts/Online/Logic/AuthService.cs`
|
||||||
|
- Pre-commit: Unity 编译检查
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
- [x] 8. ThirdPartyServiceManager.cs — 集成 AuthService
|
||||||
|
|
||||||
|
**What to do**:
|
||||||
|
- 编辑 `Assets/Scripts/Online/Logic/ThirdPartyServiceManager.cs`
|
||||||
|
- 在 `StartTapTapLogin()` 的 `LoginWithScopes` 成功后,**不再直接调用** `LoginCacheManager.SaveFromTapTapAccount(account)`(该操作移至 AuthService 流程中)
|
||||||
|
- 添加事件 `OnTapTapAccessTokenReceived(AccessToken token)` 或修改流程,使 AuthService 能拿到 accessToken
|
||||||
|
- 可选方案 A: ThirdPartyServiceManager 保留纯 SDK 封装,AuthService 通过 `TapTapLogin.Instance.GetCurrentTapAccount()` 获取 account
|
||||||
|
- 可选方案 B: ThirdPartyServiceManager 的 `OnLoginSuccess` 事件中附带 accessToken
|
||||||
|
- **推荐方案 B**: 扩展 `OnLoginSuccess` 事件参数或添加新事件
|
||||||
|
```csharp
|
||||||
|
// 新增事件: 携带 accessToken(供 AuthService 使用)
|
||||||
|
public event Action<TapTapAccount, AccessToken> OnLoginWithToken;
|
||||||
|
```
|
||||||
|
- `StartTapTapLogin()` 保持不变(依然触发 OnLoginSuccess/OnLoginCanceled/OnLoginFailed)
|
||||||
|
|
||||||
|
**Must NOT do**:
|
||||||
|
- 不要移除已有的事件(OnLoginSuccess/OnLoginCanceled/OnLoginFailed)
|
||||||
|
- 不要改变 TapTap SDK 初始化逻辑
|
||||||
|
|
||||||
|
**Recommended Agent Profile**:
|
||||||
|
- **Category**: `quick`
|
||||||
|
- Reason: 小幅接口扩展
|
||||||
|
- **Skills**: None
|
||||||
|
|
||||||
|
**Parallelization**:
|
||||||
|
- **Can Run In Parallel**: YES (with Tasks 9, 10)
|
||||||
|
- **Parallel Group**: Wave 4 (with Tasks 9, 10)
|
||||||
|
- **Blocks**: None
|
||||||
|
- **Blocked By**: Task 7
|
||||||
|
|
||||||
|
**References**:
|
||||||
|
- `Assets/Scripts/Online/Logic/ThirdPartyServiceManager.cs` — 当前文件
|
||||||
|
- `D:\Projects\Open\TapSDKLogin-Unity\Runtime\Public\TapTapAccount.cs` — TapTapAccount 结构(含 accessToken 属性)
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] `OnLoginWithToken` 事件在 TapTap 登录成功后触发
|
||||||
|
- [ ] 事件参数包含完整的 `TapTapAccount` 和 `AccessToken`
|
||||||
|
- [ ] Unity 编译通过
|
||||||
|
|
||||||
|
**QA Scenarios**:
|
||||||
|
```
|
||||||
|
Scenario: 事件触发测试
|
||||||
|
Tool: Unity Editor Play Mode
|
||||||
|
Preconditions: ThirdPartyServiceManager 已初始化
|
||||||
|
Steps:
|
||||||
|
1. 订阅 ThirdPartyServiceManager.Instance.OnLoginWithToken
|
||||||
|
2. 调用 StartTapTapLogin()
|
||||||
|
3. TapTap 登录成功后检查事件是否触发
|
||||||
|
Expected Result: 事件触发,accessToken.kid/macKey/macAlgorithm 非空
|
||||||
|
Evidence: .omo/evidence/task-8-event.png
|
||||||
|
```
|
||||||
|
|
||||||
|
**Commit**: YES (group with Tasks 9, 10)
|
||||||
|
- Message: `feat(ui): integrate auth service into login UI`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
- [x] 9. LoginPage.cs — 使用新 AuthService 驱动流程
|
||||||
|
|
||||||
|
**What to do**:
|
||||||
|
- 编辑 `Assets/Scripts/UI/LoginPage/LoginPage.cs`
|
||||||
|
- 修改 `OnTapTapClicked()`:
|
||||||
|
- 不再直接调用 `ThirdPartyServiceManager.Instance.StartTapTapLogin()`
|
||||||
|
- 改为调用 `IchniOnlineAuthService.LoginWithTapTap()`
|
||||||
|
- 修改 `OnTapTapLoginSuccess(TapTapAccount account)`:
|
||||||
|
- 不再立即 FadeOut(改为等待 AuthService 的服务端验证完成)
|
||||||
|
- 改为 `IchniOnlineAuthService.OnLoginSuccess += OnApiLoginSuccess`
|
||||||
|
- 添加新回调 `OnApiLoginSuccess(LoginResponseDto response)`:
|
||||||
|
- 服务端验证成功后 FadeOut + 恢复 StartPage
|
||||||
|
- 添加 UI 加载状态:
|
||||||
|
- 显示加载指示器(或按钮禁用+文字变化)在等待服务端响应期间
|
||||||
|
- 事件订阅:
|
||||||
|
- 订阅 `AuthService.OnLoginSuccess` / `OnLoginFailed` / `OnLoginCanceled`
|
||||||
|
- 替代原有的 ThirdPartyServiceManager 事件(或共存)
|
||||||
|
- 账户密码登录 UI:
|
||||||
|
- 如果 LoginPage 上已有用户名/密码输入框 → 绑定到 `IchniOnlineAuthService.LoginWithPassword()`
|
||||||
|
- 如果没有 → 增加简单的用户名/密码输入框 + 登录按钮
|
||||||
|
|
||||||
|
**Must NOT do**:
|
||||||
|
- 不要删除 closeButton 和原有的 UI 结构
|
||||||
|
- 不要修改 UIPageBase 基类
|
||||||
|
|
||||||
|
**Recommended Agent Profile**:
|
||||||
|
- **Category**: `visual-engineering`
|
||||||
|
- Reason: 涉及 UI 逻辑更新和用户交互流程
|
||||||
|
- **Skills**: None
|
||||||
|
|
||||||
|
**Parallelization**:
|
||||||
|
- **Can Run In Parallel**: YES (with Tasks 8, 10)
|
||||||
|
- **Parallel Group**: Wave 4 (with Tasks 8, 10)
|
||||||
|
- **Blocks**: None
|
||||||
|
- **Blocked By**: Task 7
|
||||||
|
|
||||||
|
**References**:
|
||||||
|
- `Assets/Scripts/UI/LoginPage/LoginPage.cs` — 当前文件
|
||||||
|
- `Assets/Scripts/Online/Logic/AuthService.cs` — 认证服务(Task 7)
|
||||||
|
- `Assets/Scripts/UI/StartPage/StartUIPage.cs` — StartPage 交互恢复
|
||||||
|
- `Assets/Scripts/UI/StartPage/StartUIPage.cs:TouchToStart()` — 缓存检测入口
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] TapTap 按钮触发 `AuthService.LoginWithTapTap()` 而非直接调用 ThirdPartyServiceManager
|
||||||
|
- [ ] 登录请求加载状态有 UI 反馈
|
||||||
|
- [ ] 服务端返回成功后 FadeOut + 恢复 StartPage
|
||||||
|
- [ ] 失败时恢复按钮交互
|
||||||
|
- [ ] Unity 编译通过
|
||||||
|
|
||||||
|
**QA Scenarios**:
|
||||||
|
```
|
||||||
|
Scenario: TapTap 登录 UI 流程
|
||||||
|
Tool: Unity Editor Play Mode
|
||||||
|
Preconditions: LoginPage 在 MenuScene 中打开
|
||||||
|
Steps:
|
||||||
|
1. 点击 TapTap 按钮
|
||||||
|
2. 观察按钮变为非交互状态
|
||||||
|
3. TapTap SDK 登录窗口出现
|
||||||
|
4. 完成 TapTap 登录 → 等待服务端验证
|
||||||
|
5. 成功后 LoginPage 淡出 → 恢复 StartPage
|
||||||
|
Expected Result: UI 流程完整,无中断
|
||||||
|
Evidence: .omo/evidence/task-9-ui-flow.png
|
||||||
|
```
|
||||||
|
|
||||||
|
**Commit**: YES (group with Tasks 8, 10)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
- [x] 10. StartUIPage.cs — 校验会话有效性
|
||||||
|
|
||||||
|
**What to do**:
|
||||||
|
- 编辑 `Assets/Scripts/UI/StartPage/StartUIPage.cs`
|
||||||
|
- `TouchToStart()` 中改用 `LoginCacheManager.HasValidSession` 替代 `LoginCacheManager.HasCachedLogin`
|
||||||
|
- 添加可选的 Token 过期检测:
|
||||||
|
- JWT 本身包含过期时间(可解析 payload 中的 exp 字段)
|
||||||
|
- 如果 JWT 已过期 → 清除 session → 显示 LoginPage
|
||||||
|
- 简单方案: 暂不做 JWT 解码解析,只检查 `HasValidSession`
|
||||||
|
- 如有 `RestoreInteraction()` 方法保持现有逻辑
|
||||||
|
|
||||||
|
**Must NOT do**:
|
||||||
|
- 不要修改不相关的 StartUIPage 逻辑
|
||||||
|
- 不要引入 JWT 解码库(暂不解码 JWT payload)
|
||||||
|
|
||||||
|
**Recommended Agent Profile**:
|
||||||
|
- **Category**: `visual-engineering`
|
||||||
|
- **Skills**: None
|
||||||
|
|
||||||
|
**Parallelization**:
|
||||||
|
- **Can Run In Parallel**: YES (with Tasks 8, 9)
|
||||||
|
- **Parallel Group**: Wave 4 (with Tasks 8, 9)
|
||||||
|
- **Blocks**: None
|
||||||
|
- **Blocked By**: Task 7
|
||||||
|
|
||||||
|
**References**:
|
||||||
|
- `Assets/Scripts/UI/StartPage/StartUIPage.cs` — 当前文件
|
||||||
|
- `Assets/Scripts/Online/Logic/LoginCacheManager.cs` — 扩展后的缓存管理器(Task 6)
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] `TouchToStart()` 使用 `LoginCacheManager.HasValidSession` 判断
|
||||||
|
- [ ] 有有效 session → 直接进 ChapterSelection
|
||||||
|
- [ ] 无有效 session → 显示 LoginPage
|
||||||
|
- [ ] Unity 编译通过
|
||||||
|
|
||||||
|
**QA Scenarios**:
|
||||||
|
```
|
||||||
|
Scenario: 有 JWT session 时跳过登录
|
||||||
|
Tool: Unity Editor Play Mode
|
||||||
|
Preconditions: ES3 中存在有效 JWT 缓存
|
||||||
|
Steps:
|
||||||
|
1. 进入 MenuScene
|
||||||
|
2. 点击 TouchToStart
|
||||||
|
Expected Result: 直接进入 ChapterSelection,不显示 LoginPage
|
||||||
|
Evidence: .omo/evidence/task-10-skip-login.png
|
||||||
|
|
||||||
|
Scenario: 无 JWT session 时显示登录
|
||||||
|
Preconditions: 清除 ES3 缓存
|
||||||
|
Steps:
|
||||||
|
1. 进入 MenuScene
|
||||||
|
2. 点击 TouchToStart
|
||||||
|
Expected Result: LoginPage 显示
|
||||||
|
Evidence: .omo/evidence/task-10-show-login.png
|
||||||
|
```
|
||||||
|
|
||||||
|
**Commit**: YES (group with Tasks 8, 9)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Final Verification Wave
|
||||||
|
|
||||||
|
- [x] F1. **Plan Compliance Audit** — `oracle`
|
||||||
|
Read the plan end-to-end. For each "Must Have": verify implementation exists (read file, check compilation). For each "Must NOT Have": search codebase for forbidden patterns — reject with file:line if found. Check evidence files exist in .omo/evidence/. Compare deliverables against plan.
|
||||||
|
Output: `Must Have [N/N] | Must NOT Have [N/N] | Tasks [N/N] | VERDICT: APPROVE/REJECT`
|
||||||
|
|
||||||
|
- [x] F2. **Code Quality Review** — `unspecified-high`
|
||||||
|
Check compilation status. Review changed files: proper async patterns (no sync-over-async), no `try/catch` swallowing, proper error handling, no magic strings (use constants), correct `[Serializable]` attributes on DTOs.
|
||||||
|
Output: `Build [PASS/FAIL] | Code Quality [N clean/N issues] | VERDICT`
|
||||||
|
|
||||||
|
- [x] F3. **Real Manual QA** — `unspecified-high`
|
||||||
|
Start from clean scene state. Execute QA scenarios from EVERY task — follow exact steps, capture evidence. Test integration flow: TapTap login → API call → JWT cache → restart → skip login. Test edge cases: network error, invalid credentials, ThirdParty.Unbound.
|
||||||
|
Output: `Scenarios [N/N pass] | Integration [N/N] | Edge Cases [N tested] | VERDICT`
|
||||||
|
|
||||||
|
- [x] F4. **Scope Fidelity Check** — `deep`
|
||||||
|
For each task: read "What to do", read actual diff (git log/diff). Verify 1:1 — everything in spec was built (no missing), nothing beyond spec was built (no creep). Check "Must NOT do" compliance. Detect cross-task contamination.
|
||||||
|
Output: `Tasks [N/N compliant] | Contamination [CLEAN/N issues] | Unaccounted [CLEAN/N files] | VERDICT`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Commit Strategy
|
||||||
|
|
||||||
|
- **C1** (Task 1-4): `feat(online): add network models and asmdef references`
|
||||||
|
- **C2** (Task 5-6): `feat(online): implement API client and extend login cache`
|
||||||
|
- **C3** (Task 7): `feat(online): implement auth service with TapTap/password/register flows`
|
||||||
|
- **C4** (Task 8-10): `feat(ui): integrate auth service into login UI`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Success Criteria
|
||||||
|
|
||||||
|
### Verification Commands
|
||||||
|
```bash
|
||||||
|
# In Unity Editor:
|
||||||
|
# 1. Open MenuScene
|
||||||
|
# 2. Enter Play Mode
|
||||||
|
# 3. Click TapTap Login button → should call POST /api/auth/third-party/login
|
||||||
|
# 4. Check Console for network request/response logs
|
||||||
|
# 5. Exit Play Mode → check ES3 cache contains JWT data
|
||||||
|
```
|
||||||
|
|
||||||
|
### Final Checklist
|
||||||
|
- [ ] No compilation errors in IchniOnline.asmdef or dependent assemblies
|
||||||
|
- [ ] TapTap login → server API call → JWT → ES3 cache
|
||||||
|
- [ ] Password login (if server running) → JWT → ES3 cache
|
||||||
|
- [ ] Register (if server running) → user created
|
||||||
|
- [ ] LoginPage responds to all auth states (loading/success/failure)
|
||||||
10
.omo/run-continuation/ses_12b41534affeQDNAisTmCG0XrZ.json
Normal file
10
.omo/run-continuation/ses_12b41534affeQDNAisTmCG0XrZ.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"sessionID": "ses_12b41534affeQDNAisTmCG0XrZ",
|
||||||
|
"updatedAt": "2026-06-17T08:45:47.266Z",
|
||||||
|
"sources": {
|
||||||
|
"background-task": {
|
||||||
|
"state": "idle",
|
||||||
|
"updatedAt": "2026-06-17T08:45:47.266Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
.omo/run-continuation/ses_12b516164ffekTIOv7bJsDWp4s.json
Normal file
10
.omo/run-continuation/ses_12b516164ffekTIOv7bJsDWp4s.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"sessionID": "ses_12b516164ffekTIOv7bJsDWp4s",
|
||||||
|
"updatedAt": "2026-06-17T08:25:45.254Z",
|
||||||
|
"sources": {
|
||||||
|
"background-task": {
|
||||||
|
"state": "idle",
|
||||||
|
"updatedAt": "2026-06-17T08:25:45.254Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
.omo/run-continuation/ses_135a9996effen0Yyr1bZVA5svu.json
Normal file
10
.omo/run-continuation/ses_135a9996effen0Yyr1bZVA5svu.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"sessionID": "ses_135a9996effen0Yyr1bZVA5svu",
|
||||||
|
"updatedAt": "2026-06-15T08:17:13.685Z",
|
||||||
|
"sources": {
|
||||||
|
"background-task": {
|
||||||
|
"state": "idle",
|
||||||
|
"updatedAt": "2026-06-15T08:17:13.685Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
.omo/run-continuation/ses_13621303dffegy9HFswySN0j47.json
Normal file
10
.omo/run-continuation/ses_13621303dffegy9HFswySN0j47.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"sessionID": "ses_13621303dffegy9HFswySN0j47",
|
||||||
|
"updatedAt": "2026-06-15T08:51:32.107Z",
|
||||||
|
"sources": {
|
||||||
|
"background-task": {
|
||||||
|
"state": "idle",
|
||||||
|
"updatedAt": "2026-06-15T08:51:32.107Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
5
.vscode/extensions.json
vendored
Normal file
5
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"visualstudiotoolsforunity.vstuc"
|
||||||
|
]
|
||||||
|
}
|
||||||
10
.vscode/launch.json
vendored
Normal file
10
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Attach to Unity",
|
||||||
|
"type": "vstuc",
|
||||||
|
"request": "attach"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
71
.vscode/settings.json
vendored
Normal file
71
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
{
|
||||||
|
"files.exclude": {
|
||||||
|
"**/.DS_Store": true,
|
||||||
|
"**/.git": true,
|
||||||
|
"**/.vs": true,
|
||||||
|
"**/.gitmodules": true,
|
||||||
|
"**/.vsconfig": true,
|
||||||
|
"**/*.booproj": true,
|
||||||
|
"**/*.pidb": true,
|
||||||
|
"**/*.suo": true,
|
||||||
|
"**/*.user": true,
|
||||||
|
"**/*.userprefs": true,
|
||||||
|
"**/*.unityproj": true,
|
||||||
|
"**/*.dll": true,
|
||||||
|
"**/*.exe": true,
|
||||||
|
"**/*.pdf": true,
|
||||||
|
"**/*.mid": true,
|
||||||
|
"**/*.midi": true,
|
||||||
|
"**/*.wav": true,
|
||||||
|
"**/*.gif": true,
|
||||||
|
"**/*.ico": true,
|
||||||
|
"**/*.jpg": true,
|
||||||
|
"**/*.jpeg": true,
|
||||||
|
"**/*.png": true,
|
||||||
|
"**/*.psd": true,
|
||||||
|
"**/*.tga": true,
|
||||||
|
"**/*.tif": true,
|
||||||
|
"**/*.tiff": true,
|
||||||
|
"**/*.3ds": true,
|
||||||
|
"**/*.3DS": true,
|
||||||
|
"**/*.fbx": true,
|
||||||
|
"**/*.FBX": true,
|
||||||
|
"**/*.lxo": true,
|
||||||
|
"**/*.LXO": true,
|
||||||
|
"**/*.ma": true,
|
||||||
|
"**/*.MA": true,
|
||||||
|
"**/*.obj": true,
|
||||||
|
"**/*.OBJ": true,
|
||||||
|
"**/*.asset": true,
|
||||||
|
"**/*.cubemap": true,
|
||||||
|
"**/*.flare": true,
|
||||||
|
"**/*.mat": true,
|
||||||
|
"**/*.meta": true,
|
||||||
|
"**/*.prefab": true,
|
||||||
|
"**/*.unity": true,
|
||||||
|
"build/": true,
|
||||||
|
"Build/": true,
|
||||||
|
"Library/": true,
|
||||||
|
"library/": true,
|
||||||
|
"obj/": true,
|
||||||
|
"Obj/": true,
|
||||||
|
"Logs/": true,
|
||||||
|
"logs/": true,
|
||||||
|
"ProjectSettings/": true,
|
||||||
|
"UserSettings/": true,
|
||||||
|
"temp/": true,
|
||||||
|
"Temp/": true
|
||||||
|
},
|
||||||
|
"files.associations": {
|
||||||
|
"*.asset": "yaml",
|
||||||
|
"*.meta": "yaml",
|
||||||
|
"*.prefab": "yaml",
|
||||||
|
"*.unity": "yaml",
|
||||||
|
},
|
||||||
|
"explorer.fileNesting.enabled": true,
|
||||||
|
"explorer.fileNesting.patterns": {
|
||||||
|
"*.sln": "*.csproj",
|
||||||
|
"*.slnx": "*.csproj"
|
||||||
|
},
|
||||||
|
"dotnet.defaultSolution": "ichni_Official.slnx"
|
||||||
|
}
|
||||||
@@ -213,7 +213,7 @@ Material:
|
|||||||
- _Dst: 10
|
- _Dst: 10
|
||||||
- _DstBlend: 0
|
- _DstBlend: 0
|
||||||
- _DstBlendAlpha: 0
|
- _DstBlendAlpha: 0
|
||||||
- _EdgeValue: 0.91334355
|
- _EdgeValue: 0.9979626
|
||||||
- _EnvironmentReflections: 1
|
- _EnvironmentReflections: 1
|
||||||
- _FNLfanxiangkaiguan: 0
|
- _FNLfanxiangkaiguan: 0
|
||||||
- _Face: 1
|
- _Face: 1
|
||||||
@@ -258,7 +258,7 @@ Material:
|
|||||||
- _Mask_scale: 1
|
- _Mask_scale: 1
|
||||||
- _Metallic: 0
|
- _Metallic: 0
|
||||||
- _OcclusionStrength: 1
|
- _OcclusionStrength: 1
|
||||||
- _Opacity: 0.08665645
|
- _Opacity: 0.002037406
|
||||||
- _Parallax: 0.005
|
- _Parallax: 0.005
|
||||||
- _Pass: 0
|
- _Pass: 0
|
||||||
- _QueueOffset: 0
|
- _QueueOffset: 0
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: e00e6f90ab8233e46a41c5e33917c642
|
|
||||||
timeCreated: 1585839223
|
|
||||||
licenseType: Store
|
|
||||||
DefaultImporter:
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 2690f45490c175045bbdc63395bf6278
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: fbd1fd9b3a70fad429d1eaaa5799c2a5
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 3579d9cf4b75c564faa8fffc58a9f3f6
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 0023a0858ba124646a55dfcb7231ed46
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: d1c0b77896049554fa4b635531caf741
|
|
||||||
timeCreated: 1533059192
|
|
||||||
licenseType: Store
|
|
||||||
DefaultImporter:
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: c0a0a980c9ba86345bc15411db88d34f
|
|
||||||
timeCreated: 1585839223
|
|
||||||
licenseType: Store
|
|
||||||
DefaultImporter:
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 2edbf4a9b9544774bbef617e92429664
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 13ab599a7bda4e54fba3e92a13c9580a
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: f6f268949ccf3f34fa4d18e92501ed82
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 69bc3229216b1504ea3e28b5820bbb0d
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 4f665a06c5a2aa5499fa1c79ac058999
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 8a87ed432fe2d97498c0de5fae312e35
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 7c3bfbbeb9427b94099254e2e2768ad4
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: c5303861611f41c438a30be552da5de4
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: a9d68dd8913f05d4d9ce75e7b40c6044
|
|
||||||
timeCreated: 1575902011
|
|
||||||
licenseType: Store
|
|
||||||
DefaultImporter:
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 2243c8b4e1ab6914995699133f67ab5a
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 9a5e61a8b3421b944863d0946e32da0a
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 89f0b84148d149d4d96b838d7ef60e92
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 19939ee2cdb76e0489b1b8cd4bed7f3d
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 70777e8ce9f3c8d4a8182ca2f965cdb2
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: ba281a1a00c8ac54c914e0763299f637
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: e6fc8948257acee42b666d0bfe1d782c
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 4b5cb8698f2d9c14fadf8e2383441d37
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: b460b52e6c1feae45b70b7ddc2c45bd6
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 57fcea0ed8b5eb347923c4c21fa31b57
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 2e9da72e7e3196146bf7d27450013734
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 0904cdf24ddcd5042b024326476220d5
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 929783250050f8a448821b6ca1f2c578
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: fcc4d2eb0af82e546ae75506872cf092
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: cd0a0171c5157b748afe763b89f71211
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: f4990f6ace6142c4bbbf41cdd80b0bd3
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 1782b72cd0e99a54fac09382c482e3db
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 49d5bcbbd4cbd754b98cf3200197b0f1
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: eefe45a405f061045be947217e30ed10
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 2e995dfe11e22d34d92432383d15c067
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: ec984c51d4ae2504184eeb292734c672
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: e447b3d7d913d694ca35f74e30581840
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 6584a66582083a1459dcf5e4e87f6d62
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 0190b8bde50f12943926613d9a63c89a
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: ae2ce8ad295486349839288636aed1ed
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: d69745226619e3241a8e04ce86aee6a6
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 37e6a9374416bc946a55779c58d0d984
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
BIN
Assets/FR2_Cache.asset
LFS
BIN
Assets/FR2_Cache.asset
LFS
Binary file not shown.
Binary file not shown.
BIN
Assets/Fonts/zh-CN/Kongyuan Sans R SDF.asset
LFS
Normal file
BIN
Assets/Fonts/zh-CN/Kongyuan Sans R SDF.asset
LFS
Normal file
Binary file not shown.
8
Assets/Fonts/zh-CN/Kongyuan Sans R SDF.asset.meta
Normal file
8
Assets/Fonts/zh-CN/Kongyuan Sans R SDF.asset.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 89b797ea16d80784ab1c6fe6d4062928
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
BIN
Assets/Fonts/zh-CN/Kongyuan Sans R.otf
Normal file
BIN
Assets/Fonts/zh-CN/Kongyuan Sans R.otf
Normal file
Binary file not shown.
21
Assets/Fonts/zh-CN/Kongyuan Sans R.otf.meta
Normal file
21
Assets/Fonts/zh-CN/Kongyuan Sans R.otf.meta
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bdac2488c3a0d1d46aa612a2759a8919
|
||||||
|
TrueTypeFontImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 4
|
||||||
|
fontSize: 16
|
||||||
|
forceTextureCase: -2
|
||||||
|
characterSpacing: 0
|
||||||
|
characterPadding: 1
|
||||||
|
includeFontData: 1
|
||||||
|
fontNames:
|
||||||
|
- Kongyuan Sans R
|
||||||
|
fallbackFontReferences: []
|
||||||
|
customCharacters:
|
||||||
|
fontRenderingMode: 0
|
||||||
|
ascentCalculationMode: 1
|
||||||
|
useLegacyBoundsCalculation: 0
|
||||||
|
shouldRoundAdvanceValue: 1
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Binary file not shown.
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: e45363610a59a4543a9793b3bf2be4aa
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
27
Assets/Plugins/Android/AndroidManifest.xml
Normal file
27
Assets/Plugins/Android/AndroidManifest.xml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
<application>
|
||||||
|
<!--Used when Application Entry is set to Activity, otherwise remove this activity block-->
|
||||||
|
<activity android:name="com.unity3d.player.UnityPlayerActivity"
|
||||||
|
android:theme="@style/UnityThemeSelector">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
|
||||||
|
</activity>
|
||||||
|
<!--Used when Application Entry is set to GameActivity, otherwise remove this activity block-->
|
||||||
|
<activity android:name="com.unity3d.player.UnityPlayerGameActivity"
|
||||||
|
android:theme="@style/BaseUnityGameActivityTheme">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
<data android:scheme="ichni" android:host="mylink" />
|
||||||
|
</intent-filter>
|
||||||
|
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
|
||||||
|
<meta-data android:name="android.app.lib_name" android:value="game" />
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
</manifest>
|
||||||
7
Assets/Plugins/Android/AndroidManifest.xml.meta
Normal file
7
Assets/Plugins/Android/AndroidManifest.xml.meta
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0409f4966cdb7064eb86f782bd83211b
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
8
Assets/Plugins/Android/gradleTemplate.properties
Normal file
8
Assets/Plugins/Android/gradleTemplate.properties
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
org.gradle.jvmargs=-Xmx**JVM_HEAP_SIZE**M
|
||||||
|
org.gradle.parallel=true
|
||||||
|
unityStreamingAssets=**STREAMING_ASSETS**
|
||||||
|
# Android Resolver Properties Start
|
||||||
|
android.useAndroidX=true
|
||||||
|
android.enableJetifier=true
|
||||||
|
# Android Resolver Properties End
|
||||||
|
**ADDITIONAL_PROPERTIES**
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 641c955d37d2fac4f87e00ac5c9d9bd8
|
guid: 2f011dc9caa295e4ba52ccf2f88914df
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
||||||
62
Assets/Plugins/Android/mainTemplate.gradle
Normal file
62
Assets/Plugins/Android/mainTemplate.gradle
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
apply plugin: 'com.android.library'
|
||||||
|
apply from: '../shared/keepUnitySymbols.gradle'
|
||||||
|
apply from: '../shared/common.gradle'
|
||||||
|
**APPLY_PLUGINS**
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
// Android Resolver Dependencies Start
|
||||||
|
implementation 'com.taptap.sdk:tap-core-unity:4.5.4' // Packages/com.taptap.sdk.core/Mobile/Editor/NativeDependencies.xml:7
|
||||||
|
implementation 'com.taptap.sdk:tap-login-unity:4.5.4' // Packages/com.taptap.sdk.login/Mobile/Editor/NativeDependencies.xml:7
|
||||||
|
// Android Resolver Dependencies End
|
||||||
|
**DEPS**}
|
||||||
|
|
||||||
|
// Android Resolver Exclusions Start
|
||||||
|
android {
|
||||||
|
packagingOptions {
|
||||||
|
exclude ('/lib/armeabi/*' + '*')
|
||||||
|
exclude ('/lib/mips/*' + '*')
|
||||||
|
exclude ('/lib/mips64/*' + '*')
|
||||||
|
exclude ('/lib/x86/*' + '*')
|
||||||
|
exclude ('/lib/x86_64/*' + '*')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Android Resolver Exclusions End
|
||||||
|
android {
|
||||||
|
namespace "com.unity3d.player"
|
||||||
|
ndkPath "**NDKPATH**"
|
||||||
|
ndkVersion "**NDKVERSION**"
|
||||||
|
|
||||||
|
compileSdk **APIVERSION**
|
||||||
|
buildToolsVersion = "**BUILDTOOLS**"
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_17
|
||||||
|
targetCompatibility JavaVersion.VERSION_17
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdk **MINSDK**
|
||||||
|
targetSdk **TARGETSDK**
|
||||||
|
ndk {
|
||||||
|
abiFilters **ABIFILTERS**
|
||||||
|
debugSymbolLevel **DEBUGSYMBOLLEVEL**
|
||||||
|
}
|
||||||
|
versionCode **VERSIONCODE**
|
||||||
|
versionName '**VERSIONNAME**'
|
||||||
|
consumerProguardFiles 'proguard-unity.txt'**USER_PROGUARD**
|
||||||
|
**DEFAULT_CONFIG_SETUP**
|
||||||
|
}
|
||||||
|
|
||||||
|
lint {
|
||||||
|
abortOnError false
|
||||||
|
}
|
||||||
|
|
||||||
|
androidResources {
|
||||||
|
noCompress = **BUILTIN_NOCOMPRESS** + unityStreamingAssets.tokenize(', ')
|
||||||
|
ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:!CVS:!thumbs.db:!picasa.ini:!*~"
|
||||||
|
}**PACKAGING**
|
||||||
|
}
|
||||||
|
**IL_CPP_BUILD_SETUP**
|
||||||
|
**SOURCE_BUILD_SETUP**
|
||||||
|
**EXTERNAL_SOURCES**
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 9da5530d5ebfab24c8ecad68795e720f
|
guid: 655395b375b4d6a42912b6dcb6975d5a
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
||||||
30
Assets/Plugins/Android/settingsTemplate.gradle
Normal file
30
Assets/Plugins/Android/settingsTemplate.gradle
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
pluginManagement {
|
||||||
|
repositories {
|
||||||
|
**ARTIFACTORYREPOSITORY**
|
||||||
|
gradlePluginPortal()
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
include ':launcher', ':unityLibrary'
|
||||||
|
**INCLUDES**
|
||||||
|
|
||||||
|
dependencyResolutionManagement {
|
||||||
|
repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
|
||||||
|
repositories {
|
||||||
|
**ARTIFACTORYREPOSITORY**
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
// Android Resolver Repos Start
|
||||||
|
def unityProjectPath = $/file:///**DIR_UNITYPROJECT**/$.replace("\\", "/")
|
||||||
|
maven {
|
||||||
|
url "https://repo.maven.apache.org/maven2" // Packages/com.taptap.sdk.core/Mobile/Editor/NativeDependencies.xml:6, Packages/com.taptap.sdk.login/Mobile/Editor/NativeDependencies.xml:6
|
||||||
|
}
|
||||||
|
mavenLocal()
|
||||||
|
// Android Resolver Repos End
|
||||||
|
flatDir {
|
||||||
|
dirs "${project(':unityLibrary').projectDir}/libs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: aa102d640b98b5d4781710a3a3dd6983
|
guid: 118024034a116824492c045e4ed76102
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: de41a70ead12af544a4e99a925b269d2
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
Binary file not shown.
8
Assets/Plugins/NuGet.meta
Normal file
8
Assets/Plugins/NuGet.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e92c5c7d537e309448d2932c6047741e
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
260
Assets/Plugins/NuGet/.nuget-installed.json
Normal file
260
Assets/Plugins/NuGet/.nuget-installed.json
Normal file
@@ -0,0 +1,260 @@
|
|||||||
|
{
|
||||||
|
"packages": {
|
||||||
|
"com.IvanMurzak.McpPlugin": {
|
||||||
|
"version": "6.7.1",
|
||||||
|
"dlls": [
|
||||||
|
"McpPlugin.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"com.IvanMurzak.McpPlugin.Common": {
|
||||||
|
"version": "6.7.1",
|
||||||
|
"dlls": [
|
||||||
|
"McpPlugin.Common.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"com.IvanMurzak.ReflectorNet": {
|
||||||
|
"version": "5.3.1",
|
||||||
|
"dlls": [
|
||||||
|
"ReflectorNet.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Microsoft.AspNetCore.Connections.Abstractions": {
|
||||||
|
"version": "8.0.15",
|
||||||
|
"dlls": [
|
||||||
|
"Microsoft.AspNetCore.Connections.Abstractions.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Microsoft.AspNetCore.Http.Connections.Client": {
|
||||||
|
"version": "8.0.15",
|
||||||
|
"dlls": [
|
||||||
|
"Microsoft.AspNetCore.Http.Connections.Client.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Microsoft.AspNetCore.Http.Connections.Common": {
|
||||||
|
"version": "8.0.15",
|
||||||
|
"dlls": [
|
||||||
|
"Microsoft.AspNetCore.Http.Connections.Common.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Microsoft.AspNetCore.SignalR.Client": {
|
||||||
|
"version": "8.0.15",
|
||||||
|
"dlls": [
|
||||||
|
"Microsoft.AspNetCore.SignalR.Client.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Microsoft.AspNetCore.SignalR.Client.Core": {
|
||||||
|
"version": "8.0.15",
|
||||||
|
"dlls": [
|
||||||
|
"Microsoft.AspNetCore.SignalR.Client.Core.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Microsoft.AspNetCore.SignalR.Common": {
|
||||||
|
"version": "8.0.15",
|
||||||
|
"dlls": [
|
||||||
|
"Microsoft.AspNetCore.SignalR.Common.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Microsoft.AspNetCore.SignalR.Protocols.Json": {
|
||||||
|
"version": "8.0.15",
|
||||||
|
"dlls": [
|
||||||
|
"Microsoft.AspNetCore.SignalR.Protocols.Json.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Microsoft.Bcl.AsyncInterfaces": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"dlls": [
|
||||||
|
"Microsoft.Bcl.AsyncInterfaces.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Microsoft.Bcl.Memory": {
|
||||||
|
"version": "10.0.3",
|
||||||
|
"dlls": [
|
||||||
|
"Microsoft.Bcl.Memory.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Microsoft.Bcl.TimeProvider": {
|
||||||
|
"version": "8.0.1",
|
||||||
|
"dlls": [
|
||||||
|
"Microsoft.Bcl.TimeProvider.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Microsoft.CodeAnalysis.Analyzers": {
|
||||||
|
"version": "3.3.4",
|
||||||
|
"dlls": []
|
||||||
|
},
|
||||||
|
"Microsoft.CodeAnalysis.Common": {
|
||||||
|
"version": "4.8.0",
|
||||||
|
"dlls": [
|
||||||
|
"Microsoft.CodeAnalysis.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Microsoft.CodeAnalysis.CSharp": {
|
||||||
|
"version": "4.8.0",
|
||||||
|
"dlls": [
|
||||||
|
"Microsoft.CodeAnalysis.CSharp.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Caching.Abstractions": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"dlls": [
|
||||||
|
"Microsoft.Extensions.Caching.Abstractions.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"dlls": [
|
||||||
|
"Microsoft.Extensions.Configuration.Abstractions.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.DependencyInjection": {
|
||||||
|
"version": "8.0.1",
|
||||||
|
"dlls": [
|
||||||
|
"Microsoft.Extensions.DependencyInjection.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.DependencyInjection.Abstractions": {
|
||||||
|
"version": "8.0.2",
|
||||||
|
"dlls": [
|
||||||
|
"Microsoft.Extensions.DependencyInjection.Abstractions.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Diagnostics.Abstractions": {
|
||||||
|
"version": "8.0.1",
|
||||||
|
"dlls": [
|
||||||
|
"Microsoft.Extensions.Diagnostics.Abstractions.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Features": {
|
||||||
|
"version": "8.0.15",
|
||||||
|
"dlls": [
|
||||||
|
"Microsoft.Extensions.Features.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.FileProviders.Abstractions": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"dlls": [
|
||||||
|
"Microsoft.Extensions.FileProviders.Abstractions.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Hosting.Abstractions": {
|
||||||
|
"version": "8.0.1",
|
||||||
|
"dlls": [
|
||||||
|
"Microsoft.Extensions.Hosting.Abstractions.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Logging": {
|
||||||
|
"version": "8.0.1",
|
||||||
|
"dlls": [
|
||||||
|
"Microsoft.Extensions.Logging.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Logging.Abstractions": {
|
||||||
|
"version": "8.0.3",
|
||||||
|
"dlls": [
|
||||||
|
"Microsoft.Extensions.Logging.Abstractions.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Options": {
|
||||||
|
"version": "8.0.2",
|
||||||
|
"dlls": [
|
||||||
|
"Microsoft.Extensions.Options.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Primitives": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"dlls": [
|
||||||
|
"Microsoft.Extensions.Primitives.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"R3": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"dlls": [
|
||||||
|
"R3.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"System.Buffers": {
|
||||||
|
"version": "4.5.1",
|
||||||
|
"dlls": [
|
||||||
|
"System.Buffers.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"System.Collections.Immutable": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"dlls": [
|
||||||
|
"System.Collections.Immutable.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"System.ComponentModel.Annotations": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"dlls": [
|
||||||
|
"System.ComponentModel.Annotations.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"System.Diagnostics.DiagnosticSource": {
|
||||||
|
"version": "8.0.1",
|
||||||
|
"dlls": [
|
||||||
|
"System.Diagnostics.DiagnosticSource.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"System.IO.Pipelines": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"dlls": [
|
||||||
|
"System.IO.Pipelines.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"System.Memory": {
|
||||||
|
"version": "4.5.5",
|
||||||
|
"dlls": [
|
||||||
|
"System.Memory.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"System.Numerics.Vectors": {
|
||||||
|
"version": "4.4.0",
|
||||||
|
"dlls": [
|
||||||
|
"System.Numerics.Vectors.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"System.Reflection.Metadata": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"dlls": [
|
||||||
|
"System.Reflection.Metadata.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"System.Runtime.CompilerServices.Unsafe": {
|
||||||
|
"version": "6.1.2",
|
||||||
|
"dlls": [
|
||||||
|
"System.Runtime.CompilerServices.Unsafe.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"System.Text.Encoding.CodePages": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"dlls": [
|
||||||
|
"System.Text.Encoding.CodePages.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"System.Text.Encodings.Web": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"dlls": [
|
||||||
|
"System.Text.Encodings.Web.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"System.Text.Json": {
|
||||||
|
"version": "8.0.5",
|
||||||
|
"dlls": [
|
||||||
|
"System.Text.Json.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"System.Threading.Channels": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"dlls": [
|
||||||
|
"System.Threading.Channels.dll"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"System.Threading.Tasks.Extensions": {
|
||||||
|
"version": "4.5.4",
|
||||||
|
"dlls": [
|
||||||
|
"System.Threading.Tasks.Extensions.dll"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
Assets/Plugins/NuGet/McpPlugin.Common.dll
Normal file
BIN
Assets/Plugins/NuGet/McpPlugin.Common.dll
Normal file
Binary file not shown.
28
Assets/Plugins/NuGet/McpPlugin.Common.dll.meta
Normal file
28
Assets/Plugins/NuGet/McpPlugin.Common.dll.meta
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 05495eab6e4e41748bd25d84eda0f02c
|
||||||
|
PluginImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 3
|
||||||
|
iconMap: {}
|
||||||
|
executionOrder: {}
|
||||||
|
defineConstraints: []
|
||||||
|
isPreloaded: 0
|
||||||
|
isOverridable: 0
|
||||||
|
isExplicitlyReferenced: 0
|
||||||
|
validateReferences: 1
|
||||||
|
platformData:
|
||||||
|
Any:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
Exclude Editor: 0
|
||||||
|
Editor:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
DefaultValueInitialized: true
|
||||||
|
WindowsStoreApps:
|
||||||
|
enabled: 0
|
||||||
|
settings:
|
||||||
|
CPU: AnyCPU
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
BIN
Assets/Plugins/NuGet/McpPlugin.dll
Normal file
BIN
Assets/Plugins/NuGet/McpPlugin.dll
Normal file
Binary file not shown.
28
Assets/Plugins/NuGet/McpPlugin.dll.meta
Normal file
28
Assets/Plugins/NuGet/McpPlugin.dll.meta
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: de52387d4dc3d5546acdea549c9d90cc
|
||||||
|
PluginImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 3
|
||||||
|
iconMap: {}
|
||||||
|
executionOrder: {}
|
||||||
|
defineConstraints: []
|
||||||
|
isPreloaded: 0
|
||||||
|
isOverridable: 0
|
||||||
|
isExplicitlyReferenced: 0
|
||||||
|
validateReferences: 1
|
||||||
|
platformData:
|
||||||
|
Any:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
Exclude Editor: 0
|
||||||
|
Editor:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
DefaultValueInitialized: true
|
||||||
|
WindowsStoreApps:
|
||||||
|
enabled: 0
|
||||||
|
settings:
|
||||||
|
CPU: AnyCPU
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Binary file not shown.
@@ -0,0 +1,28 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b8cdd9785c3e3104da67efc5678b83d1
|
||||||
|
PluginImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 3
|
||||||
|
iconMap: {}
|
||||||
|
executionOrder: {}
|
||||||
|
defineConstraints: []
|
||||||
|
isPreloaded: 0
|
||||||
|
isOverridable: 0
|
||||||
|
isExplicitlyReferenced: 0
|
||||||
|
validateReferences: 1
|
||||||
|
platformData:
|
||||||
|
Any:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
Exclude Editor: 0
|
||||||
|
Editor:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
DefaultValueInitialized: true
|
||||||
|
WindowsStoreApps:
|
||||||
|
enabled: 0
|
||||||
|
settings:
|
||||||
|
CPU: AnyCPU
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Binary file not shown.
@@ -0,0 +1,28 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6c7b4bc6c2919ca4d8b92fa5c45acf4a
|
||||||
|
PluginImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 3
|
||||||
|
iconMap: {}
|
||||||
|
executionOrder: {}
|
||||||
|
defineConstraints: []
|
||||||
|
isPreloaded: 0
|
||||||
|
isOverridable: 0
|
||||||
|
isExplicitlyReferenced: 0
|
||||||
|
validateReferences: 1
|
||||||
|
platformData:
|
||||||
|
Any:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
Exclude Editor: 0
|
||||||
|
Editor:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
DefaultValueInitialized: true
|
||||||
|
WindowsStoreApps:
|
||||||
|
enabled: 0
|
||||||
|
settings:
|
||||||
|
CPU: AnyCPU
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Binary file not shown.
@@ -0,0 +1,28 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 93508e7e73d55b8498b4ac0f29ba1a8b
|
||||||
|
PluginImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 3
|
||||||
|
iconMap: {}
|
||||||
|
executionOrder: {}
|
||||||
|
defineConstraints: []
|
||||||
|
isPreloaded: 0
|
||||||
|
isOverridable: 0
|
||||||
|
isExplicitlyReferenced: 0
|
||||||
|
validateReferences: 1
|
||||||
|
platformData:
|
||||||
|
Any:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
Exclude Editor: 0
|
||||||
|
Editor:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
DefaultValueInitialized: true
|
||||||
|
WindowsStoreApps:
|
||||||
|
enabled: 0
|
||||||
|
settings:
|
||||||
|
CPU: AnyCPU
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Binary file not shown.
@@ -0,0 +1,28 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 43d7d0d1769e19442a70182cc80877dd
|
||||||
|
PluginImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 3
|
||||||
|
iconMap: {}
|
||||||
|
executionOrder: {}
|
||||||
|
defineConstraints: []
|
||||||
|
isPreloaded: 0
|
||||||
|
isOverridable: 0
|
||||||
|
isExplicitlyReferenced: 0
|
||||||
|
validateReferences: 1
|
||||||
|
platformData:
|
||||||
|
Any:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
Exclude Editor: 0
|
||||||
|
Editor:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
DefaultValueInitialized: true
|
||||||
|
WindowsStoreApps:
|
||||||
|
enabled: 0
|
||||||
|
settings:
|
||||||
|
CPU: AnyCPU
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
BIN
Assets/Plugins/NuGet/Microsoft.AspNetCore.SignalR.Client.dll
Normal file
BIN
Assets/Plugins/NuGet/Microsoft.AspNetCore.SignalR.Client.dll
Normal file
Binary file not shown.
@@ -0,0 +1,28 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 26492bc7d8a33e74eaaed6179e3d506c
|
||||||
|
PluginImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 3
|
||||||
|
iconMap: {}
|
||||||
|
executionOrder: {}
|
||||||
|
defineConstraints: []
|
||||||
|
isPreloaded: 0
|
||||||
|
isOverridable: 0
|
||||||
|
isExplicitlyReferenced: 0
|
||||||
|
validateReferences: 1
|
||||||
|
platformData:
|
||||||
|
Any:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
Exclude Editor: 0
|
||||||
|
Editor:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
DefaultValueInitialized: true
|
||||||
|
WindowsStoreApps:
|
||||||
|
enabled: 0
|
||||||
|
settings:
|
||||||
|
CPU: AnyCPU
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
BIN
Assets/Plugins/NuGet/Microsoft.AspNetCore.SignalR.Common.dll
Normal file
BIN
Assets/Plugins/NuGet/Microsoft.AspNetCore.SignalR.Common.dll
Normal file
Binary file not shown.
@@ -0,0 +1,28 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 64728dbc622dd1f4e9acf1a99ad48924
|
||||||
|
PluginImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 3
|
||||||
|
iconMap: {}
|
||||||
|
executionOrder: {}
|
||||||
|
defineConstraints: []
|
||||||
|
isPreloaded: 0
|
||||||
|
isOverridable: 0
|
||||||
|
isExplicitlyReferenced: 0
|
||||||
|
validateReferences: 1
|
||||||
|
platformData:
|
||||||
|
Any:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
Exclude Editor: 0
|
||||||
|
Editor:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
DefaultValueInitialized: true
|
||||||
|
WindowsStoreApps:
|
||||||
|
enabled: 0
|
||||||
|
settings:
|
||||||
|
CPU: AnyCPU
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Binary file not shown.
@@ -0,0 +1,28 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 07a3015e7f854514e91ea819adfa59bd
|
||||||
|
PluginImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 3
|
||||||
|
iconMap: {}
|
||||||
|
executionOrder: {}
|
||||||
|
defineConstraints: []
|
||||||
|
isPreloaded: 0
|
||||||
|
isOverridable: 0
|
||||||
|
isExplicitlyReferenced: 0
|
||||||
|
validateReferences: 1
|
||||||
|
platformData:
|
||||||
|
Any:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
Exclude Editor: 0
|
||||||
|
Editor:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
DefaultValueInitialized: true
|
||||||
|
WindowsStoreApps:
|
||||||
|
enabled: 0
|
||||||
|
settings:
|
||||||
|
CPU: AnyCPU
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
BIN
Assets/Plugins/NuGet/Microsoft.Bcl.AsyncInterfaces.dll
Normal file
BIN
Assets/Plugins/NuGet/Microsoft.Bcl.AsyncInterfaces.dll
Normal file
Binary file not shown.
28
Assets/Plugins/NuGet/Microsoft.Bcl.AsyncInterfaces.dll.meta
Normal file
28
Assets/Plugins/NuGet/Microsoft.Bcl.AsyncInterfaces.dll.meta
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0ca5be7ee04e73745b435d56d9a3059f
|
||||||
|
PluginImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 3
|
||||||
|
iconMap: {}
|
||||||
|
executionOrder: {}
|
||||||
|
defineConstraints: []
|
||||||
|
isPreloaded: 0
|
||||||
|
isOverridable: 0
|
||||||
|
isExplicitlyReferenced: 0
|
||||||
|
validateReferences: 1
|
||||||
|
platformData:
|
||||||
|
Any:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
Exclude Editor: 0
|
||||||
|
Editor:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
DefaultValueInitialized: true
|
||||||
|
WindowsStoreApps:
|
||||||
|
enabled: 0
|
||||||
|
settings:
|
||||||
|
CPU: AnyCPU
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
BIN
Assets/Plugins/NuGet/Microsoft.Bcl.Memory.dll
Normal file
BIN
Assets/Plugins/NuGet/Microsoft.Bcl.Memory.dll
Normal file
Binary file not shown.
27
Assets/Plugins/NuGet/Microsoft.Bcl.Memory.dll.meta
Normal file
27
Assets/Plugins/NuGet/Microsoft.Bcl.Memory.dll.meta
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: dacefc9dad1bbc346af79a6cb0e5e5c6
|
||||||
|
PluginImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 3
|
||||||
|
iconMap: {}
|
||||||
|
executionOrder: {}
|
||||||
|
defineConstraints: []
|
||||||
|
isPreloaded: 0
|
||||||
|
isOverridable: 0
|
||||||
|
isExplicitlyReferenced: 0
|
||||||
|
validateReferences: 1
|
||||||
|
platformData:
|
||||||
|
Any:
|
||||||
|
enabled: 0
|
||||||
|
settings: {}
|
||||||
|
Editor:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
DefaultValueInitialized: true
|
||||||
|
WindowsStoreApps:
|
||||||
|
enabled: 0
|
||||||
|
settings:
|
||||||
|
CPU: AnyCPU
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
BIN
Assets/Plugins/NuGet/Microsoft.Bcl.TimeProvider.dll
Normal file
BIN
Assets/Plugins/NuGet/Microsoft.Bcl.TimeProvider.dll
Normal file
Binary file not shown.
28
Assets/Plugins/NuGet/Microsoft.Bcl.TimeProvider.dll.meta
Normal file
28
Assets/Plugins/NuGet/Microsoft.Bcl.TimeProvider.dll.meta
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9543ba4b10348da4bbe360ba460689b3
|
||||||
|
PluginImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 3
|
||||||
|
iconMap: {}
|
||||||
|
executionOrder: {}
|
||||||
|
defineConstraints: []
|
||||||
|
isPreloaded: 0
|
||||||
|
isOverridable: 0
|
||||||
|
isExplicitlyReferenced: 0
|
||||||
|
validateReferences: 1
|
||||||
|
platformData:
|
||||||
|
Any:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
Exclude Editor: 0
|
||||||
|
Editor:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
DefaultValueInitialized: true
|
||||||
|
WindowsStoreApps:
|
||||||
|
enabled: 0
|
||||||
|
settings:
|
||||||
|
CPU: AnyCPU
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
BIN
Assets/Plugins/NuGet/Microsoft.CodeAnalysis.CSharp.dll
Normal file
BIN
Assets/Plugins/NuGet/Microsoft.CodeAnalysis.CSharp.dll
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user