Compare commits
6 Commits
0e3cb360ee
...
30390cb288
| Author | SHA1 | Date | |
|---|---|---|---|
| 30390cb288 | |||
| d195bdd14e | |||
| 972956323d | |||
| 75bbc0131e | |||
| ac09170856 | |||
| d0e23e6408 |
175
.codex/skills/th1-base/SKILL.md
Normal file
175
.codex/skills/th1-base/SKILL.md
Normal file
@ -0,0 +1,175 @@
|
||||
---
|
||||
name: th1-base
|
||||
description: TH1 project baseline engineering guide for Unity client changes: assembly boundaries, HybridCLR hotfix rules, YooAsset/AssetBundle resource rules, MemoryPack/AOT serialization safety, build packaging flow, and routing to domain skills. Use before broad TH1 Unity code/resource/build changes, especially when touching Scripts, asmdefs, HybridCLR, hotfix DLLs, StreamingAssets, BundleResources, Resources.Load replacement, YooAsset, MemoryPack, generated config, build panels, or package verification.
|
||||
---
|
||||
|
||||
# TH1 Base Engineering
|
||||
|
||||
## Core Rule
|
||||
|
||||
Treat TH1 as a hot-update Unity project with a small AOT shell, a large `TH1.Hotfix` gameplay layer, and YooAsset-managed resources.
|
||||
|
||||
Most feature work may live in hotfix code, but platform bootstrap, HybridCLR/YooAsset initialization, AOT metadata loading, and build packaging must remain stable and boring. Do not solve a hotfix/AOT/resource issue with one-off special cases when a shared entrypoint or generator fix is possible.
|
||||
|
||||
## Skill Routing
|
||||
|
||||
Start here for baseline constraints, then add the domain skill that owns the behavior:
|
||||
|
||||
- `th1-ios-migration`: iOS/IL2CPP, HybridCLR, YooAsset, Steam platform isolation, touch/mobile, packaging.
|
||||
- `th1-action-logic`: gameplay actions, AI action flow, turn state, replay, deterministic skill side effects.
|
||||
- `th1-network-sync`: Steam lobby/P2P, GameStart/ForceUpdate, `MapData` network payloads, multiplayer resume.
|
||||
- `th1-game-archive`: local save/load, `GameRecord`, archive files, resume, bug report archive payloads.
|
||||
- `th1-multilingual`: localization export/import, `Multilingual.asset`, Workshop language mods.
|
||||
- `th1-server-backend`: OSS/STS/function compute/upload/auth backend work.
|
||||
- `th1-online-debug`: production logs, CrashSight/UnityLogError, obfuscated stack decode.
|
||||
- `th1-crashsight-daily`: daily CrashSight triage and reports.
|
||||
- `.agents/skills/th1-config-guide`: Excel config generation, `GenerateCS`/`ExcelPartial`, MemoryPack config rules.
|
||||
- `.agents/skills/th1-ui-patterns`: View/Controller UI work.
|
||||
- `.agents/skills/th1-ai-nodes`: NodeCanvas AI behavior tree nodes.
|
||||
- `.agents/skills/th1-anim-scope`: attack animation scope-aware renderer updates.
|
||||
|
||||
If multiple skills apply, use this skill first, then the narrow domain skill.
|
||||
|
||||
## First Moves
|
||||
|
||||
- Run `git status --short`; preserve unrelated user/Unity changes.
|
||||
- Identify whether the change touches AOT shell, hotfix code, resources/AB, serialization, build pipeline, platform services, or gameplay behavior.
|
||||
- For Unity code changes, inspect nearby asmdefs and namespace ownership before moving files.
|
||||
- For generated files, find and update the generator/template instead of hand-editing output, unless the user explicitly asks for a one-off generated output patch.
|
||||
- Do not modify MemoryPack compatibility, obfuscation behavior, or generated config formats without explicit confirmation.
|
||||
|
||||
## Assembly Boundaries
|
||||
|
||||
Current target shape:
|
||||
|
||||
- AOT shell: minimal startup scene and bootstrap code. It loads AOT metadata, loads `TH1.Hotfix.dll.bytes`, initializes YooAsset, loads the game scene, then invokes hotfix entrypoints.
|
||||
- `TH1.Hotfix`: gameplay logic, UI logic, renderer logic, config consumers, AI nodes, save/game/archive logic where possible.
|
||||
- `TH1_Resource`: resource facade and compatibility wrappers. Gameplay code should load through these wrappers, not direct YooAsset calls scattered everywhere.
|
||||
- Editor assemblies: build panels, HybridCLR/YooAsset tools, config/export windows. They must not leak into runtime/hotfix assemblies.
|
||||
|
||||
Rules:
|
||||
|
||||
- The Build Settings scene should be the empty/init AOT shell scene. The real game scene is loaded through YooAsset after hotfix and metadata are ready.
|
||||
- Do not put hotfix `MonoBehaviour` references directly in the shell scene.
|
||||
- If a prefab/scene contains hotfix scripts, it must be loaded only after the hotfix assembly is loaded.
|
||||
- Keep startup contracts stable and explicit. Prefer direct typed calls for required runtime packages over reflection that silently skips failures.
|
||||
- Hotfix code must not directly reference editor-only assemblies or platform-specific SDKs that are unavailable on the target platform.
|
||||
|
||||
## HybridCLR Rules
|
||||
|
||||
- After hotfix code, AOT dependency, or generic-heavy serialization changes, rerun the HybridCLR prepare flow before packaging.
|
||||
- Required artifacts are platform-specific: hotfix DLL bytes and AOT metadata under `StreamingAssets/HybridCLR`.
|
||||
- Load supplemental metadata before starting hotfix gameplay:
|
||||
- `mscorlib.dll.bytes`
|
||||
- `System.dll.bytes`
|
||||
- `System.Core.dll.bytes`
|
||||
- `MemoryPack.dll.bytes`
|
||||
- `System.Runtime.CompilerServices.Unsafe.dll.bytes`
|
||||
- Use `HybridCLR.RuntimeApi.LoadMetadataForAOTAssembly(..., HomologousImageMode.SuperSet)` for the required load path; do not hide missing RuntimeApi as a non-fatal reflection miss in player builds.
|
||||
- Do not manually copy stale hotfix DLLs. Use the project build panel/command so generated DLL, AOT metadata, and build status stay consistent.
|
||||
- If NodeCanvas/ParadoxNotion serialized task types are moved into hotfix, refresh/regenerate the relevant type metadata before packaging.
|
||||
|
||||
## MemoryPack And AOT Serialization
|
||||
|
||||
MemoryPack format compatibility is high risk. Preserve layout unless explicitly changing format.
|
||||
|
||||
Runtime/hotfix code should avoid direct generic MemoryPack entrypoints when the serialized type may live in hotfix:
|
||||
|
||||
```csharp
|
||||
// Prefer project wrapper or Type API.
|
||||
TH1Serialization.Serialize(value);
|
||||
TH1Serialization.Deserialize<T>(bytes);
|
||||
|
||||
MemoryPackSerializer.Serialize(typeof(T), value);
|
||||
MemoryPackSerializer.Deserialize(typeof(T), bytes);
|
||||
```
|
||||
|
||||
Avoid adding new runtime code like:
|
||||
|
||||
```csharp
|
||||
MemoryPackSerializer.Serialize<T>(value);
|
||||
MemoryPackSerializer.Deserialize<T>(bytes);
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
- Use `TH1_Logic.Tools.TH1Serialization` for gameplay/save/network/runtime data.
|
||||
- For generators that cannot reference Unity runtime code, generate MemoryPack `Type` API calls.
|
||||
- Do not reorder or remove existing `[MemoryPackInclude]` members in persisted/networked types. Append new fields.
|
||||
- For old fields no longer used, keep compatibility placeholders when later fields would shift.
|
||||
- Treat `MapData`, `NetData`, `GameRecord`, `GameRecordData`, config bytes, and network messages as compatibility-sensitive.
|
||||
- If generated config code needs a change, update `ExcelExport/ExportTemplate_*.txt` and regenerate/sync output.
|
||||
|
||||
## YooAsset And AB Rules
|
||||
|
||||
Resources are moving to AB-first loading:
|
||||
|
||||
- Use `Assets/BundleResources` as the packaged resource root.
|
||||
- Prefer stable logical addresses. Do not make gameplay code depend on platform-specific bundle paths.
|
||||
- Replace `Resources.Load` through `TH1Resource.ResourceLoader`/resource cache wrappers, not scattered direct YooAsset calls.
|
||||
- Editor may run simulate mode; PC/iOS packages should run actual built-in AB package logic.
|
||||
- Rebuild YooAsset bundles after moving, adding, deleting, or renaming packaged assets.
|
||||
- Keep Standalone and iOS bundles separate. Do not reuse PC bundle assumptions for iOS compression or platform output.
|
||||
- Do not put invalid source files in AB roots: backups (`*.BAK`), raw local-only config, editor-only files, or unknown icon/temp files should live outside `BundleResources`.
|
||||
- If an address is missing, fix the collector/address/generator path rather than adding local `Resources` fallbacks.
|
||||
|
||||
## Build And Packaging Flow
|
||||
|
||||
For migration-era PC IL2CPP smoke builds, use the project one-click flow where possible:
|
||||
|
||||
1. Configure target platform/build settings.
|
||||
2. Configure HybridCLR.
|
||||
3. Run HybridCLR `GenerateAll`.
|
||||
4. Build hotfix DLL and copy hotfix/AOT metadata to `StreamingAssets`.
|
||||
5. Build YooAsset built-in `DefaultPackage`.
|
||||
6. Build Windows IL2CPP player.
|
||||
7. Launch player and scan the log for startup red errors.
|
||||
|
||||
Manual Unity packaging gotchas:
|
||||
|
||||
- After scene list changes, use full `Build`/`Clean Build`; do not use `Build Scripts Only`.
|
||||
- If you only need a runnable PC package, keep `Create Visual Studio Solution` off unless explicitly debugging the generated solution.
|
||||
- Avoid `Script Debugging` for automated smoke player runs; it can wait for a managed debugger.
|
||||
- If Unity exports a Visual Studio solution for IL2CPP, MSBuild may need current Windows SDK/toolset retargeting.
|
||||
- Generated build artifacts such as `HybridCLRGenerate/AOTGenericReferences.cs` may change after HybridCLR GenerateAll; commit them only when intentionally refreshed.
|
||||
- Obfuscator logs and local build output should not be committed unless explicitly part of the requested change.
|
||||
|
||||
Startup smoke success markers:
|
||||
|
||||
- AOT metadata logs show `OK`.
|
||||
- `TH1.Hotfix` loads.
|
||||
- YooAsset `DefaultPackage` initializes.
|
||||
- Game scene loads from YooAsset.
|
||||
- Hotfix `Main` starts.
|
||||
- No `MissingMethodException`, `Type Request Error`, `NullReferenceException`, or `LogError` during startup.
|
||||
|
||||
## Verification
|
||||
|
||||
For ordinary Unity runtime C#:
|
||||
|
||||
```powershell
|
||||
dotnet build Unity/Assembly-CSharp.csproj --no-restore
|
||||
```
|
||||
|
||||
For editor/build/config tooling:
|
||||
|
||||
```powershell
|
||||
dotnet build Unity/Assembly-CSharp-Editor.csproj --no-restore
|
||||
```
|
||||
|
||||
Known caveat: this repo can hit Unity package compile errors outside changed code when building the full editor csproj from dotnet. If that happens, report it clearly and verify the narrower runtime/tool project or Unity Editor compile path instead.
|
||||
|
||||
For config generator changes:
|
||||
|
||||
```powershell
|
||||
dotnet run --project ExcelExport/ExcelExport.csproj -- 1
|
||||
dotnet build ExcelExport/ExcelExport.csproj --no-restore
|
||||
```
|
||||
|
||||
Before finishing migration/build work, inspect:
|
||||
|
||||
```powershell
|
||||
rg -n "Resources\\.Load|MemoryPackSerializer\\.Serialize<|MemoryPackSerializer\\.Deserialize<|using Steamworks|BuildScriptsOnly" Unity/Assets/Scripts
|
||||
```
|
||||
|
||||
Only treat matches as problems after checking context; editor-only tools and intentionally platform-bound Steam implementations may be valid.
|
||||
@ -7,6 +7,7 @@ This repository is a Unity 2022.3 LTS / ET Framework turn-based strategy game. T
|
||||
- For architecture questions, read the `MD/GameMDFramework/00-*` overview document and the relevant subsystem document before editing.
|
||||
- For code navigation, read `Unity/graphify-out/GRAPH_REPORT.md` for Unity code and `graphify-out/GRAPH_REPORT.md` for whole-repository context.
|
||||
- If a task touches action execution, networking, localization, online errors, backend upload, or CrashSight reports, use the matching `.codex/skills/th1-*` skill first.
|
||||
- For broad TH1 Unity/code/resource/build changes, use `.codex/skills/th1-base` first, then layer the narrower business skill on top.
|
||||
- Claude-era context remains in `.claude/` and `Unity/Assets/Scripts/CLAUDE.md`; treat it as historical source material, not the active entrypoint.
|
||||
|
||||
## Project Shape
|
||||
@ -36,6 +37,7 @@ This repository is a Unity 2022.3 LTS / ET Framework turn-based strategy game. T
|
||||
## Codex Skills And Agents
|
||||
|
||||
- Prefer `.codex/skills` for current project-specific workflows:
|
||||
- `th1-base`: baseline Unity engineering rules for assembly boundaries, HybridCLR hotfix, YooAsset/AB, MemoryPack/AOT serialization, generated config, and build/package verification.
|
||||
- `th1-action-logic`: action execution, AI action flow, turn actions, and action-triggered skills.
|
||||
- `th1-network-sync`: Steam lobby, P2P, multiplayer save/recovery, action sync, and deterministic network behavior.
|
||||
- `th1-multilingual`: localization import/export, active text scanning, duplicate IDs, and translation diagnostics.
|
||||
|
||||
@ -14,7 +14,7 @@ namespace ExcelConfig
|
||||
|
||||
public override void Init(byte[] data)
|
||||
{
|
||||
Dict = MemoryPackSerializer.Deserialize<Dictionary<int, (ConfigName)>>(data);
|
||||
Dict = (Dictionary<int, (ConfigName)>)MemoryPackSerializer.Deserialize(typeof(Dictionary<int, (ConfigName)>), data)!;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ namespace ExcelConfig
|
||||
|
||||
public override byte[] GetData()
|
||||
{
|
||||
return MemoryPackSerializer.Serialize(Dict);
|
||||
return MemoryPackSerializer.Serialize(typeof(Dictionary<int, (ConfigName)>), Dict);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ namespace ExcelConfig
|
||||
|
||||
public override void Init(byte[] data)
|
||||
{
|
||||
Dict = MemoryPackSerializer.Deserialize<Dictionary<int, AIConfig>>(data);
|
||||
Dict = (Dictionary<int, AIConfig>)MemoryPackSerializer.Deserialize(typeof(Dictionary<int, AIConfig>), data)!;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ namespace ExcelConfig
|
||||
|
||||
public override void Init(byte[] data)
|
||||
{
|
||||
Dict = MemoryPackSerializer.Deserialize<Dictionary<int, GeoDesc>>(data);
|
||||
Dict = (Dictionary<int, GeoDesc>)MemoryPackSerializer.Deserialize(typeof(Dictionary<int, GeoDesc>), data)!;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ namespace ExcelConfig
|
||||
|
||||
public override void Init(byte[] data)
|
||||
{
|
||||
Dict = MemoryPackSerializer.Deserialize<Dictionary<int, Moment>>(data);
|
||||
Dict = (Dictionary<int, Moment>)MemoryPackSerializer.Deserialize(typeof(Dictionary<int, Moment>), data)!;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ namespace ExcelConfig
|
||||
|
||||
public override byte[] GetData()
|
||||
{
|
||||
return MemoryPackSerializer.Serialize(Dict);
|
||||
return MemoryPackSerializer.Serialize(typeof(Dictionary<int, AIConfig>), Dict);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ namespace ExcelConfig
|
||||
|
||||
public override byte[] GetData()
|
||||
{
|
||||
return MemoryPackSerializer.Serialize(Dict);
|
||||
return MemoryPackSerializer.Serialize(typeof(Dictionary<int, GeoDesc>), Dict);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ namespace ExcelConfig
|
||||
|
||||
public override byte[] GetData()
|
||||
{
|
||||
return MemoryPackSerializer.Serialize(Dict);
|
||||
return MemoryPackSerializer.Serialize(typeof(Dictionary<int, Moment>), Dict);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -103,7 +103,6 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
|
||||
// System.Action<Logic.AI.MatchResult>
|
||||
// System.Action<Logic.Multilingual.TranslationEntry>
|
||||
// System.Action<Logic.Multilingual.WorkshopModLoader.SubscribedModEntry>
|
||||
// System.Action<MemoryPack.Internal.BufferSegment>
|
||||
// System.Action<MomentImagePack>
|
||||
// System.Action<RuntimeData.UnitFullType>
|
||||
// System.Action<SkillViewTypeColor>
|
||||
@ -240,7 +239,6 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
|
||||
// System.Buffers.ArrayPool<byte>
|
||||
// System.Buffers.ConfigurableArrayPool.Bucket<byte>
|
||||
// System.Buffers.ConfigurableArrayPool<byte>
|
||||
// System.Buffers.IBufferWriter<byte>
|
||||
// System.Buffers.MemoryManager<byte>
|
||||
// System.Buffers.MemoryManager<float>
|
||||
// System.Buffers.TlsOverPerCoreLockedStacksArrayPool.LockedStack<byte>
|
||||
@ -262,7 +260,6 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
|
||||
// System.Collections.Generic.ArraySortHelper<Logic.AI.MatchResult>
|
||||
// System.Collections.Generic.ArraySortHelper<Logic.Multilingual.TranslationEntry>
|
||||
// System.Collections.Generic.ArraySortHelper<Logic.Multilingual.WorkshopModLoader.SubscribedModEntry>
|
||||
// System.Collections.Generic.ArraySortHelper<MemoryPack.Internal.BufferSegment>
|
||||
// System.Collections.Generic.ArraySortHelper<MomentImagePack>
|
||||
// System.Collections.Generic.ArraySortHelper<RuntimeData.UnitFullType>
|
||||
// System.Collections.Generic.ArraySortHelper<SkillViewTypeColor>
|
||||
@ -305,7 +302,6 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
|
||||
// System.Collections.Generic.Comparer<Logic.AI.MatchResult>
|
||||
// System.Collections.Generic.Comparer<Logic.Multilingual.TranslationEntry>
|
||||
// System.Collections.Generic.Comparer<Logic.Multilingual.WorkshopModLoader.SubscribedModEntry>
|
||||
// System.Collections.Generic.Comparer<MemoryPack.Internal.BufferSegment>
|
||||
// System.Collections.Generic.Comparer<MomentImagePack>
|
||||
// System.Collections.Generic.Comparer<RuntimeData.UnitFullType>
|
||||
// System.Collections.Generic.Comparer<SkillViewTypeColor>
|
||||
@ -349,7 +345,6 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
|
||||
// System.Collections.Generic.ComparisonComparer<Logic.AI.MatchResult>
|
||||
// System.Collections.Generic.ComparisonComparer<Logic.Multilingual.TranslationEntry>
|
||||
// System.Collections.Generic.ComparisonComparer<Logic.Multilingual.WorkshopModLoader.SubscribedModEntry>
|
||||
// System.Collections.Generic.ComparisonComparer<MemoryPack.Internal.BufferSegment>
|
||||
// System.Collections.Generic.ComparisonComparer<MomentImagePack>
|
||||
// System.Collections.Generic.ComparisonComparer<RuntimeData.UnitFullType>
|
||||
// System.Collections.Generic.ComparisonComparer<SkillViewTypeColor>
|
||||
@ -611,7 +606,6 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
|
||||
// System.Collections.Generic.ICollection<Logic.AI.MatchResult>
|
||||
// System.Collections.Generic.ICollection<Logic.Multilingual.TranslationEntry>
|
||||
// System.Collections.Generic.ICollection<Logic.Multilingual.WorkshopModLoader.SubscribedModEntry>
|
||||
// System.Collections.Generic.ICollection<MemoryPack.Internal.BufferSegment>
|
||||
// System.Collections.Generic.ICollection<MomentImagePack>
|
||||
// System.Collections.Generic.ICollection<RuntimeData.UnitFullType>
|
||||
// System.Collections.Generic.ICollection<SkillViewTypeColor>
|
||||
@ -682,7 +676,6 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
|
||||
// System.Collections.Generic.IComparer<Logic.AI.MatchResult>
|
||||
// System.Collections.Generic.IComparer<Logic.Multilingual.TranslationEntry>
|
||||
// System.Collections.Generic.IComparer<Logic.Multilingual.WorkshopModLoader.SubscribedModEntry>
|
||||
// System.Collections.Generic.IComparer<MemoryPack.Internal.BufferSegment>
|
||||
// System.Collections.Generic.IComparer<MomentImagePack>
|
||||
// System.Collections.Generic.IComparer<RuntimeData.UnitFullType>
|
||||
// System.Collections.Generic.IComparer<SkillViewTypeColor>
|
||||
@ -727,7 +720,6 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
|
||||
// System.Collections.Generic.IEnumerable<Logic.AI.MatchResult>
|
||||
// System.Collections.Generic.IEnumerable<Logic.Multilingual.TranslationEntry>
|
||||
// System.Collections.Generic.IEnumerable<Logic.Multilingual.WorkshopModLoader.SubscribedModEntry>
|
||||
// System.Collections.Generic.IEnumerable<MemoryPack.Internal.BufferSegment>
|
||||
// System.Collections.Generic.IEnumerable<MomentImagePack>
|
||||
// System.Collections.Generic.IEnumerable<RuntimeData.UnitFullType>
|
||||
// System.Collections.Generic.IEnumerable<SkillViewTypeColor>
|
||||
@ -798,7 +790,6 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
|
||||
// System.Collections.Generic.IEnumerator<Logic.AI.MatchResult>
|
||||
// System.Collections.Generic.IEnumerator<Logic.Multilingual.TranslationEntry>
|
||||
// System.Collections.Generic.IEnumerator<Logic.Multilingual.WorkshopModLoader.SubscribedModEntry>
|
||||
// System.Collections.Generic.IEnumerator<MemoryPack.Internal.BufferSegment>
|
||||
// System.Collections.Generic.IEnumerator<MomentImagePack>
|
||||
// System.Collections.Generic.IEnumerator<RuntimeData.UnitFullType>
|
||||
// System.Collections.Generic.IEnumerator<SkillViewTypeColor>
|
||||
@ -882,7 +873,6 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
|
||||
// System.Collections.Generic.IList<Logic.AI.MatchResult>
|
||||
// System.Collections.Generic.IList<Logic.Multilingual.TranslationEntry>
|
||||
// System.Collections.Generic.IList<Logic.Multilingual.WorkshopModLoader.SubscribedModEntry>
|
||||
// System.Collections.Generic.IList<MemoryPack.Internal.BufferSegment>
|
||||
// System.Collections.Generic.IList<MomentImagePack>
|
||||
// System.Collections.Generic.IList<RuntimeData.UnitFullType>
|
||||
// System.Collections.Generic.IList<SkillViewTypeColor>
|
||||
@ -969,7 +959,6 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
|
||||
// System.Collections.Generic.List.Enumerator<Logic.AI.MatchResult>
|
||||
// System.Collections.Generic.List.Enumerator<Logic.Multilingual.TranslationEntry>
|
||||
// System.Collections.Generic.List.Enumerator<Logic.Multilingual.WorkshopModLoader.SubscribedModEntry>
|
||||
// System.Collections.Generic.List.Enumerator<MemoryPack.Internal.BufferSegment>
|
||||
// System.Collections.Generic.List.Enumerator<MomentImagePack>
|
||||
// System.Collections.Generic.List.Enumerator<RuntimeData.UnitFullType>
|
||||
// System.Collections.Generic.List.Enumerator<SkillViewTypeColor>
|
||||
@ -1012,7 +1001,6 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
|
||||
// System.Collections.Generic.List<Logic.AI.MatchResult>
|
||||
// System.Collections.Generic.List<Logic.Multilingual.TranslationEntry>
|
||||
// System.Collections.Generic.List<Logic.Multilingual.WorkshopModLoader.SubscribedModEntry>
|
||||
// System.Collections.Generic.List<MemoryPack.Internal.BufferSegment>
|
||||
// System.Collections.Generic.List<MomentImagePack>
|
||||
// System.Collections.Generic.List<RuntimeData.UnitFullType>
|
||||
// System.Collections.Generic.List<SkillViewTypeColor>
|
||||
@ -1055,7 +1043,6 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
|
||||
// System.Collections.Generic.ObjectComparer<Logic.AI.MatchResult>
|
||||
// System.Collections.Generic.ObjectComparer<Logic.Multilingual.TranslationEntry>
|
||||
// System.Collections.Generic.ObjectComparer<Logic.Multilingual.WorkshopModLoader.SubscribedModEntry>
|
||||
// System.Collections.Generic.ObjectComparer<MemoryPack.Internal.BufferSegment>
|
||||
// System.Collections.Generic.ObjectComparer<MomentImagePack>
|
||||
// System.Collections.Generic.ObjectComparer<RuntimeData.UnitFullType>
|
||||
// System.Collections.Generic.ObjectComparer<SkillViewTypeColor>
|
||||
@ -1154,7 +1141,6 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
|
||||
// System.Collections.ObjectModel.ReadOnlyCollection<Logic.AI.MatchResult>
|
||||
// System.Collections.ObjectModel.ReadOnlyCollection<Logic.Multilingual.TranslationEntry>
|
||||
// System.Collections.ObjectModel.ReadOnlyCollection<Logic.Multilingual.WorkshopModLoader.SubscribedModEntry>
|
||||
// System.Collections.ObjectModel.ReadOnlyCollection<MemoryPack.Internal.BufferSegment>
|
||||
// System.Collections.ObjectModel.ReadOnlyCollection<MomentImagePack>
|
||||
// System.Collections.ObjectModel.ReadOnlyCollection<RuntimeData.UnitFullType>
|
||||
// System.Collections.ObjectModel.ReadOnlyCollection<SkillViewTypeColor>
|
||||
@ -1197,7 +1183,6 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
|
||||
// System.Comparison<Logic.AI.MatchResult>
|
||||
// System.Comparison<Logic.Multilingual.TranslationEntry>
|
||||
// System.Comparison<Logic.Multilingual.WorkshopModLoader.SubscribedModEntry>
|
||||
// System.Comparison<MemoryPack.Internal.BufferSegment>
|
||||
// System.Comparison<MomentImagePack>
|
||||
// System.Comparison<RuntimeData.UnitFullType>
|
||||
// System.Comparison<SkillViewTypeColor>
|
||||
@ -1313,7 +1298,6 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
|
||||
// System.Predicate<Logic.AI.MatchResult>
|
||||
// System.Predicate<Logic.Multilingual.TranslationEntry>
|
||||
// System.Predicate<Logic.Multilingual.WorkshopModLoader.SubscribedModEntry>
|
||||
// System.Predicate<MemoryPack.Internal.BufferSegment>
|
||||
// System.Predicate<MomentImagePack>
|
||||
// System.Predicate<RuntimeData.UnitFullType>
|
||||
// System.Predicate<SkillViewTypeColor>
|
||||
@ -1458,9 +1442,7 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
|
||||
// byte& MemoryPack.Internal.MemoryMarshalEx.GetArrayDataReference<byte>(byte[])
|
||||
// int& MemoryPack.Internal.MemoryMarshalEx.GetArrayDataReference<int>(int[])
|
||||
// object& MemoryPack.Internal.MemoryMarshalEx.GetArrayDataReference<object>(object[])
|
||||
// MemoryPack.MemoryPackFormatter<int> MemoryPack.MemoryPackFormatterProvider.GetFormatter<int>()
|
||||
// MemoryPack.MemoryPackFormatter<object> MemoryPack.MemoryPackFormatterProvider.GetFormatter<object>()
|
||||
// MemoryPack.MemoryPackFormatter<uint> MemoryPack.MemoryPackFormatterProvider.GetFormatter<uint>()
|
||||
// bool MemoryPack.MemoryPackFormatterProvider.IsRegistered<byte>()
|
||||
// bool MemoryPack.MemoryPackFormatterProvider.IsRegistered<int>()
|
||||
// bool MemoryPack.MemoryPackFormatterProvider.IsRegistered<object>()
|
||||
@ -1557,21 +1539,10 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
|
||||
// int[] MemoryPack.MemoryPackReader.ReadUnmanagedArray<int>()
|
||||
// System.Void MemoryPack.MemoryPackReader.ReadValue<object>(object&)
|
||||
// object MemoryPack.MemoryPackReader.ReadValue<object>()
|
||||
// int MemoryPack.MemoryPackSerializer.Deserialize<object>(System.ReadOnlySpan<byte>,object&,MemoryPack.MemoryPackSerializerOptions)
|
||||
// object MemoryPack.MemoryPackSerializer.Deserialize<object>(System.ReadOnlySpan<byte>,MemoryPack.MemoryPackSerializerOptions)
|
||||
// System.Void MemoryPack.MemoryPackSerializer.Serialize<int>(MemoryPack.MemoryPackWriter&,int&)
|
||||
// System.Void MemoryPack.MemoryPackSerializer.Serialize<object>(MemoryPack.MemoryPackWriter&,object&)
|
||||
// System.Void MemoryPack.MemoryPackSerializer.Serialize<object>(System.Buffers.IBufferWriter<byte>&,object&,MemoryPack.MemoryPackSerializerOptions)
|
||||
// System.Void MemoryPack.MemoryPackSerializer.Serialize<uint>(MemoryPack.MemoryPackWriter&,uint&)
|
||||
// byte[] MemoryPack.MemoryPackSerializer.Serialize<int>(int&,MemoryPack.MemoryPackSerializerOptions)
|
||||
// byte[] MemoryPack.MemoryPackSerializer.Serialize<object>(object&,MemoryPack.MemoryPackSerializerOptions)
|
||||
// byte[] MemoryPack.MemoryPackSerializer.Serialize<uint>(uint&,MemoryPack.MemoryPackSerializerOptions)
|
||||
// System.Void MemoryPack.MemoryPackWriter.DangerousWriteUnmanagedArray<byte>(byte[])
|
||||
// System.Void MemoryPack.MemoryPackWriter.DangerousWriteUnmanagedArray<int>(int[])
|
||||
// System.Void MemoryPack.MemoryPackWriter.DangerousWriteUnmanagedArray<object>(object[])
|
||||
// MemoryPack.IMemoryPackFormatter<int> MemoryPack.MemoryPackWriter.GetFormatter<int>()
|
||||
// MemoryPack.IMemoryPackFormatter<object> MemoryPack.MemoryPackWriter.GetFormatter<object>()
|
||||
// MemoryPack.IMemoryPackFormatter<uint> MemoryPack.MemoryPackWriter.GetFormatter<uint>()
|
||||
// System.Void MemoryPack.MemoryPackWriter.WriteArray<object>(object[])
|
||||
// System.Void MemoryPack.MemoryPackWriter.WritePackable<object>(object&)
|
||||
// System.Void MemoryPack.MemoryPackWriter.WriteUnmanaged<byte,RuntimeData.UnitFullType,int,int,uint,int,int,int,RuntimeData.UnitFullType,RuntimeData.UnitFullType,int,int,uint,float,RuntimeData.UnitFullType>(byte&,RuntimeData.UnitFullType&,int&,int&,uint&,int&,int&,int&,RuntimeData.UnitFullType&,RuntimeData.UnitFullType&,int&,int&,uint&,float&,RuntimeData.UnitFullType&)
|
||||
@ -1653,9 +1624,7 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
|
||||
// System.Void MemoryPack.MemoryPackWriter.WriteUnmanagedWithObjectHeader<ulong,uint,uint,uint,byte,int,int,byte,byte,byte>(byte,ulong&,uint&,uint&,uint&,byte&,int&,int&,byte&,byte&,byte&)
|
||||
// System.Void MemoryPack.MemoryPackWriter.WriteUnmanagedWithObjectHeader<ulong,ulong>(byte,ulong&,ulong&)
|
||||
// System.Void MemoryPack.MemoryPackWriter.WriteUnmanagedWithObjectHeader<ulong>(byte,ulong&)
|
||||
// System.Void MemoryPack.MemoryPackWriter.WriteValue<int>(int&)
|
||||
// System.Void MemoryPack.MemoryPackWriter.WriteValue<object>(object&)
|
||||
// System.Void MemoryPack.MemoryPackWriter.WriteValue<uint>(uint&)
|
||||
// Microsoft.ML.OnnxRuntime.Tensors.Tensor<float> Microsoft.ML.OnnxRuntime.NamedOnnxValue.AsTensor<float>()
|
||||
// Microsoft.ML.OnnxRuntime.NamedOnnxValue Microsoft.ML.OnnxRuntime.NamedOnnxValue.CreateFromTensor<float>(string,Microsoft.ML.OnnxRuntime.Tensors.Tensor<float>)
|
||||
// NodeCanvas.Framework.Variable<object> NodeCanvas.Framework.IBlackboardExtensions.GetVariable<object>(NodeCanvas.Framework.IBlackboard,string)
|
||||
@ -1740,9 +1709,7 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
|
||||
// System.Void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.ValueTuple<byte,object>>.Start<object>(object&)
|
||||
// System.Void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<byte>.Start<object>(object&)
|
||||
// System.Void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<object>.Start<object>(object&)
|
||||
// bool System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences<int>()
|
||||
// bool System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences<object>()
|
||||
// bool System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences<uint>()
|
||||
// byte& System.Runtime.CompilerServices.Unsafe.Add<byte>(byte&,int)
|
||||
// byte& System.Runtime.CompilerServices.Unsafe.As<byte,byte>(byte&)
|
||||
// byte& System.Runtime.CompilerServices.Unsafe.As<int,byte>(int&)
|
||||
@ -1750,16 +1717,13 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
|
||||
// object& System.Runtime.CompilerServices.Unsafe.As<object,object>(object&)
|
||||
// object& System.Runtime.CompilerServices.Unsafe.As<object,object>(object&)
|
||||
// System.Void* System.Runtime.CompilerServices.Unsafe.AsPointer<object>(object&)
|
||||
// int& System.Runtime.CompilerServices.Unsafe.AsRef<int>(int&)
|
||||
// object& System.Runtime.CompilerServices.Unsafe.AsRef<object>(object&)
|
||||
// uint& System.Runtime.CompilerServices.Unsafe.AsRef<uint>(uint&)
|
||||
// Empire System.Runtime.CompilerServices.Unsafe.ReadUnaligned<Empire>(byte&)
|
||||
// RuntimeData.UnitFullType System.Runtime.CompilerServices.Unsafe.ReadUnaligned<RuntimeData.UnitFullType>(byte&)
|
||||
// byte System.Runtime.CompilerServices.Unsafe.ReadUnaligned<byte>(byte&)
|
||||
// float System.Runtime.CompilerServices.Unsafe.ReadUnaligned<float>(byte&)
|
||||
// int System.Runtime.CompilerServices.Unsafe.ReadUnaligned<int>(byte&)
|
||||
// long System.Runtime.CompilerServices.Unsafe.ReadUnaligned<long>(byte&)
|
||||
// object System.Runtime.CompilerServices.Unsafe.ReadUnaligned<object>(byte&)
|
||||
// uint System.Runtime.CompilerServices.Unsafe.ReadUnaligned<uint>(byte&)
|
||||
// ulong System.Runtime.CompilerServices.Unsafe.ReadUnaligned<ulong>(byte&)
|
||||
// int System.Runtime.CompilerServices.Unsafe.SizeOf<Empire>()
|
||||
@ -1777,11 +1741,9 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
|
||||
// System.Void System.Runtime.CompilerServices.Unsafe.WriteUnaligned<float>(byte&,float)
|
||||
// System.Void System.Runtime.CompilerServices.Unsafe.WriteUnaligned<int>(byte&,int)
|
||||
// System.Void System.Runtime.CompilerServices.Unsafe.WriteUnaligned<long>(byte&,long)
|
||||
// System.Void System.Runtime.CompilerServices.Unsafe.WriteUnaligned<object>(byte&,object)
|
||||
// System.Void System.Runtime.CompilerServices.Unsafe.WriteUnaligned<uint>(byte&,uint)
|
||||
// System.Void System.Runtime.CompilerServices.Unsafe.WriteUnaligned<ulong>(byte&,ulong)
|
||||
// Steamworks.SteamNetworkingMessage_t System.Runtime.InteropServices.Marshal.PtrToStructure<Steamworks.SteamNetworkingMessage_t>(System.IntPtr)
|
||||
// byte& System.Runtime.InteropServices.MemoryMarshal.GetReference<byte>(System.ReadOnlySpan<byte>)
|
||||
// byte& System.Runtime.InteropServices.MemoryMarshal.GetReference<byte>(System.Span<byte>)
|
||||
// int& System.Runtime.InteropServices.MemoryMarshal.GetReference<int>(System.Span<int>)
|
||||
// object& System.Runtime.InteropServices.MemoryMarshal.GetReference<object>(System.Span<object>)
|
||||
|
||||
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using HybridCLR;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TH1_Logic.Hotfix
|
||||
@ -85,26 +86,6 @@ namespace TH1_Logic.Hotfix
|
||||
{
|
||||
if (_aotMetadataLoaded) return;
|
||||
|
||||
var runtimeApiType = FindType("HybridCLR.RuntimeApi");
|
||||
var modeType = FindType("HybridCLR.HomologousImageMode");
|
||||
if (runtimeApiType == null || modeType == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var method = runtimeApiType.GetMethod(
|
||||
"LoadMetadataForAOTAssembly",
|
||||
BindingFlags.Public | BindingFlags.Static,
|
||||
null,
|
||||
new[] { typeof(byte[]), modeType },
|
||||
null);
|
||||
if (method == null)
|
||||
{
|
||||
Debug.LogWarning("[TH1.Hotfix] HybridCLR RuntimeApi.LoadMetadataForAOTAssembly not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
var mode = Enum.Parse(modeType, "SuperSet");
|
||||
var aotDir = Path.Combine(root, HotfixManifest.AotMetadataFolderName);
|
||||
var allLoaded = true;
|
||||
|
||||
@ -118,7 +99,7 @@ namespace TH1_Logic.Hotfix
|
||||
continue;
|
||||
}
|
||||
|
||||
var result = method.Invoke(null, new object[] { File.ReadAllBytes(path), mode });
|
||||
var result = RuntimeApi.LoadMetadataForAOTAssembly(File.ReadAllBytes(path), HomologousImageMode.SuperSet);
|
||||
Debug.Log($"[TH1.Hotfix] Load AOT metadata {fileName}: {result}");
|
||||
}
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ namespace ExcelConfig
|
||||
|
||||
public override void Init(byte[] data)
|
||||
{
|
||||
Dict = MemoryPackSerializer.Deserialize<Dictionary<int, AIConfig>>(data);
|
||||
Dict = (Dictionary<int, AIConfig>)MemoryPackSerializer.Deserialize(typeof(Dictionary<int, AIConfig>), data)!;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ namespace ExcelConfig
|
||||
|
||||
public override void Init(byte[] data)
|
||||
{
|
||||
Dict = MemoryPackSerializer.Deserialize<Dictionary<int, GeoDesc>>(data);
|
||||
Dict = (Dictionary<int, GeoDesc>)MemoryPackSerializer.Deserialize(typeof(Dictionary<int, GeoDesc>), data)!;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ namespace ExcelConfig
|
||||
|
||||
public override void Init(byte[] data)
|
||||
{
|
||||
Dict = MemoryPackSerializer.Deserialize<Dictionary<int, Moment>>(data);
|
||||
Dict = (Dictionary<int, Moment>)MemoryPackSerializer.Deserialize(typeof(Dictionary<int, Moment>), data)!;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* @Author: 白哉
|
||||
* @Description:
|
||||
* @Date: 2025年04月03日 星期四 11:04:31
|
||||
@ -114,8 +114,8 @@ namespace RuntimeData
|
||||
|
||||
public MapConfig CreateRuntimeCopy()
|
||||
{
|
||||
var bytes = MemoryPackSerializer.Serialize(this);
|
||||
return MemoryPackSerializer.Deserialize<MapConfig>(bytes);
|
||||
var bytes = TH1Serialization.Serialize(this);
|
||||
return TH1Serialization.Deserialize<MapConfig>(bytes);
|
||||
}
|
||||
|
||||
// MemoryPack 反序列化之后的后处理
|
||||
@ -968,7 +968,7 @@ namespace RuntimeData
|
||||
{
|
||||
if (!LobbyManager.Instance.Lobby.IsInLobby()) return;
|
||||
|
||||
byte[] bytes = MemoryPackSerializer.Serialize(this);
|
||||
byte[] bytes = TH1Serialization.Serialize(this);
|
||||
var hash128 = new Hash128();
|
||||
hash128.Append(bytes);
|
||||
var hash = hash128.ToString();
|
||||
@ -2295,7 +2295,7 @@ namespace RuntimeData
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] bytes = MemoryPackSerializer.Serialize(config);
|
||||
byte[] bytes = TH1Serialization.Serialize(config);
|
||||
if (FileTools.SafeWriteFile(path, bytes)) return true;
|
||||
retryCount--;
|
||||
if (retryCount <= 0)
|
||||
@ -2343,7 +2343,7 @@ namespace RuntimeData
|
||||
try
|
||||
{
|
||||
byte[] bytes = File.ReadAllBytes(path);
|
||||
var config = MemoryPackSerializer.Deserialize<MapConfig>(bytes);
|
||||
var config = TH1Serialization.Deserialize<MapConfig>(bytes);
|
||||
|
||||
config.ClearMultiCivs();
|
||||
return config;
|
||||
@ -2376,14 +2376,14 @@ namespace RuntimeData
|
||||
// 新版所有 begin / quick_continue / continue / end 都通过 GameArchiveManager 管理。
|
||||
private static byte[] SerializeMapArchive(MapData map)
|
||||
{
|
||||
var rawBytes = MemoryPackSerializer.Serialize(map);
|
||||
var rawBytes = TH1Serialization.Serialize(map);
|
||||
return NetworkPayloadCodec.Encode(rawBytes);
|
||||
}
|
||||
|
||||
private static MapData DeserializeMapArchive(byte[] bytes)
|
||||
{
|
||||
var rawBytes = NetworkPayloadCodec.DecodeIfNeeded(bytes);
|
||||
return MemoryPackSerializer.Deserialize<MapData>(rawBytes);
|
||||
return TH1Serialization.Deserialize<MapData>(rawBytes);
|
||||
}
|
||||
|
||||
// 给新版 GameArchiveManager 使用的 MapData 存档序列化入口。
|
||||
@ -2961,8 +2961,8 @@ namespace RuntimeData
|
||||
{
|
||||
try
|
||||
{
|
||||
var bytes1 = MemoryPackSerializer.Serialize(obj1);
|
||||
var bytes2 = MemoryPackSerializer.Serialize(obj2);
|
||||
var bytes1 = TH1Serialization.Serialize(obj1);
|
||||
var bytes2 = TH1Serialization.Serialize(obj2);
|
||||
|
||||
return bytes1.SequenceEqual(bytes2);
|
||||
}
|
||||
@ -2977,8 +2977,8 @@ namespace RuntimeData
|
||||
{
|
||||
try
|
||||
{
|
||||
var bytes1 = MemoryPackSerializer.Serialize(obj1);
|
||||
var bytes2 = MemoryPackSerializer.Serialize(obj2);
|
||||
var bytes1 = TH1Serialization.Serialize(obj1);
|
||||
var bytes2 = TH1Serialization.Serialize(obj2);
|
||||
|
||||
if (!bytes1.SequenceEqual(bytes2))
|
||||
{
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* @Author: 白哉
|
||||
* @Description:
|
||||
* @Date: 2025年04月03日 星期四 11:04:31
|
||||
@ -15,6 +15,7 @@ using Logic.CrashSight;
|
||||
using MemoryPack;
|
||||
using TH1_Logic.Core;
|
||||
using TH1_Logic.Net;
|
||||
using TH1_Logic.Tools;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
@ -460,7 +461,7 @@ namespace RuntimeData
|
||||
// mapData.Net.Actions = null;
|
||||
//
|
||||
// _bufferWriter.Clear();
|
||||
// MemoryPackSerializer.Serialize(_bufferWriter, mapData);
|
||||
// TH1Serialization.Serialize(_bufferWriter, mapData);
|
||||
//
|
||||
// mapData.Net.Actions = actions;
|
||||
//
|
||||
@ -478,7 +479,7 @@ namespace RuntimeData
|
||||
try
|
||||
{
|
||||
_bufferWriter.Clear();
|
||||
MemoryPackSerializer.Serialize(_bufferWriter, mapData);
|
||||
TH1Serialization.Serialize(_bufferWriter, mapData);
|
||||
var hash128 = new Hash128();
|
||||
var writtenMemory = _bufferWriter.WrittenMemory;
|
||||
if (MemoryMarshal.TryGetArray(writtenMemory, out ArraySegment<byte> segment) && segment.Array != null)
|
||||
|
||||
@ -15,6 +15,7 @@ using Logic.Pool;
|
||||
using MemoryPack;
|
||||
using RuntimeData;
|
||||
using TH1_Logic.Core;
|
||||
using TH1_Logic.Tools;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
@ -409,7 +410,7 @@ namespace TH1_Logic.AITrain
|
||||
if (_actionLogicIdData != null) return;
|
||||
TextAsset asset = TH1Resource.ResourceLoader.Load<TextAsset>($"CommonIdData/CommonIdData");
|
||||
var data = asset?.bytes ?? Array.Empty<byte>();
|
||||
_actionLogicIdData = MemoryPackSerializer.Deserialize<ActionLogicIdData>(data) ?? new ActionLogicIdData();
|
||||
_actionLogicIdData = TH1Serialization.Deserialize<ActionLogicIdData>(data) ?? new ActionLogicIdData();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* @Author: 白哉
|
||||
* @Description: 行为逻辑类
|
||||
* @Date: 2025年04月10日 星期四 11:04:44
|
||||
@ -27,6 +27,7 @@ using TH1_Presentation.Sequencer.Task;
|
||||
using TH1_Renderer;
|
||||
using TH1_Logic.Net;
|
||||
using TH1_Logic.Steam;
|
||||
using TH1_Logic.Tools;
|
||||
using UnityEngine;
|
||||
using TH1Renderer;
|
||||
|
||||
@ -1831,8 +1832,8 @@ namespace Logic.Action
|
||||
#if CHECK_ACTIONDEFFERENCE
|
||||
if (actionParams.MapData == Main.MapData)
|
||||
{
|
||||
byte[] bt = MemoryPack.MemoryPackSerializer.Serialize(Main.MapData);
|
||||
Main.Instance.CheckMapData = MemoryPack.MemoryPackSerializer.Deserialize<MapData>(bt);
|
||||
byte[] bt = TH1Serialization.Serialize(Main.MapData);
|
||||
Main.Instance.CheckMapData = TH1Serialization.Deserialize<MapData>(bt);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Logic.CrashSight;
|
||||
using MemoryPack;
|
||||
using TH1_Logic.Tools;
|
||||
using UnityEngine;
|
||||
using Vector2 = System.Numerics.Vector2;
|
||||
|
||||
@ -123,7 +124,7 @@ namespace TH1_Logic.Comic
|
||||
return null;
|
||||
}
|
||||
|
||||
ComicAsset comicConfig = MemoryPackSerializer.Deserialize<ComicAsset>(textAsset.bytes);
|
||||
ComicAsset comicConfig = TH1Serialization.Deserialize<ComicAsset>(textAsset.bytes);
|
||||
LogSystem.LogInfo($"LoadComicAsset: 加载成功");
|
||||
return comicConfig;
|
||||
}
|
||||
@ -146,7 +147,7 @@ namespace TH1_Logic.Comic
|
||||
return null;
|
||||
}
|
||||
|
||||
ImageMapData imageMap = MemoryPackSerializer.Deserialize<ImageMapData>(textAsset.bytes);
|
||||
ImageMapData imageMap = TH1Serialization.Deserialize<ImageMapData>(textAsset.bytes);
|
||||
LogSystem.LogInfo($"LoadImageMap: 加载成功");
|
||||
return imageMap;
|
||||
}
|
||||
@ -168,7 +169,7 @@ namespace TH1_Logic.Comic
|
||||
if (!Directory.Exists(folderPath)) Directory.CreateDirectory(folderPath);
|
||||
|
||||
string filePath = Path.Combine(folderPath, $"ImageMap.bytes");
|
||||
byte[] bytes = MemoryPackSerializer.Serialize(_imageMap);
|
||||
byte[] bytes = TH1Serialization.Serialize(_imageMap);
|
||||
File.WriteAllBytes(filePath, bytes);
|
||||
|
||||
// 刷新 AssetDatabase
|
||||
@ -193,7 +194,7 @@ namespace TH1_Logic.Comic
|
||||
if (!Directory.Exists(folderPath)) Directory.CreateDirectory(folderPath);
|
||||
|
||||
string filePath = Path.Combine(folderPath, $"ComicAsset.bytes");
|
||||
byte[] bytes = MemoryPackSerializer.Serialize(_asset);
|
||||
byte[] bytes = TH1Serialization.Serialize(_asset);
|
||||
File.WriteAllBytes(filePath, bytes);
|
||||
|
||||
// 刷新 AssetDatabase
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* @Author: 白哉
|
||||
* @Description: 游戏入口
|
||||
* @Date: 2025年04月01日 星期二 11:04:16
|
||||
@ -27,6 +27,7 @@ using TH1_Logic.MatchConfig;
|
||||
using TH1_Logic.Net;
|
||||
using TH1_Logic.Oss;
|
||||
using TH1_Logic.Steam;
|
||||
using TH1_Logic.Tools;
|
||||
using TH1_UI.Controller.Interaction;
|
||||
using TH1Renderer;
|
||||
using TH1Resource;
|
||||
@ -284,8 +285,8 @@ namespace TH1_Logic.Core
|
||||
GameArchiveManager.Instance.SaveBeginArchive(MapData);
|
||||
|
||||
#if CHECK_ACTIONDEFFERENCE
|
||||
byte[] bt = MemoryPack.MemoryPackSerializer.Serialize(Main.MapData);
|
||||
Main.Instance.CheckMapData = MemoryPack.MemoryPackSerializer.Deserialize<MapData>(bt);
|
||||
byte[] bt = TH1Serialization.Serialize(Main.MapData);
|
||||
Main.Instance.CheckMapData = TH1Serialization.Deserialize<MapData>(bt);
|
||||
#endif
|
||||
MapData.RefreshTurn();
|
||||
}
|
||||
|
||||
377
Unity/Assets/Scripts/TH1_Logic/Editor/TH1MigrationCommandLine.cs
Normal file
377
Unity/Assets/Scripts/TH1_Logic/Editor/TH1MigrationCommandLine.cs
Normal file
@ -0,0 +1,377 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using TH1_Logic.Editor.HybridCLR;
|
||||
using TH1_Logic.Editor.YooAssetTools;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Build;
|
||||
using UnityEditor.Build.Reporting;
|
||||
using UnityEngine;
|
||||
using DiagnosticsProcess = System.Diagnostics.Process;
|
||||
using DiagnosticsProcessStartInfo = System.Diagnostics.ProcessStartInfo;
|
||||
|
||||
namespace TH1_Logic.Editor
|
||||
{
|
||||
public static class TH1MigrationCommandLine
|
||||
{
|
||||
private const string BuildDirArg = "-th1SmokeBuildDir";
|
||||
private const string DefaultBuildSubDirectory = "TH1/CodexSmoke";
|
||||
private const string ExeName = "TOHOTOPIA.exe";
|
||||
|
||||
[MenuItem("Tools/TH1/iOS Migration/Command Line/Prepare And Build Windows Smoke")]
|
||||
public static void PrepareAndBuildWindowsSmoke()
|
||||
{
|
||||
RunBatchAction(() =>
|
||||
{
|
||||
ConfigureWindowsIl2CppSmokeSettings();
|
||||
PrepareCurrentPlatform(true);
|
||||
|
||||
var exePath = BuildWindowsSmokePlayer();
|
||||
Debug.Log($"[TH1.Migration.CLI] Windows smoke build OK: {exePath}");
|
||||
});
|
||||
}
|
||||
|
||||
[MenuItem("Tools/TH1/iOS Migration/Command Line/Prepare Current Platform")]
|
||||
public static void PrepareCurrentPlatformMenu()
|
||||
{
|
||||
RunBatchAction(() => PrepareCurrentPlatform(true));
|
||||
}
|
||||
|
||||
public static void PrepareCurrentPlatform(bool developmentBuild)
|
||||
{
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
TH1HybridCLRBuildTools.ConfigureHotfixSettings();
|
||||
TH1YooAssetBuildTools.ConfigureDefaultPackageCollector();
|
||||
TH1HybridCLRBuildTools.GenerateAll();
|
||||
|
||||
if (!TH1HybridCLRBuildTools.BuildAndCopyHotfixArtifacts(developmentBuild))
|
||||
{
|
||||
throw new BuildFailedException("[TH1.Migration.CLI] Build hotfix dll failed.");
|
||||
}
|
||||
|
||||
TH1YooAssetBuildTools.BuildBuiltinDefaultPackage();
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
var blockers = TH1MigrationBuildStatus.GetBuildBlockingMessages(EditorUserBuildSettings.activeBuildTarget);
|
||||
if (blockers.Count > 0)
|
||||
{
|
||||
throw new BuildFailedException(
|
||||
"[TH1.Migration.CLI] Build preparation still has blocking errors:\n" +
|
||||
string.Join("\n", blockers));
|
||||
}
|
||||
|
||||
Debug.Log("[TH1.Migration.CLI] Prepare current platform OK.");
|
||||
}
|
||||
|
||||
private static void ConfigureWindowsIl2CppSmokeSettings()
|
||||
{
|
||||
const BuildTargetGroup group = BuildTargetGroup.Standalone;
|
||||
const BuildTarget target = BuildTarget.StandaloneWindows64;
|
||||
|
||||
if (EditorUserBuildSettings.activeBuildTarget != target)
|
||||
{
|
||||
EditorUserBuildSettings.SwitchActiveBuildTarget(group, target);
|
||||
}
|
||||
|
||||
PlayerSettings.SetScriptingBackend(group, ScriptingImplementation.IL2CPP);
|
||||
EditorUserBuildSettings.development = true;
|
||||
EditorUserBuildSettings.allowDebugging = false;
|
||||
PlayerSettings.usePlayerLog = true;
|
||||
PlayerSettings.SetStackTraceLogType(LogType.Log, StackTraceLogType.ScriptOnly);
|
||||
PlayerSettings.SetStackTraceLogType(LogType.Warning, StackTraceLogType.ScriptOnly);
|
||||
PlayerSettings.SetStackTraceLogType(LogType.Error, StackTraceLogType.ScriptOnly);
|
||||
PlayerSettings.SetStackTraceLogType(LogType.Assert, StackTraceLogType.ScriptOnly);
|
||||
PlayerSettings.SetStackTraceLogType(LogType.Exception, StackTraceLogType.ScriptOnly);
|
||||
|
||||
Debug.Log("[TH1.Migration.CLI] Configured Windows IL2CPP smoke build settings.");
|
||||
}
|
||||
|
||||
private static string BuildWindowsSmokePlayer()
|
||||
{
|
||||
var outputRoot = GetSmokeBuildDirectory();
|
||||
CleanSmokeBuildDirectory(outputRoot);
|
||||
|
||||
var outputExe = Path.Combine(outputRoot, ExeName);
|
||||
var scenes = EditorBuildSettings.scenes
|
||||
.Where(scene => scene.enabled)
|
||||
.Select(scene => scene.path)
|
||||
.ToArray();
|
||||
|
||||
if (scenes.Length == 0)
|
||||
{
|
||||
throw new BuildFailedException("[TH1.Migration.CLI] No enabled scenes in EditorBuildSettings.");
|
||||
}
|
||||
|
||||
var options = new BuildPlayerOptions
|
||||
{
|
||||
scenes = scenes,
|
||||
locationPathName = outputExe,
|
||||
target = BuildTarget.StandaloneWindows64,
|
||||
targetGroup = BuildTargetGroup.Standalone,
|
||||
options = BuildOptions.Development
|
||||
};
|
||||
|
||||
var report = BuildPipeline.BuildPlayer(options);
|
||||
var summary = report.summary;
|
||||
if (summary.result != BuildResult.Succeeded)
|
||||
{
|
||||
throw new BuildFailedException(
|
||||
$"[TH1.Migration.CLI] Build failed: {summary.result}, errors={summary.totalErrors}, warnings={summary.totalWarnings}");
|
||||
}
|
||||
|
||||
var playerExe = FindPlayerExecutable(outputRoot, outputExe);
|
||||
if (string.IsNullOrEmpty(playerExe))
|
||||
{
|
||||
BuildExportedVisualStudioSolution(outputRoot);
|
||||
playerExe = FindPlayerExecutable(outputRoot, outputExe);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(playerExe))
|
||||
{
|
||||
throw new BuildFailedException(
|
||||
$"[TH1.Migration.CLI] Build succeeded but no runnable player exe was found under {outputRoot}.");
|
||||
}
|
||||
|
||||
return playerExe;
|
||||
}
|
||||
|
||||
private static string GetSmokeBuildDirectory()
|
||||
{
|
||||
var argValue = GetCommandLineValue(BuildDirArg);
|
||||
if (!string.IsNullOrEmpty(argValue))
|
||||
{
|
||||
return Path.GetFullPath(argValue);
|
||||
}
|
||||
|
||||
return Path.GetFullPath(Path.Combine(GetProjectRoot(), DefaultBuildSubDirectory));
|
||||
}
|
||||
|
||||
private static string FindPlayerExecutable(string outputRoot, string expectedExe)
|
||||
{
|
||||
if (File.Exists(expectedExe)) return expectedExe;
|
||||
if (!Directory.Exists(outputRoot)) return string.Empty;
|
||||
|
||||
var exeFiles = Directory.GetFiles(outputRoot, "*.exe", SearchOption.AllDirectories)
|
||||
.Where(path =>
|
||||
{
|
||||
if (path.IndexOf("Il2CppOutputProject", StringComparison.OrdinalIgnoreCase) >= 0) return false;
|
||||
var fileName = Path.GetFileName(path);
|
||||
if (fileName.IndexOf("CrashHandler", StringComparison.OrdinalIgnoreCase) >= 0) return false;
|
||||
if (fileName.Equals("il2cpp.exe", StringComparison.OrdinalIgnoreCase)) return false;
|
||||
if (fileName.Equals("UnityLinker.exe", StringComparison.OrdinalIgnoreCase)) return false;
|
||||
if (fileName.Equals("bee_backend.exe", StringComparison.OrdinalIgnoreCase)) return false;
|
||||
if (fileName.Equals("Analytics.exe", StringComparison.OrdinalIgnoreCase)) return false;
|
||||
if (fileName.Equals("createdump.exe", StringComparison.OrdinalIgnoreCase)) return false;
|
||||
return true;
|
||||
})
|
||||
.OrderBy(path => path.Length)
|
||||
.ToArray();
|
||||
|
||||
return exeFiles.FirstOrDefault() ?? string.Empty;
|
||||
}
|
||||
|
||||
private static void BuildExportedVisualStudioSolution(string outputRoot)
|
||||
{
|
||||
var solutionPath = Directory.GetFiles(outputRoot, "*.sln", SearchOption.TopDirectoryOnly)
|
||||
.OrderBy(path => path.Length)
|
||||
.FirstOrDefault();
|
||||
if (string.IsNullOrEmpty(solutionPath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var msBuildPath = FindMSBuildPath();
|
||||
if (string.IsNullOrEmpty(msBuildPath))
|
||||
{
|
||||
throw new BuildFailedException(
|
||||
$"[TH1.Migration.CLI] Unity exported a Visual Studio solution but MSBuild was not found: {solutionPath}");
|
||||
}
|
||||
|
||||
Debug.Log($"[TH1.Migration.CLI] Unity exported Visual Studio solution, building it with MSBuild: {solutionPath}");
|
||||
var windowsSdkVersion = FindLatestWindowsSdkVersion();
|
||||
var platformToolset = FindLatestPlatformToolset(msBuildPath);
|
||||
var retargetArgs = string.Empty;
|
||||
if (!string.IsNullOrEmpty(windowsSdkVersion))
|
||||
{
|
||||
retargetArgs += $" /p:WindowsTargetPlatformVersion={windowsSdkVersion}";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(platformToolset))
|
||||
{
|
||||
retargetArgs += $" /p:PlatformToolset={platformToolset}";
|
||||
}
|
||||
|
||||
RunProcess(
|
||||
msBuildPath,
|
||||
$"\"{solutionPath}\" /m /p:Configuration=Debug /p:Platform=x64{retargetArgs} /verbosity:minimal",
|
||||
outputRoot);
|
||||
}
|
||||
|
||||
private static string FindMSBuildPath()
|
||||
{
|
||||
var programFilesX86 = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);
|
||||
var vsWherePath = Path.Combine(programFilesX86, "Microsoft Visual Studio", "Installer", "vswhere.exe");
|
||||
if (File.Exists(vsWherePath))
|
||||
{
|
||||
var output = RunProcess(vsWherePath, "-latest -products * -requires Microsoft.Component.MSBuild -find MSBuild\\**\\Bin\\MSBuild.exe", GetProjectRoot(), false);
|
||||
var path = output
|
||||
.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
|
||||
.FirstOrDefault(File.Exists);
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
var programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
|
||||
var candidates = new[]
|
||||
{
|
||||
Path.Combine(programFiles, "Microsoft Visual Studio", "2022", "Community", "MSBuild", "Current", "Bin", "MSBuild.exe"),
|
||||
Path.Combine(programFiles, "Microsoft Visual Studio", "2022", "Professional", "MSBuild", "Current", "Bin", "MSBuild.exe"),
|
||||
Path.Combine(programFiles, "Microsoft Visual Studio", "2022", "Enterprise", "MSBuild", "Current", "Bin", "MSBuild.exe"),
|
||||
Path.Combine(programFilesX86, "Microsoft Visual Studio", "2022", "BuildTools", "MSBuild", "Current", "Bin", "MSBuild.exe")
|
||||
};
|
||||
|
||||
return candidates.FirstOrDefault(File.Exists) ?? string.Empty;
|
||||
}
|
||||
|
||||
private static string FindLatestWindowsSdkVersion()
|
||||
{
|
||||
var programFilesX86 = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);
|
||||
var sdkLibRoot = Path.Combine(programFilesX86, "Windows Kits", "10", "Lib");
|
||||
if (!Directory.Exists(sdkLibRoot))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return Directory.GetDirectories(sdkLibRoot)
|
||||
.Select(Path.GetFileName)
|
||||
.Where(name => Version.TryParse(name?.TrimEnd('.'), out _))
|
||||
.OrderByDescending(name => Version.Parse(name.TrimEnd('.')))
|
||||
.FirstOrDefault() ?? string.Empty;
|
||||
}
|
||||
|
||||
private static string FindLatestPlatformToolset(string msBuildPath)
|
||||
{
|
||||
var current = new FileInfo(msBuildPath).Directory;
|
||||
while (current != null)
|
||||
{
|
||||
var toolsetRoot = Path.Combine(current.FullName, "Microsoft", "VC", "v170", "Platforms", "x64", "PlatformToolsets");
|
||||
if (Directory.Exists(toolsetRoot))
|
||||
{
|
||||
return Directory.GetDirectories(toolsetRoot)
|
||||
.Select(Path.GetFileName)
|
||||
.Where(name => name != null && name.StartsWith("v", StringComparison.OrdinalIgnoreCase))
|
||||
.OrderByDescending(name => name)
|
||||
.FirstOrDefault() ?? string.Empty;
|
||||
}
|
||||
|
||||
current = current.Parent;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private static string RunProcess(string fileName, string arguments, string workingDirectory, bool throwOnError = true)
|
||||
{
|
||||
var process = new DiagnosticsProcess
|
||||
{
|
||||
StartInfo = new DiagnosticsProcessStartInfo
|
||||
{
|
||||
FileName = fileName,
|
||||
Arguments = arguments,
|
||||
WorkingDirectory = workingDirectory,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true
|
||||
}
|
||||
};
|
||||
|
||||
process.Start();
|
||||
var output = process.StandardOutput.ReadToEnd();
|
||||
var error = process.StandardError.ReadToEnd();
|
||||
process.WaitForExit();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(output))
|
||||
{
|
||||
Debug.Log(output);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(error))
|
||||
{
|
||||
Debug.LogWarning(error);
|
||||
}
|
||||
|
||||
if (throwOnError && process.ExitCode != 0)
|
||||
{
|
||||
throw new BuildFailedException(
|
||||
$"[TH1.Migration.CLI] Process failed ({process.ExitCode}): {fileName} {arguments}\n{output}\n{error}");
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private static string GetCommandLineValue(string name)
|
||||
{
|
||||
var args = Environment.GetCommandLineArgs();
|
||||
for (var i = 0; i < args.Length - 1; i++)
|
||||
{
|
||||
if (string.Equals(args[i], name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return args[i + 1];
|
||||
}
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private static string GetProjectRoot()
|
||||
{
|
||||
return Directory.GetParent(Application.dataPath)?.FullName ?? Application.dataPath;
|
||||
}
|
||||
|
||||
private static void CleanSmokeBuildDirectory(string outputRoot)
|
||||
{
|
||||
var fullOutputRoot = Path.GetFullPath(outputRoot);
|
||||
var defaultSafeRoot = Path.GetFullPath(Path.Combine(GetProjectRoot(), "TH1"));
|
||||
if (!fullOutputRoot.StartsWith(defaultSafeRoot, StringComparison.OrdinalIgnoreCase) &&
|
||||
string.IsNullOrEmpty(GetCommandLineValue(BuildDirArg)))
|
||||
{
|
||||
throw new BuildFailedException($"[TH1.Migration.CLI] Refuse to clean unexpected smoke build dir: {fullOutputRoot}");
|
||||
}
|
||||
|
||||
if (Directory.Exists(fullOutputRoot))
|
||||
{
|
||||
Directory.Delete(fullOutputRoot, true);
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(fullOutputRoot);
|
||||
}
|
||||
|
||||
private static void RunBatchAction(System.Action action)
|
||||
{
|
||||
try
|
||||
{
|
||||
action();
|
||||
if (Application.isBatchMode)
|
||||
{
|
||||
EditorApplication.Exit(0);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"[TH1.Migration.CLI] Failed:\n{e}");
|
||||
if (Application.isBatchMode)
|
||||
{
|
||||
EditorApplication.Exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3ef088115a5f4492b90b43c79291c551
|
||||
timeCreated: 1781111040
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* @Author: 白哉
|
||||
* @Description: 游戏记录管理
|
||||
* @Date: 2025年05月22日 星期四 11:05:24
|
||||
@ -237,7 +237,7 @@ namespace RuntimeData
|
||||
// 统一保存 GameRecordData,避免 Add/Remove/Upsert 到处重复序列化逻辑。
|
||||
private void SaveGameRecordData()
|
||||
{
|
||||
byte[] bytes = MemoryPackSerializer.Serialize(_gameRecord);
|
||||
byte[] bytes = TH1Serialization.Serialize(_gameRecord);
|
||||
FileTools.SafeWriteFile(Application.persistentDataPath + "/../Config/game_record.dat", bytes);
|
||||
}
|
||||
|
||||
@ -262,7 +262,7 @@ namespace RuntimeData
|
||||
LogSystem.LogInfo("[GameRecord] 从备份恢复成功");
|
||||
try
|
||||
{
|
||||
byte[] bytes = MemoryPackSerializer.Serialize(_gameRecord);
|
||||
byte[] bytes = TH1Serialization.Serialize(_gameRecord);
|
||||
FileTools.SafeWriteFile(path, bytes);
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* @Author: 白哉
|
||||
* @Description:
|
||||
* @Date: 2025年09月05日 星期五 15:09:36
|
||||
@ -90,7 +90,7 @@ namespace Logic
|
||||
LogSystem.LogInfo("[InputConfig] 从备份恢复成功");
|
||||
try
|
||||
{
|
||||
byte[] bytes = MemoryPackSerializer.Serialize(_config);
|
||||
byte[] bytes = TH1Serialization.Serialize(_config);
|
||||
FileTools.SafeWriteFile(path, bytes);
|
||||
}
|
||||
catch (System.Exception e)
|
||||
@ -111,7 +111,7 @@ namespace Logic
|
||||
public void SaveInputConfig()
|
||||
{
|
||||
if (_config == null) return;
|
||||
byte[] bytes = MemoryPackSerializer.Serialize(_config);
|
||||
byte[] bytes = TH1Serialization.Serialize(_config);
|
||||
FileTools.SafeWriteFile(Application.persistentDataPath + "/../Config/input_config.dat", bytes);
|
||||
}
|
||||
|
||||
|
||||
@ -12,6 +12,7 @@ using Logic.CrashSight;
|
||||
using MemoryPack;
|
||||
using RuntimeData;
|
||||
using TH1_Logic.MatchConfig;
|
||||
using TH1_Logic.Tools;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
@ -49,7 +50,7 @@ namespace Logic
|
||||
|
||||
string filePath = Path.Combine(folderPath, $"{name}.bytes");
|
||||
var record = new MapRecordData(map, name);
|
||||
byte[] bytes = MemoryPackSerializer.Serialize(record);
|
||||
byte[] bytes = TH1Serialization.Serialize(record);
|
||||
File.WriteAllBytes(filePath, bytes);
|
||||
|
||||
// 刷新 AssetDatabase
|
||||
@ -81,7 +82,7 @@ namespace Logic
|
||||
return null;
|
||||
}
|
||||
|
||||
MapRecordData map = MemoryPackSerializer.Deserialize<MapRecordData>(textAsset.bytes);
|
||||
MapRecordData map = TH1Serialization.Deserialize<MapRecordData>(textAsset.bytes);
|
||||
LogSystem.LogInfo($"LoadMapRecord: 地图 {name} 加载成功");
|
||||
return map;
|
||||
}
|
||||
@ -92,4 +93,4 @@ namespace Logic
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ using System.IO;
|
||||
using Logic.CrashSight;
|
||||
using MemoryPack;
|
||||
using RuntimeData;
|
||||
using TH1_Logic.Tools;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
@ -59,7 +60,7 @@ namespace TH1_Logic.MatchConfig
|
||||
return null;
|
||||
}
|
||||
|
||||
MatchLevelData matchConfig = MemoryPackSerializer.Deserialize<MatchLevelData>(textAsset.bytes);
|
||||
MatchLevelData matchConfig = TH1Serialization.Deserialize<MatchLevelData>(textAsset.bytes);
|
||||
LogSystem.LogInfo($"LoadMatchLevelData: 关卡配置加载成功");
|
||||
return matchConfig;
|
||||
}
|
||||
@ -89,7 +90,7 @@ namespace TH1_Logic.MatchConfig
|
||||
if (!Directory.Exists(folderPath)) Directory.CreateDirectory(folderPath);
|
||||
|
||||
string filePath = Path.Combine(folderPath, $"LevelData.bytes");
|
||||
byte[] bytes = MemoryPackSerializer.Serialize(LevelData);
|
||||
byte[] bytes = TH1Serialization.Serialize(LevelData);
|
||||
File.WriteAllBytes(filePath, bytes);
|
||||
|
||||
// 刷新 AssetDatabase
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Logic.CrashSight;
|
||||
using MemoryPack;
|
||||
@ -9,6 +9,7 @@ using TH1_Logic.Config;
|
||||
using TH1_Logic.Core;
|
||||
using TH1_Logic.GameArchive;
|
||||
using TH1_Logic.Net;
|
||||
using TH1_Logic.Tools;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TH1_Logic.Oss
|
||||
@ -55,7 +56,7 @@ namespace TH1_Logic.Oss
|
||||
ossData.Actions = endMap.Net.Actions;
|
||||
ossData.CollectData = CollectManager.Instance.CollectData;
|
||||
ossData.CollectData.MemberId = LobbyManager.Instance.Lobby.GetSelfMemberId();
|
||||
byte[] bytes = MemoryPackSerializer.Serialize(ossData);
|
||||
byte[] bytes = TH1Serialization.Serialize(ossData);
|
||||
_ = UploadGameDataAsync(steamId, bytes);
|
||||
}
|
||||
|
||||
@ -110,7 +111,7 @@ namespace TH1_Logic.Oss
|
||||
LogSystem.LogInfo($"Collect STS token obtained, expires at {_collectCredentialsExpireTime}");
|
||||
}
|
||||
|
||||
byte[] data = MemoryPackSerializer.Serialize(collectData);
|
||||
byte[] data = TH1Serialization.Serialize(collectData);
|
||||
var result = await _uploadService.UploadFileAsync(_cachedCollectCredentials, data);
|
||||
if (result)
|
||||
{
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
using Logic;
|
||||
using Logic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@ -12,6 +12,7 @@ using TH1_Core.Managers;
|
||||
using TH1_Logic.Config;
|
||||
using TH1_Logic.Core;
|
||||
using TH1_Logic.Net;
|
||||
using TH1_Logic.Tools;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TH1_Logic.Steam
|
||||
@ -25,7 +26,7 @@ namespace TH1_Logic.Steam
|
||||
{
|
||||
try
|
||||
{
|
||||
var message = MemoryPack.MemoryPackSerializer.Deserialize<BaseMessage>(data);
|
||||
var message = TH1Serialization.Deserialize<BaseMessage>(data);
|
||||
if (message == null) return;
|
||||
if (message.MessageType == P2PMsgType.NetworkStress) return;
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* @Author: 白哉
|
||||
* @Description:
|
||||
* @Date: 2025年09月08日 星期一 17:09:18
|
||||
@ -17,6 +17,7 @@ using TH1_Logic.Chat;
|
||||
using TH1_Logic.Config;
|
||||
using TH1_Logic.Core;
|
||||
using TH1_Logic.Net;
|
||||
using TH1_Logic.Tools;
|
||||
|
||||
|
||||
namespace TH1_Logic.Steam
|
||||
@ -67,7 +68,7 @@ namespace TH1_Logic.Steam
|
||||
LobbyVersion = lobbyInfo.Version,
|
||||
};
|
||||
|
||||
byte[] messageBytes = NetworkPayloadCodec.Encode(MemoryPackSerializer.Serialize<BaseMessage>(data));
|
||||
byte[] messageBytes = NetworkPayloadCodec.Encode(TH1Serialization.Serialize<BaseMessage>(data));
|
||||
if (SimpleP2P.Instance.SendToWithOutConnect(targetId, messageBytes)) return true;
|
||||
|
||||
LogSystem.LogError($"InviteVersionMismatchMessage: 发送给房主失败 owner={lobbyInfo.OwnerId}, lobby={lobbyInfo.LobbyId}");
|
||||
@ -97,7 +98,7 @@ namespace TH1_Logic.Steam
|
||||
|
||||
private static byte[] SerializeForNetwork(BaseMessage message)
|
||||
{
|
||||
var rawBytes = MemoryPack.MemoryPackSerializer.Serialize<BaseMessage>(message);
|
||||
var rawBytes = TH1Serialization.Serialize<BaseMessage>(message);
|
||||
return NetworkPayloadCodec.Encode(rawBytes);
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@ -17,6 +17,7 @@ using TH1_Logic.Chat;
|
||||
using TH1_Logic.Config;
|
||||
using TH1_Logic.Core;
|
||||
using TH1_Logic.Net;
|
||||
using TH1_Logic.Tools;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
@ -1036,7 +1037,7 @@ namespace TH1_Logic.Steam
|
||||
};
|
||||
var data = new InviteMessage();
|
||||
data.LobbyInfo = lobbyInfo;
|
||||
byte[] bytes = MemoryPackSerializer.Serialize<BaseMessage>(data);
|
||||
byte[] bytes = TH1Serialization.Serialize<BaseMessage>(data);
|
||||
// 优先从缓存获取,否则直接构造 CSteamID
|
||||
var targetId = _onlineFriendsId.TryGetValue(targetSteamId, out var cachedId) ? cachedId : new CSteamID(targetSteamId);
|
||||
|
||||
@ -1103,7 +1104,7 @@ namespace TH1_Logic.Steam
|
||||
ReporterId = selfId,
|
||||
Version = ConfigManager.Instance.VersionCfg.CurVersionInfo.Version,
|
||||
};
|
||||
var bytes = MemoryPackSerializer.Serialize<BaseMessage>(data);
|
||||
var bytes = TH1Serialization.Serialize<BaseMessage>(data);
|
||||
if (!SimpleP2P.Instance.SendToWithOutConnect(targetId, bytes))
|
||||
{
|
||||
LogSystem.LogError($"Report lobby failed: send to owner failed, lobby={lobbyInfo.LobbyId}, owner={lobbyInfo.OwnerId}");
|
||||
|
||||
@ -9,7 +9,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Logic.CrashSight;
|
||||
using MemoryPack;
|
||||
|
||||
|
||||
namespace TH1_Logic.Tools
|
||||
@ -29,7 +28,7 @@ namespace TH1_Logic.Tools
|
||||
return null;
|
||||
}
|
||||
|
||||
var data = MemoryPackSerializer.Deserialize<T>(bytes);
|
||||
var data = TH1Serialization.Deserialize<T>(bytes);
|
||||
if (data == null)
|
||||
{
|
||||
LogSystem.LogError($"反序列化结果无效: {path}");
|
||||
@ -101,4 +100,4 @@ namespace TH1_Logic.Tools
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
48
Unity/Assets/Scripts/TH1_Logic/Tools/TH1Serialization.cs
Normal file
48
Unity/Assets/Scripts/TH1_Logic/Tools/TH1Serialization.cs
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* @Author: Codex
|
||||
* @Description: AOT-safe MemoryPack entrypoints for hotfix types
|
||||
* @Date: 2026年06月11日 星期四 00:00:00
|
||||
* @Modify:
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using MemoryPack;
|
||||
|
||||
|
||||
namespace TH1_Logic.Tools
|
||||
{
|
||||
public static class TH1Serialization
|
||||
{
|
||||
public static byte[] Serialize<T>(T value)
|
||||
{
|
||||
return MemoryPackSerializer.Serialize(typeof(T), value);
|
||||
}
|
||||
|
||||
public static byte[] Serialize(Type type, object value)
|
||||
{
|
||||
if (type == null) throw new ArgumentNullException(nameof(type));
|
||||
return MemoryPackSerializer.Serialize(type, value);
|
||||
}
|
||||
|
||||
public static void Serialize<T>(IBufferWriter<byte> writer, T value)
|
||||
{
|
||||
if (writer == null) throw new ArgumentNullException(nameof(writer));
|
||||
MemoryPackSerializer.Serialize(typeof(T), writer, value);
|
||||
}
|
||||
|
||||
public static T Deserialize<T>(byte[] bytes)
|
||||
{
|
||||
if (bytes == null) throw new ArgumentNullException(nameof(bytes));
|
||||
object value = MemoryPackSerializer.Deserialize(typeof(T), bytes);
|
||||
return value is T data ? data : default;
|
||||
}
|
||||
|
||||
public static object Deserialize(Type type, byte[] bytes)
|
||||
{
|
||||
if (type == null) throw new ArgumentNullException(nameof(type));
|
||||
if (bytes == null) throw new ArgumentNullException(nameof(bytes));
|
||||
return MemoryPackSerializer.Deserialize(type, bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8f579489cbe74efc80aab7da3c1aa1f3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Loading…
x
Reference in New Issue
Block a user