Files
test/Assets/PerfectWorld/Scripts/Task/TaskTemplContainerSO.cs
2026-02-28 18:34:39 +07:00

158 lines
5.3 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Serialization;
namespace BrewMonster.Scripts.Task
{
[ CreateAssetMenu(fileName = "TaskTemplContainerSO", menuName = "BrewMonster/Task/TaskTemplContainerSO")]
public class TaskTemplContainerSO : ScriptableObject
{
public const ulong TASK_PACK_MAGIC = 0x93858361;
public const ulong _task_templ_cur_version = 121;
[SerializeField] private bool _loadAllTasksFromSo = false;
[HideInInspector] [SerializeField] private List<uint> _topTaskTemplIds = new ();
[HideInInspector] [SerializeField] private List<ATaskTempl> _allTaskTemplates = new List<ATaskTempl>();
[Header("DEBUG")]
[SerializeField] private int _taskDemoIndex = 100;
// /*[SerializeField]*/ private ATaskTempl _taskDemo ;
private Dictionary<uint, ATaskTempl> _allTaskTemplMap = new Dictionary<uint, ATaskTempl>();
public List<ATaskTempl> TopTaskTemplates { get; } = new List<ATaskTempl>();
public int TaskLoadedCount;
public bool LoadAllTasksFromSO => _loadAllTasksFromSo;
private void OnValidate()
{
TaskLoadedCount = _topTaskTemplIds == null ? 0 : _topTaskTemplIds.Count;
// if (TaskLoadedCount > _taskDemoIndex)
// {
// _taskDemo = _topTaskTemplates[_taskDemoIndex];
// }
}
public ATaskTempl GetTaskTemplate(uint id)
{
return _allTaskTemplMap.ContainsKey(id) ? _allTaskTemplMap[id] : null;
}
// call when start load data from SO to runtime-memory
public void BuildTaskTemplateMap()
{
_allTaskTemplMap.Clear();
TopTaskTemplates.Clear();
// build all-task map
foreach (var templ in _allTaskTemplates)
{
if (!_allTaskTemplMap.ContainsKey(templ.m_ID))
{
_allTaskTemplMap.Add(templ.m_ID, templ);
}
}
// build top-task list
foreach (var topId in _topTaskTemplIds)
{
if (_allTaskTemplMap.ContainsKey((uint)topId))
{
TopTaskTemplates.Add(_allTaskTemplMap[(uint)topId]);
}
}
Debug.Log($"[TaskTemplContainerSO] Built task template map with {_allTaskTemplMap.Count} entries.");
}
[ContextMenu(" Load All Tasks From Pack")]
public void LoadAllTasksFromPack()
{
string task_data_path = Path.Combine(Application.streamingAssetsPath, "data/tasks.data");
_topTaskTemplIds = LoadTasksFromPack(task_data_path);
Debug.Log($"[TaskTemplContainerSO] Loaded {_topTaskTemplIds.Count} task templates from pack.");
}
[ContextMenu(" Clear All Loaded Tasks")]
public void ClearDatas()
{
_topTaskTemplIds.Clear();
_allTaskTemplates.Clear();
_allTaskTemplMap.Clear();
Debug.Log($"[TaskTemplContainerSO] Cleared all loaded task templates.");
}
private List<uint> LoadTasksFromPack(string szPackPath)
{
long readBytes = 0;
// var tasks = new List<ATaskTempl>();
var taskIds = new List<uint>();
using (var fs = new FileStream(
szPackPath,
FileMode.Open,
FileAccess.Read,
FileShare.Read))
{
TASK_PACK_HEADER tph =
AAssit.ReadFromBinaryOf<TASK_PACK_HEADER>(fs, ref readBytes);
if (tph.magic != TASK_PACK_MAGIC ||
tph.version != _task_templ_cur_version)
throw new Exception("Invalid task pack header");
if (tph.item_count == 0)
return taskIds;
uint[] pOffs =
AAssit.ReadArrayFromBinary<uint>(fs, (int)tph.item_count, ref readBytes);
for (int i = 0; i < tph.item_count; i++)
{
fs.Seek(pOffs[i], SeekOrigin.Begin);
ATaskTempl templ = new ATaskTempl();
if (!templ.LoadFromBinFile(fs))
continue;
taskIds.Add(templ.m_ID);
RecursiveToSyncSerializableData(templ);
}
fs.Seek(0, SeekOrigin.Begin);
fs.Close();
}
return taskIds;
}
private void RecursiveToSyncSerializableData(ATaskTempl pTempl)
{
// save all task templates to map
// reuse when load data from SO to runtime-memory
_allTaskTemplates.Add(pTempl);
// fill serializable datas from unserialized ones
pTempl.SyncSerializableDataAfterLoaded();
ATaskTempl pChild = pTempl.m_pFirstChild;
while (pChild != null)
{
RecursiveToSyncSerializableData(pChild);
pChild = pChild.m_pNextSibling;
}
}
}
}