Files
test/Assets/PerfectWorld/Scripts/Task/TaskTempl.Struct.cs
T
2025-12-11 17:41:20 +07:00

464 lines
13 KiB
C#

using System;
using System.Linq;
using System.Runtime.InteropServices;
using CSNetwork.GPDataType;
namespace BrewMonster.Scripts.Task
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct task_sub_tags
{
// private const int MAX_SUB_TAGS = 32;
// union
// {
// unsigned short sub_task;
// unsigned char state;
// };
// IMPORTANT: union
public ushort sub_task;
public byte state
{
get { return (byte)(sub_task & 0xFF); }
set { sub_task = (ushort)((sub_task & 0xFF00) | value); }
}
public byte sz;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_SUB_TAGS)]
public byte[] tags;
public byte cur_index; // for temporary use, dont take into account
public int get_size() { return sz + 3; }
public bool valid_size(int _sz)
{
if (_sz < 3) return false;
return get_size() == _sz;
}
};
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct task_notify_base
{
public byte reason;
public ushort task;
};
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct svr_monster_killed
{
public task_notify_base baseObj;
public uint monster_id;
public ushort monster_num;
public int dps;
public int dph;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct svr_player_killed
{
public task_notify_base baseObj;
public ushort index;
public ushort player_num;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct svr_task_err_code
{
public task_notify_base baseObj;
public uint err_code;
};
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct StorageTaskList
{
// unsigned short m_Storages[TASK_STORAGE_COUNT][TASK_STORAGE_LEN];
// NOTE: 2D array flattened
[MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.TASK_STORAGE_COUNT * TaskTemplConstants.TASK_STORAGE_LEN)]
public ushort[] m_Storages;
// union {
// unsigned short m_StoragesTaskSetCount[TASK_STORAGE_COUNT];
// unsigned short m_StoragesRefreshCount[TASK_STORAGE_COUNT];
// };
// NOTE: union
[MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.TASK_STORAGE_COUNT)]
public ushort[] m_StoragesTaskSetCount;
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.TASK_STORAGE_COUNT)]
public ushort[] m_StoragesRefreshCount
{
get => m_StoragesTaskSetCount;
set { m_StoragesTaskSetCount = value; }
}
[MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.TASK_STORAGE_COUNT)]
public uint[] m_StoragesRefreshTime;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.TASK_STORAGE_COUNT)]
public byte[] m_StoragesReceivePerDay;
public void RemoveAll()
{
for (int i = 0; i < TaskTemplConstants.TASK_STORAGE_COUNT; i++)
{
for (int j = 0; j < TaskTemplConstants.TASK_STORAGE_LEN; j++)
{
m_Storages[i * TaskTemplConstants.TASK_STORAGE_LEN + j] = 0;
}
m_StoragesTaskSetCount[i] = 0;
m_StoragesRefreshCount[i] = 0;
m_StoragesRefreshTime[i] = 0;
m_StoragesReceivePerDay[i] = 0;
}
}
public void ReadByte(byte[] data)
{
int offset = 0;
for (int i=0; i < TaskTemplConstants.TASK_STORAGE_COUNT; i++)
{
for (int j=0; j < TaskTemplConstants.TASK_STORAGE_LEN; j++)
{
m_Storages[i * TaskTemplConstants.TASK_STORAGE_LEN + j] = BitConverter.ToUInt16(data, (i * TaskTemplConstants.TASK_STORAGE_LEN + j) * 2);
}
}
offset += TaskTemplConstants.TASK_STORAGE_COUNT * TaskTemplConstants.TASK_STORAGE_LEN * 2;
// union
for (int i=0; i < TaskTemplConstants.TASK_STORAGE_COUNT; i++)
{
m_StoragesTaskSetCount[i] = BitConverter.ToUInt16(data, offset + i * 2);
// m_StoragesRefreshCount[i] = BitConverter.ToUInt16(data, offset + i * 2);
}
offset += TaskTemplConstants.TASK_STORAGE_COUNT * 2;
for (int i=0; i < TaskTemplConstants.TASK_STORAGE_COUNT; i++)
{
m_StoragesRefreshTime[i] = BitConverter.ToUInt32(data, offset + i * 4);
}
offset += TaskTemplConstants.TASK_STORAGE_COUNT * 4;
for (int i=0; i < TaskTemplConstants.TASK_STORAGE_COUNT; i++)
{
m_StoragesReceivePerDay[i] = data[offset + i];
}
}
}
[ StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct svr_new_task
{
public task_notify_base baseObj;
public uint cur_time;
public uint cap_task; // In C++ use to store ActiveTaskEntry pointer's address -> In C#, we just store the task ID
public task_sub_tags sub_tags;
// public ActiveTaskEntry cap_task_entry; //
public void set_data(
uint _cur_time,
uint _cap_task,
task_sub_tags _sub_tags)
{
cur_time = _cur_time;
cap_task = _cap_task;
// memcpy(&sub_tags, &_sub_tags, _sub_tags.get_size());
sub_tags = _sub_tags;
}
public void get_data(
ref uint _cur_time,
ref uint _cap_task,
ref task_sub_tags _sub_tags)
{
_cur_time = cur_time;
_cap_task = cap_task;
// memcpy(&_sub_tags, &sub_tags, sub_tags.get_size());
_sub_tags = sub_tags;
}
// inline size_t get_size() const { return sizeof(task_notify_base) + 8 + sub_tags.get_size(); }
public int get_size() { return Marshal.SizeOf<task_notify_base>() + 8 + sub_tags.get_size(); }
public bool valid_size(int sz)
{
int base_sz = Marshal.SizeOf<task_notify_base>() + 8;
if (sz <= base_sz) return false;
return sub_tags.valid_size(sz - base_sz);
}
}
[ StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct svr_treasure_map
{
public task_notify_base baseObj;
public int treasure_index;
}
public struct tm {
public int tm_sec; /* seconds after the minute [0-60] */
public int tm_min; /* minutes after the hour [0-59] */
public int tm_hour; /* hours since midnight [0-23] */
public int tm_mday; /* day of the month [1-31] */
public int tm_mon; /* months since January [0-11] */
public int tm_year; /* years since 1900 */
public int tm_wday; /* days since Sunday [0-6] */
public int tm_yday; /* days since January 1 [0-365] */
public int tm_isdst; /* Daylight Savings Time flag */
public long tm_gmtoff; /* offset from UTC in seconds */
public byte tm_zone; /* timezone abbreviation */
};
[StructLayout(LayoutKind.Explicit)]
public struct TaskGlobalData
{
[FieldOffset(0)]
[MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskInterfaceConstants.TASK_GLOBAL_DATA_SIZE)]
public byte[] buf;
[FieldOffset(0)]
public ulong m_ulReceiverNum;
[FieldOffset(8)]
public ulong m_ulRcvUpdateTime;
void AddRevNum() { m_ulReceiverNum++; }
void CheckRcvUpdateTime(uint ulCurTime, int nFrequency)
{
// TODO: implement time-based receiver number reset logic
// if (nFrequency == TaskCompletionMethod.enumTAFNormal || m_ulRcvUpdateTime == 0)
// return;
//
// tm tmCur = *localtime((time_t*)&ulCurTime);
// tm tmRcv = *localtime((time_t*)&m_ulRcvUpdateTime);
//
// if (nFrequency == enumTAFEachDay)
// {
// if (tmCur.tm_year != tmRcv.tm_year || tmCur.tm_yday != tmRcv.tm_yday)
// m_ulReceiverNum = 0;
// }
// else if (nFrequency == enumTAFEachWeek)
// {
// if (!_is_same_week(&tmCur, &tmRcv, ulCurTime, m_ulRcvUpdateTime))
// m_ulReceiverNum = 0;
// }
// else if (nFrequency == enumTAFEachMonth)
// {
// if (tmCur.tm_year != tmRcv.tm_year || tmCur.tm_mon != tmRcv.tm_mon)
// m_ulReceiverNum = 0;
// }
// else if (nFrequency == enumTAFEachYear)
// {
// if (tmCur.tm_year != tmRcv.tm_year)
// m_ulReceiverNum = 0;
// }
}
}
[ StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct svr_task_complete
{
public task_notify_base baseObj;
public uint cur_time;
public task_sub_tags sub_tags;
public void set_data(
uint _cur_time,
task_sub_tags _sub_tags
)
{
cur_time = _cur_time;
// memcpy(&sub_tags, &_sub_tags, _sub_tags.get_size());
sub_tags = _sub_tags;
}
public void get_data(
ref uint _cur_time,
ref task_sub_tags _sub_tags)
{
_cur_time = cur_time;
// memcpy(&_sub_tags, &sub_tags, sub_tags.get_size());
_sub_tags = sub_tags;
}
public int get_size() { return Marshal.SizeOf<task_notify_base>() + 4 + sub_tags.get_size(); }
public bool valid_size(int sz)
{
int base_sz = Marshal.SizeOf<task_notify_base>() + 4;
if (sz <= base_sz) return false;
return sub_tags.valid_size(sz - base_sz);
}
}
[StructLayout( LayoutKind.Sequential, Pack = 1)]
public struct special_award
{
public uint id1;
public uint id2;
public uint special_mask;
};
[StructLayout( LayoutKind.Sequential, Pack = 1)]
public struct svr_task_special_award
{
public svr_task_complete baseObj;
public special_award sa;
};
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct FnshedTaskListHeader
{
public ushort m_uTaskCount;
public byte m_Version;
public byte m_Reserved;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct FnshedTaskEntry
{
public ushort m_uTaskId;
public byte m_Buf;
// public byte m_Mask; // 1-bit mask: 0 = success, 1 = failure
// public byte m_Reserved; // Remaining 7 bits reserved
public byte m_FnshedCount; // Number of times the task has been completed
public byte m_Mask
{
get { return (byte)(m_Buf & 0x1); }
set { m_Buf = (byte)((m_Buf & 0xFE) | (value & 0x1)); }
}
public byte m_Reserved
{
get { return (byte)(m_Buf & 0x3); }
set { m_Buf = (byte)((m_Buf & 0xFE) | (value & 0x3)); }
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct FinishedTaskList
{
// --- Layout 1: Header + List ---
public FnshedTaskListHeader m_FnshHeader
{
get {
FnshedTaskListHeader header = new FnshedTaskListHeader();
header.m_uTaskCount = BitConverter.ToUInt16(m_Buf, 0);
header.m_Version = m_Buf[2];
header.m_Reserved = m_Buf[3];
return header;
}
}
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskInterfaceConstants.TASK_FINISHED_LIST_MAX_LEN)]
public FnshedTaskEntry[] m_aTaskList
{
get
{
FnshedTaskEntry[] taskList = new FnshedTaskEntry[TaskInterfaceConstants.TASK_FINISHED_LIST_MAX_LEN];
for (int i=0; i < m_FnshHeader.m_uTaskCount; i++)
{
int size = Marshal.SizeOf<FnshedTaskEntry>();
int startIndex = i * size + 4; // 4 bytes for m_FnshHeader
int endIndex = startIndex + size;
taskList[i] = GPDataTypeHelper.FromBytes<FnshedTaskEntry>(m_Buf[startIndex..endIndex]);
}
return taskList;
}
}
[MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskInterfaceConstants.TASK_FINISHED_LIST_BUF_SIZE)]
public byte[] m_Buf;
public bool ReadFromBytes(byte[] data)
{
if (data.Length != TaskInterfaceConstants.TASK_FINISHED_LIST_BUF_SIZE)
return false;
m_Buf = new byte[TaskInterfaceConstants.TASK_FINISHED_LIST_BUF_SIZE];
Array.Copy(data, m_Buf, TaskInterfaceConstants.TASK_FINISHED_LIST_BUF_SIZE);
return true;
}
public int GetTaskPos(ulong ulID)
{
// TODO: Implement logic to get task position
//throw new NotImplementedException();
return 0;
}
public void AddOneTask(ulong ulID, bool bSuccess)
{
// TODO: Implement logic to add one task
//throw new NotImplementedException();
}
public void RemoveTask(ulong ulID)
{
// TODO: Implement logic to remove a task
//throw new NotImplementedException();
// unsigned long ulPos = GetTaskPos(ulID);
// if (static_cast<int>(ulPos) < 0) return;
//
// m_FnshHeader.m_uTaskCount--;
//
// if (m_FnshHeader.m_uTaskCount <= ulPos)
// return;
//
// memmove(
// &m_aTaskList[ulPos],
// &m_aTaskList[ulPos+1],
// (m_FnshHeader.m_uTaskCount-ulPos) * sizeof(FnshedTaskEntry));
}
public int SearchTask(ulong ulID)
{
// TODO: Implement logic to search for a task
//throw new NotImplementedException();
return 0;
}
public byte SearchTaskFinishCount(ulong ulID)
{
// TODO: Implement logic to search task finish count
//throw new NotImplementedException();
return 0;
}
public void ResetFinishCount(ulong ulID)
{
// TODO: Implement logic to reset finish count
//throw new NotImplementedException();
}
public void AddForFinishCount(ulong ulID, bool bSuccess)
{
// TODO: Implement logic to add for finish count
//throw new NotImplementedException();
}
public void RemoveAll()
{
Array.Clear(m_aTaskList, 0, m_aTaskList.Length);
Array.Clear(m_Buf, 0, m_Buf.Length);
}
public bool IsValid()
{
return m_FnshHeader.m_uTaskCount <= TaskInterfaceConstants.TASK_FINISHED_LIST_MAX_LEN;
}
}
}