279 lines
11 KiB
C#
279 lines
11 KiB
C#
using System;
|
|
using System.Runtime.InteropServices;
|
|
using BrewMonster.Scripts.Task;
|
|
using UnityEngine;
|
|
|
|
namespace PerfectWorld.Scripts.Task
|
|
{
|
|
public class TaskProcess
|
|
{
|
|
|
|
}
|
|
[Flags]
|
|
public enum TaskState : byte
|
|
{
|
|
TASK_STATE_FINISHED = 0x01, // Is finished
|
|
TASK_STATE_SUCCESS = 0x02, // Is successful
|
|
TASK_STATE_GIVEUP = 0x04, // Is given up
|
|
TASK_STATE_ERR_REPORTED = 0x08, // Error has been reported to client
|
|
TASK_STATE_AWARD_NOTIFY_TEAM = 0x10, // Award has been notified to team
|
|
TASK_STATE_CONTRIBUTION_FINISH = 0x20 // Contribution finished
|
|
}
|
|
|
|
// Cur Size 21 bytes
|
|
public class TASK_ENTRY_FIXED_DATA
|
|
{
|
|
public ushort m_ID; // ID
|
|
public char m_ParentIndex; // Parent node index
|
|
public char m_PrevSblIndex; // Previous sibling node index
|
|
public char m_NextSblIndex; // Next sibling node index
|
|
public char m_ChildIndex; // Child node index
|
|
public char m_uState; // Task state
|
|
public uint m_ulTaskTime; // Timestamp
|
|
public ushort m_uCapTaskId; // Captain task ID
|
|
public uint m_ulTemplAddr; // Template address
|
|
public uint m_ulCapTemplAddr; // Captain task template address
|
|
|
|
public static int Size()
|
|
{
|
|
return 2 + 1 + 1 + 1 + 1 + 1 + 4 + 2 + 4 + 4;
|
|
}
|
|
};
|
|
|
|
// ´óСΪTASK_DATA_BUF_MAX_LEN
|
|
public class ActiveTaskEntry : TASK_ENTRY_FIXED_DATA
|
|
{
|
|
// Buffer union simplified (C# does not support union directly)
|
|
// unsigned char m_BufData[TASK_DATA_BUF_MAX_LEN-sizeof(TASK_ENTRY_FIXED_DATA)];
|
|
public byte[] m_BufData = new byte[TaskInterfaceConstants.TASK_DATA_BUF_MAX_LEN - 21 ]; // Raw data buffer
|
|
// nsigned short m_wMonsterNum[MAX_MONSTER_WANTED];
|
|
public ushort[] m_wMonsterNum = new ushort[TaskInterfaceConstants.MAX_MONSTER_WANTED]; // Monster numbers
|
|
public int m_iUsefulData1;
|
|
public byte m_iUsefulData2; // char in C++, but using byte here for simplicity
|
|
|
|
public void ReadFromBuffer(byte[] buffer, ref int offset)
|
|
{
|
|
m_ID = BitConverter.ToUInt16(buffer, offset);
|
|
offset += 2;
|
|
m_ParentIndex = (char)buffer[offset++];
|
|
m_PrevSblIndex = (char)buffer[offset++];
|
|
m_NextSblIndex = (char)buffer[offset++];
|
|
m_ChildIndex = (char)buffer[offset++];
|
|
m_uState = (char)buffer[offset++];
|
|
m_ulTaskTime = BitConverter.ToUInt32(buffer, offset);
|
|
offset += 4;
|
|
m_uCapTaskId = BitConverter.ToUInt16(buffer, offset);
|
|
offset += 2;
|
|
m_ulTemplAddr = BitConverter.ToUInt32(buffer, offset);
|
|
offset += 4;
|
|
m_ulCapTemplAddr = BitConverter.ToUInt32(buffer, offset);
|
|
offset += 4;
|
|
|
|
int localOffset = offset; // store current offset for reading additional fields from union
|
|
|
|
// Read remaining buffer data
|
|
Array.Copy(buffer, offset, m_BufData, 0, m_BufData.Length);
|
|
offset += m_BufData.Length; // in C++ have union, so we dont plus offset here
|
|
|
|
// Additional fields can be read here as needed
|
|
m_wMonsterNum = new ushort[TaskInterfaceConstants.MAX_MONSTER_WANTED];
|
|
for (int i = 0; i < TaskInterfaceConstants.MAX_MONSTER_WANTED; i++)
|
|
{
|
|
m_wMonsterNum[i] = BitConverter.ToUInt16(buffer, localOffset);
|
|
localOffset += 2; // in C++ have union, so we dont plus offset here
|
|
}
|
|
|
|
m_iUsefulData1 = BitConverter.ToInt32(buffer, localOffset);
|
|
localOffset += 4; // in C++ have union, so we dont plus offset here
|
|
|
|
m_iUsefulData2 = buffer[localOffset++]; // in C++ have union, so we dont plus offset here
|
|
|
|
|
|
}
|
|
|
|
// bool IsFinished() const { return (m_uState & TASK_STATE_FINISHED) != 0; }
|
|
// bool IsSuccess() const { return (m_uState & TASK_STATE_SUCCESS) != 0; }
|
|
// bool IsGiveUp() const { return (m_uState & TASK_STATE_GIVEUP) != 0; }
|
|
// bool IsErrReported() const { return (m_uState & TASK_STATE_ERR_REPORTED) != 0; }
|
|
// bool IsAwardNotifyTeam() const { return (m_uState & TASK_STATE_AWARD_NOTIFY_TEAM) != 0; }
|
|
// bool IsContributionFinish() const { return (m_uState & TASK_STATE_CONTRIBUTION_FINISH) != 0; }
|
|
// --- State check methods ---
|
|
public bool IsFinished() => (m_uState & (byte)TaskState.TASK_STATE_FINISHED) != 0;
|
|
public bool IsSuccess() => (m_uState & (byte)TaskState.TASK_STATE_SUCCESS) != 0;
|
|
public bool IsGiveUp() => (m_uState & (byte)TaskState.TASK_STATE_GIVEUP) != 0;
|
|
public bool IsErrReported() => (m_uState & (byte)TaskState.TASK_STATE_ERR_REPORTED) != 0;
|
|
public bool IsAwardNotifyTeam() => (m_uState & (byte)TaskState.TASK_STATE_AWARD_NOTIFY_TEAM) != 0;
|
|
public bool IsContributionFinish() => (m_uState & (byte)TaskState.TASK_STATE_CONTRIBUTION_FINISH) != 0;
|
|
|
|
// void SetFinished() { m_uState |= TASK_STATE_FINISHED; }
|
|
// void ClearFinished() { m_uState &= ~TASK_STATE_FINISHED; }
|
|
// void SetSuccess() { m_uState |= TASK_STATE_SUCCESS; }
|
|
// void ClearSuccess() { m_uState &= ~TASK_STATE_SUCCESS; }
|
|
// void SetGiveUp() { m_uState |= TASK_STATE_GIVEUP; }
|
|
// void ClearGiveUp() { m_uState &= ~TASK_STATE_GIVEUP; }
|
|
// void SetErrReported() { m_uState |= TASK_STATE_ERR_REPORTED; }
|
|
// void ClearErrReported() { m_uState &= ~TASK_STATE_ERR_REPORTED; }
|
|
// void SetAwardNotifyTeam() { m_uState |= TASK_STATE_AWARD_NOTIFY_TEAM; }
|
|
// void ClearAwardNotifyTeam() { m_uState &= ~TASK_STATE_AWARD_NOTIFY_TEAM; }
|
|
// void SetContributionFinish() { m_uState |= TASK_STATE_CONTRIBUTION_FINISH; }
|
|
// void ClearContributionFinish() { m_uState &= ~TASK_STATE_CONTRIBUTION_FINISH; }
|
|
//
|
|
public ATaskTempl GetTempl()
|
|
{
|
|
// Managed fallback: resolve via template manager by ID
|
|
try
|
|
{
|
|
var man = BrewMonster.Network.EC_Game.GetTaskTemplateMan();
|
|
if (man != null)
|
|
{
|
|
var templ = man.GetTaskTemplByID(m_ID);
|
|
if (templ != null) return templ;
|
|
}
|
|
}
|
|
catch { }
|
|
|
|
// Legacy pointer path (likely unused in managed port)
|
|
if (m_ulTemplAddr != 0)
|
|
{
|
|
try
|
|
{
|
|
return Marshal.PtrToStructure<ATaskTempl>(new IntPtr(unchecked((long)m_ulTemplAddr)));
|
|
}
|
|
catch { }
|
|
}
|
|
return null;
|
|
}
|
|
// const ATaskTempl* GetCap() const { return reinterpret_cast<const ATaskTempl*>(m_ulCapTemplAddr); }
|
|
// const ATaskTempl* GetCapOrSelf() const
|
|
// {
|
|
// if (m_ulCapTemplAddr) return GetCap();
|
|
// else return GetTempl();
|
|
// }
|
|
// bool HasParent() const { return m_ParentIndex != 0xff; }
|
|
// bool HasChildren() const { return m_ChildIndex != 0xff; }
|
|
// bool IsValid(unsigned char uIndex, unsigned char uMaxCount) const
|
|
// {
|
|
// if (m_ParentIndex != 0xff)
|
|
// {
|
|
// if (m_ParentIndex >= uIndex || m_ParentIndex >= uMaxCount)
|
|
// return false;
|
|
// }
|
|
//
|
|
// if (m_PrevSblIndex != 0xff)
|
|
// {
|
|
// if (m_PrevSblIndex >= uIndex || m_PrevSblIndex >= uMaxCount)
|
|
// return false;
|
|
// }
|
|
//
|
|
// if (m_NextSblIndex != 0xff)
|
|
// {
|
|
// if (m_NextSblIndex <= uIndex || m_NextSblIndex >= uMaxCount)
|
|
// return false;
|
|
// }
|
|
//
|
|
// if (m_ChildIndex != 0xff)
|
|
// {
|
|
// if (m_ChildIndex <= uIndex || m_ChildIndex >= uMaxCount)
|
|
// return false;
|
|
// }
|
|
//
|
|
// return true;
|
|
// }
|
|
};
|
|
|
|
public class ActiveTaskList
|
|
{
|
|
// --- Header Fields ---
|
|
public byte[] header = new byte[CECTaskInterface.TASK_ACTIVE_LIST_HEADER_LEN];
|
|
|
|
public byte m_uTaskCount; // number of tasks
|
|
public byte m_uUsedCount; // used count
|
|
public ushort m_Version; // version
|
|
public byte m_uTopShowTaskCount; // top show task count
|
|
public byte m_uListState; // list state
|
|
public byte m_uTopHideTaskCount; // top hide task count
|
|
|
|
private byte _flags; // simulate bitfield (1 bit + 7 bits)
|
|
|
|
public bool m_uMaxSimultaneousCount
|
|
{
|
|
get => (_flags & 0x01) != 0;
|
|
set
|
|
{
|
|
if (value) _flags |= 0x01;
|
|
else _flags &= unchecked((byte)~0x01);
|
|
}
|
|
}
|
|
|
|
public byte m_uTitleTaskCount
|
|
{
|
|
get => (byte)((_flags & 0xFE) >> 1);
|
|
set => _flags = (byte)((_flags & 0x01) | ((value & 0x7F) << 1));
|
|
}
|
|
|
|
// ActiveTaskEntry m_TaskEntries[TASK_ACTIVE_LIST_MAX_LEN];
|
|
public ActiveTaskEntry[] m_TaskEntries = new ActiveTaskEntry[CECTaskInterface.TASK_ACTIVE_LIST_MAX_LEN];
|
|
|
|
// --- Methods ---
|
|
public void ReadFromBuffer(byte[] buffer)
|
|
{
|
|
// NOTE: union
|
|
// cause C++ use union here, header use same data slot with the rest of properties like m_uTaskCount etc.
|
|
// so, we dont need to read other properties again, just copy the header part
|
|
int offset = 0;
|
|
Array.Copy(buffer, offset, header, 0, header.Length);
|
|
// offset += header.Length;
|
|
|
|
m_uTaskCount = buffer[offset++];
|
|
m_uUsedCount = buffer[offset++];
|
|
m_Version = BitConverter.ToUInt16(buffer, offset);
|
|
offset += 2;
|
|
m_uTopShowTaskCount = buffer[offset++];
|
|
m_uListState = buffer[offset++];
|
|
m_uTopHideTaskCount = buffer[offset++];
|
|
_flags = buffer[offset++];
|
|
|
|
for (int i = 0; i < m_uTaskCount; i++)
|
|
{
|
|
ActiveTaskEntry entry = new ActiveTaskEntry();
|
|
entry.ReadFromBuffer(buffer, ref offset);
|
|
m_TaskEntries[i] = entry;
|
|
}
|
|
}
|
|
|
|
// void UpdateTaskMask(unsigned long& ulMask) const;
|
|
// void UpdateUsedCount();
|
|
// void RealignTask(ActiveTaskEntry* pEntry, unsigned char uReserve);
|
|
// void ClearTask(TaskInterface* pTask, ActiveTaskEntry* pEntry, bool bRemoveItem);
|
|
// void RecursiveClearTask(TaskInterface* pTask, ActiveTaskEntry* pEntry, bool bRemoveItem, bool bRemoveAcquired, bool bClearTask);
|
|
// void ClearChildrenOf(TaskInterface* pTask, ActiveTaskEntry* pParent, bool bRemoveItem = true);
|
|
// ActiveTaskEntry* GetEntry(unsigned long ulId)
|
|
// {
|
|
// for (unsigned char i = 0; i < m_uTaskCount; i++)
|
|
// if (m_TaskEntries[i].m_ID == ulId)
|
|
// return &m_TaskEntries[i];
|
|
//
|
|
// return NULL;
|
|
// }
|
|
// void RemoveAll()
|
|
// {
|
|
// unsigned short ver = m_Version;
|
|
// memset(this, 0, sizeof(*this));
|
|
// m_Version = ver;
|
|
// }
|
|
// bool IsValid() const { return m_uTaskCount <= TASK_ACTIVE_LIST_MAX_LEN; }
|
|
// bool IsTimeMarkUpdate() const { return (m_uListState & TLIST_STATE_UPDATE_TIME_MARK) != 0; }
|
|
// void SetTimeMarkUpdate() { m_uListState |= TLIST_STATE_UPDATE_TIME_MARK; }
|
|
// void ClearTimeMarkUpdate() { m_uListState &= ~TLIST_STATE_UPDATE_TIME_MARK; }
|
|
// int GetMaxSimultaneousCount() {return m_uMaxSimultaneousCount ? TASK_MAX_SIMULTANEOUS_COUT : TASK_DEFAULT_MAX_SIMULTANEOUS_COUT;}
|
|
// void ExpandMaxSimultaneousCount() {m_uMaxSimultaneousCount = 1;}
|
|
public ActiveTaskEntry GetEntry(uint ulId)
|
|
{
|
|
for (int i = 0; i < m_uTaskCount; i++)
|
|
if (m_TaskEntries[i].m_ID == ulId)
|
|
return m_TaskEntries[i];
|
|
|
|
return null;
|
|
}
|
|
};
|
|
} |