using BrewMonster; using ModelRenderer.Scripts.GameData; using System.Collections.Generic; using System.IO; using UnityEngine; namespace PerfectWorld.Scripts.Task { public class ATaskTemplMan { public const ulong TASK_PACK_MAGIC = 0x93858361; public const ulong _task_templ_cur_version = 121; private ulong g_ulNewCount = 0;// do we need this? private Dictionary m_TaskTemplMap = new Dictionary(); private Dictionary m_AllTemplMap = new Dictionary(); private Dictionary m_DynTaskMap = new Dictionary(); private Dictionary m_TitleTaskMap = new Dictionary(); private Dictionary m_ExlusiveAwardTaskMap = new Dictionary(); private Dictionary m_ProtectNPCMap = new Dictionary(); private Dictionary m_AutoDelvMap = new Dictionary(); private Dictionary m_DeathTrigMap = new Dictionary(); private Dictionary m_PQTemplMap = new Dictionary(); private Dictionary m_StorageEssenseMap = new Dictionary(); private Dictionary m_WeightEssenseMap = new Dictionary(); private Dictionary m_StorageTaskMap = new Dictionary(); private List m_SkillTaskLst = new List(); private List m_TmLmtChkLst = new List(); private elementdataman m_pEleDataMan; public void Release() { } public void Init(elementdataman pMan) { m_pEleDataMan = pMan; } public bool LoadTasksFromPack(string szPackPath, bool bLoadDescript) { //TaskInterface::WriteLog(0, 0, 2, "LoadPack begin"); BMLogger.Log("[Dat]- szPackPath: " + szPackPath); if (!File.Exists(szPackPath)) { BMLogger.LogError("[Dat]- File not found: " + szPackPath); return false; } long readBytes = 0; FileStream fs = new FileStream(szPackPath, FileMode.Open, FileAccess.Read); TASK_PACK_HEADER tph = AAssit.ReadFromBinaryOf(fs, ref readBytes); if (tph.magic != TASK_PACK_MAGIC || tph.version != _task_templ_cur_version) return false; if (tph.item_count == 0) return true; uint[] pOffs = new uint[tph.item_count]; g_ulNewCount++; // fread(pOffs, sizeof(long), tph.item_count, fp); pOffs = AAssit.ReadArrayFromBinary(fs, tph.item_count, ref readBytes); for (int i = 0; i < tph.item_count; i++) { fs.Seek(pOffs[i], SeekOrigin.Begin); ATaskTempl pTempl = new ATaskTempl(); g_ulNewCount++; if (!pTempl.LoadFromBinFile(fs)) { CECTaskInterface.WriteLog(0, (int)pTempl.m_FixedData.m_ID, 0, "Cant Load Task"); // LOG_DELETE(pTempl); continue; } AddOneTaskTempl(pTempl); // TaskInterface::WriteLog(0, pTempl->m_ID, 2, "LoadTask"); } // // char log[1024]; // // sprintf(log, "LoadTask, Count = %d", m_TaskTemplMap.size()); // // TaskInterface::WriteLog(0, 0, 2, log); // //todo: check // // LOG_DELETE_ARR(pOffs); fs.Close(); // UpdateTimeLimitCheckList(); #if _ELEMENTCLIENT _task_err.Release(); _task_err.Init("Configs\\task_err.txt", true); #endif return true; } // General method to read a struct from a FileStream private T ReadStruct(FileStream stream) where T : struct { int size = System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)); byte[] buffer = new byte[size]; int bytesRead = stream.Read(buffer, 0, size); if (bytesRead != size) throw new EndOfStreamException("Could not read enough bytes for struct"); var handle = System.Runtime.InteropServices.GCHandle.Alloc(buffer, System.Runtime.InteropServices.GCHandleType.Pinned); try { return (T)System.Runtime.InteropServices.Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); } finally { handle.Free(); } } public bool LoadNPCInfoFromPack(string szPath) { return true; } public void VerifyDynTasksPack(string szPath) { } private void AddOneTaskTempl(ATaskTempl pTask) { //todo: recheck - wrong logic if (m_AllTemplMap.ContainsKey(pTask.m_FixedData.m_ID)) { CECTaskInterface.WriteLog(0, (int)pTask.m_FixedData.m_ID, 0, "Dup Task Found"); // Optionally log duplicate task found, e.g.: // Debug.LogWarning($"Duplicate Task Found: {pTempl.m_ID}"); return; } m_TaskTemplMap[pTask.m_FixedData.m_ID] = pTask; if (pTask.m_FixedData.m_bDeathTrig) m_DeathTrigMap[pTask.m_FixedData.m_ID] = pTask; else if (pTask.m_FixedData.m_bAutoDeliver) m_AutoDelvMap[pTask.m_FixedData.m_ID] = pTask; if (pTask.m_FixedData.m_bPQTask) m_PQTemplMap[pTask.m_FixedData.m_ID] = pTask; if (pTask.m_FixedData.m_bSkillTask) m_SkillTaskLst.Add(pTask); //todo: recheck m_DynTaskType type if (!string.IsNullOrEmpty(pTask.m_FixedData.m_DynTaskType)) { if (m_DynTaskMap.TryGetValue(pTask.m_FixedData.m_ID, out ATaskTempl task)) { CECTaskInterface.WriteLog(0, (int)pTask.m_FixedData.m_ID, 0, "Dup Dyn Task Found"); } m_DynTaskMap[pTask.m_FixedData.m_ID] = pTask; } if (pTask.m_FixedData.m_bDisplayInTitleTaskUI) m_TitleTaskMap[pTask.m_FixedData.m_ID] = pTask; if (pTask.m_FixedData.m_bAutoDeliver && pTask.m_FixedData.m_bDisplayInExclusiveUI) m_ExlusiveAwardTaskMap[pTask.m_FixedData.m_ID] = pTask; //#if _TASK_CLIENT // if (pTask.m_ulDelvNPC != 0 && pTask.m_bCanSeekOut) // m_TasksCanSeekOut.Add(pTask); //#endif AddTaskToMap(pTask); } private void AddTaskToMap(ATaskTempl pTempl) { if (pTempl.m_FixedData.m_enumMethod == (ulong)TaskMethod.enumTMProtectNPC && pTempl.m_FixedData.m_ulNPCToProtect > 0) m_ProtectNPCMap[pTempl.m_FixedData.m_ulNPCToProtect] = pTempl; m_AllTemplMap[pTempl.m_FixedData.m_ID] = pTempl; ATaskTempl pChild = pTempl.m_pFirstChild; while (pChild != null) { AddTaskToMap(pChild); pChild = pChild.m_pNextSibling; } } void UpdateTimeLimitCheckList() { m_TmLmtChkLst.Clear(); foreach (var entry in m_TaskTemplMap) { if (entry.Value.m_FixedData.m_ulMaxReceiver != 0) { m_TmLmtChkLst.Add(entry.Value); } } } public bool InitStorageTask() { m_StorageEssenseMap.Clear(); m_WeightEssenseMap.Clear(); DATA_TYPE dt; //ID_SPACE.ID_SPACE_ESSENCE foreach (var pair in m_pEleDataMan.essence_id_data_type_map) { if (pair.Value == DATA_TYPE.DT_NPC_TASK_OUT_SERVICE) { dt = pair.Value; NPC_TASK_OUT_SERVICE pData = (NPC_TASK_OUT_SERVICE)m_pEleDataMan.get_data_ptr(pair.Key, ID_SPACE.ID_SPACE_ESSENCE, ref dt); if (pData.storage_id == 0) continue; if (pData.storage_id > CECTaskInterface.TASK_STORAGE_COUNT) return false; if (m_StorageEssenseMap.ContainsKey(pData.storage_id)) return false; m_StorageEssenseMap[pData.storage_id] = pData.id; for (var i = 0; i < pData.id_tasks.Length; i++) { if (pData.id_tasks[i] > 0) { m_StorageTaskMap[(int)pData.id_tasks[i]] = (int)pData.storage_id; } } } } // ID_SPACE_CONFIG foreach (var pair in m_pEleDataMan.config_id_data_type_map) { if (pair.Value == DATA_TYPE.DT_NPC_TASK_OUT_SERVICE) { dt = pair.Value; NPC_TASK_OUT_SERVICE pData = (NPC_TASK_OUT_SERVICE)m_pEleDataMan.get_data_ptr(pair.Key, ID_SPACE.ID_SPACE_ESSENCE, ref dt); if (pData.storage_id == 0) continue; if (pData.storage_id > CECTaskInterface.TASK_STORAGE_COUNT) return false; if (m_StorageEssenseMap.ContainsKey(pData.storage_id)) return false; m_StorageEssenseMap[pData.storage_id] = pData.id; for (var i = 0; i < pData.id_tasks.Length; i++) { if (pData.id_tasks[i] > 0) { m_StorageTaskMap[(int)pData.id_tasks[i]] = (int)pData.storage_id; } } } } return true; } } }