From 0132075d1c6a88066ce6f6225f168a49e76a51a3 Mon Sep 17 00:00:00 2001 From: maybegreat48 <96936658+maybegreat48@users.noreply.github.com> Date: Mon, 9 Oct 2023 13:01:36 +0000 Subject: [PATCH] Netsync stuff (#5) * feat(metric): add rlMetric * fix(metric): serializer fix * feat(tls): add tlsContext * feat(fwEntity): add entity classes * fix: add import * fix(vector): constexpr ctors * feat(ped): add CPed * feat(sync): add sync nodes * feat(netsync): add netSyncDataNode::IsActive * feat(netsync): first node * fix: make GetData accessible * fix: make netSyncDataNode an abstract class * fix(netsync): the compiler is too smart for its own good * feat(netsync): add CObjectCreationData * feat(netsync): add CPlayerAppearanceData * feat(netsync): CVehicleCreationData * feat(netsync): add CPickupCreationData * feat(netsync): add CPhysicalAttachData * feat(netsync): add CVehicleProximityMigrationData * feat(netsync): add CPedTaskTreeData * feat(network): add CScriptedGameEvent --------- --- classes.cpp | 18 ++++++ network/CScriptedGameEvent.hpp | 22 ++++++++ network/netGameEvent.hpp | 19 +++++++ network/sync/CProjectBaseSyncDataNode.hpp | 30 ++++++++++ network/sync/NodeCommonDataOperations.hpp | 22 ++++++++ network/sync/netSyncDataNode.hpp | 38 +++++++++++++ network/sync/netSyncNodeBase.hpp | 40 +++++++++++++ network/sync/netSyncTree.hpp | 25 +++++++++ network/sync/object/CObjectCreationData.hpp | 13 +++++ network/sync/ped/CPedCreationData.hpp | 15 +++++ network/sync/ped/CPedTaskTreeData.hpp | 45 +++++++++++++++ network/sync/physical/CPhysicalAttachData.hpp | 21 +++++++ network/sync/pickup/CPickupCreationData.hpp | 12 ++++ network/sync/player/CPlayerAppearanceData.hpp | 12 ++++ network/sync/vehicle/CVehicleCreationData.hpp | 13 +++++ .../CVehicleProximityMigrationData.hpp | 21 +++++++ rage/atPlayerBits.hpp | 31 ++++++++++ rage/tlsContext.hpp | 8 ++- rage/vector.hpp | 2 +- rdr2.rcnet | Bin 5154 -> 16597 bytes script/scriptId.hpp | 31 ++++++++++ script/scriptIdBase.hpp | 53 ++++++++++++++++++ 22 files changed, 487 insertions(+), 4 deletions(-) create mode 100644 network/CScriptedGameEvent.hpp create mode 100644 network/netGameEvent.hpp create mode 100644 network/sync/CProjectBaseSyncDataNode.hpp create mode 100644 network/sync/NodeCommonDataOperations.hpp create mode 100644 network/sync/netSyncDataNode.hpp create mode 100644 network/sync/netSyncNodeBase.hpp create mode 100644 network/sync/netSyncTree.hpp create mode 100644 network/sync/object/CObjectCreationData.hpp create mode 100644 network/sync/ped/CPedCreationData.hpp create mode 100644 network/sync/ped/CPedTaskTreeData.hpp create mode 100644 network/sync/physical/CPhysicalAttachData.hpp create mode 100644 network/sync/pickup/CPickupCreationData.hpp create mode 100644 network/sync/player/CPlayerAppearanceData.hpp create mode 100644 network/sync/vehicle/CVehicleCreationData.hpp create mode 100644 network/sync/vehicle/CVehicleProximityMigrationData.hpp create mode 100644 rage/atPlayerBits.hpp create mode 100644 script/scriptId.hpp create mode 100644 script/scriptIdBase.hpp diff --git a/classes.cpp b/classes.cpp index ac4474c..798f004 100644 --- a/classes.cpp +++ b/classes.cpp @@ -3,8 +3,23 @@ #include "base/fwRefAwareBase.hpp" #include "base/fwRefAwareBaseImpl.hpp" #include "entity/fwEntity.hpp" +#include "network/sync/object/CObjectCreationData.hpp" +#include "network/sync/ped/CPedCreationData.hpp" +#include "network/sync/ped/CPedTaskTreeData.hpp" +#include "network/sync/physical/CPhysicalAttachData.hpp" +#include "network/sync/pickup/CPickupCreationData.hpp" +#include "network/sync/player/CPlayerAppearanceData.hpp" +#include "network/sync/vehicle/CVehicleCreationData.hpp" +#include "network/sync/vehicle/CVehicleProximityMigrationData.hpp" +#include "network/sync/CProjectBaseSyncDataNode.hpp" +#include "network/sync/netSyncDataNode.hpp" +#include "network/sync/netSyncNodeBase.hpp" +#include "network/sync/netSyncTree.hpp" +#include "network/sync/NodeCommonDataOperations.hpp" #include "network/CNetGamePlayer.hpp" #include "network/CNetworkPlayerMgr.hpp" +#include "network/CScriptedGameEvent.hpp" +#include "network/netGameEvent.hpp" #include "network/netObject.hpp" #include "network/netPeerAddress.hpp" #include "network/netPlayer.hpp" @@ -15,12 +30,15 @@ #include "player/CPlayerInfo.hpp" #include "ped/CPed.hpp" #include "rage/atArray.hpp" +#include "rage/atPlayerBits.hpp" #include "rage/joaat.hpp" #include "rage/rlJson.hpp" #include "rage/rlMetric.hpp" #include "rage/tlsContext.hpp" #include "rage/vector.hpp" #include "script/scriptHandlerNetComponent.hpp" +#include "script/scriptId.hpp" +#include "script/scriptIdBase.hpp" #include "script/scrNativeHandler.hpp" #include "script/scrThread.hpp" #include "script/scrThreadContext.hpp" diff --git a/network/CScriptedGameEvent.hpp b/network/CScriptedGameEvent.hpp new file mode 100644 index 0000000..d2c9dc5 --- /dev/null +++ b/network/CScriptedGameEvent.hpp @@ -0,0 +1,22 @@ +#pragma once +#include "netGameEvent.hpp" +#include "script/scriptId.hpp" +#include "rage/atPlayerBits.hpp" + +#pragma pack(push, 8) +class CScriptedGameEvent : public rage::netGameEvent +{ +public: + CGameScriptId m_ScriptId; // 0x38 + int m_DataSize; // 0x60 + bool m_Unk; // 0x64 (netComponent && *(netComponent + 0x16C) == 32) + bool m_ScriptIdOverridden; // 0x65 + bool m_HasScriptMetadataIdx; // 0x66 + std::uint64_t m_Data[54]; // 0x68 + rage::atPlayerBits m_ReceiverBits; // 0x218 + int m_ScriptMetadataIndex; // 0x21C + int m_ScriptHash; // 0x220 + int16_t m_Status; // 0x224 +}; +#pragma pack(pop) +static_assert(sizeof(CScriptedGameEvent) == 0x228); \ No newline at end of file diff --git a/network/netGameEvent.hpp b/network/netGameEvent.hpp new file mode 100644 index 0000000..875b9b5 --- /dev/null +++ b/network/netGameEvent.hpp @@ -0,0 +1,19 @@ +#pragma once +#include + +class CNetGamePlayer; +namespace rage +{ + class netGameEvent + { + public: + virtual ~netGameEvent() = 0; // 0x00 + + std::int16_t m_EventType; // 0x08 + bool m_RequiresReply; // 0x0A + char m_Pad1[0xD]; // 0x0B + class CNetGamePlayer* m_Sender; // 0x18 + char m_Pad2[0x18]; // 0x20 + }; + static_assert(sizeof(rage::netGameEvent) == 0x38); +} \ No newline at end of file diff --git a/network/sync/CProjectBaseSyncDataNode.hpp b/network/sync/CProjectBaseSyncDataNode.hpp new file mode 100644 index 0000000..8b5426a --- /dev/null +++ b/network/sync/CProjectBaseSyncDataNode.hpp @@ -0,0 +1,30 @@ +#pragma once +#include "netSyncDataNode.hpp" +#include "NodeCommonDataOperations.hpp" + +namespace rage +{ + class netSyncData; + class netObject; +} + +class CProjectBaseSyncDataNode : public rage::netSyncDataNode +{ +private: + NodeCommonDataOperations m_CommonDataOperations; // 0x120 + char m_Data[]; // 0x130 + +public: +#if _WIN32 + template + T& GetData() + { + return *reinterpret_cast(&m_Data[rage::tlsContext::Get()->m_SyncThreadIndex * sizeof(T)]); + } +#endif +}; +static_assert(sizeof(CProjectBaseSyncDataNode) == 0x130); + +// We probably don't need these anymore +//class CSyncDataNodeFrequent : public CProjectBaseSyncDataNode {}; +//class CSyncDataNodeInfrequent : public CProjectBaseSyncDataNode {}; \ No newline at end of file diff --git a/network/sync/NodeCommonDataOperations.hpp b/network/sync/NodeCommonDataOperations.hpp new file mode 100644 index 0000000..dcb6a7e --- /dev/null +++ b/network/sync/NodeCommonDataOperations.hpp @@ -0,0 +1,22 @@ +#pragma once + +namespace rage +{ + class datBitBuffer; +} + +class NodeCommonDataOperations +{ +public: + virtual ~NodeCommonDataOperations() = default; + virtual void ReadFromBuffer(rage::datBitBuffer* buffer, void* log) {}; // 0x08 + virtual void WriteToBuffer(void* data_base, rage::datBitBuffer* buffer, void* log, bool cache) {}; // 0x10 + virtual void Unk() {}; // 0x18 + // TODO: + virtual int CalculateSize(rage::datBitBuffer* buffer) { return 0; }; // 0x20 + virtual int CalculateSize2(rage::datBitBuffer* buffer) { return 0; }; // 0x28 + virtual void LogSyncData(rage::datBitBuffer* buffer) {}; // 0x30 + virtual void LogSyncData2(rage::datBitBuffer* buffer) {}; // 0x38 + rage::datBitBuffer* m_Buffer; // 0x8 +}; +static_assert(sizeof(NodeCommonDataOperations) == 0x10); \ No newline at end of file diff --git a/network/sync/netSyncDataNode.hpp b/network/sync/netSyncDataNode.hpp new file mode 100644 index 0000000..a973e2e --- /dev/null +++ b/network/sync/netSyncDataNode.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include "netSyncNodeBase.hpp" +#include "rage/tlsContext.hpp" + +namespace rage +{ +#pragma pack(push, 8) + class netSyncDataNode : public netSyncNodeBase + { + struct ThreadData + { + bool m_Unk; + bool m_NodeActive; + }; + static_assert(sizeof(ThreadData) == 2); + + public: + uint32_t m_Flags; // 0x40 + uint32_t pad3; // 0x44 + uint64_t pad4; // 0x48 + netSyncDataNode* m_ParentData; // 0x50 + uint32_t m_MoreFlags; // 0x58 + netSyncDataNode* m_Children[19]; // 0x60 + ThreadData m_ThreadData[8]; // 0xF8 + char pad5[10]; // 0x110 + void* m_CommonDataOpsVFT; // 0x118 + +#if _WIN32 + inline bool IsActive() + { + return m_ThreadData[rage::tlsContext::Get()->m_SyncThreadIndex].m_NodeActive; + } +#endif + }; + static_assert(sizeof(netSyncDataNode) == 0x120); +#pragma pack(pop) +} \ No newline at end of file diff --git a/network/sync/netSyncNodeBase.hpp b/network/sync/netSyncNodeBase.hpp new file mode 100644 index 0000000..51605c2 --- /dev/null +++ b/network/sync/netSyncNodeBase.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include + +namespace rage +{ + class datBitBuffer; + class netSyncTree; + +#pragma pack(push, 8) + class netSyncNodeBase + { + public: + virtual ~netSyncNodeBase() = default; // 0x00 + virtual bool IsDataNode() = 0; // 0x08 + virtual bool IsParentNode() = 0; // 0x10 + virtual void MoveCommonDataOpsVFT() = 0; // 0x18 + virtual void ClearChildren() = 0; // 0x20 + virtual void _0x28(void*, void*, void*, int* out_count) = 0; // 0x28 + virtual bool Serialize(int flags, int flags2, void*, rage::datBitBuffer* buffer, int, void*, bool, int*, int* num_serialized) = 0; // 0x30 + virtual bool Deserialize(int flags, int flags2, rage::datBitBuffer* buffer, void*) = 0; // 0x38 + virtual int CalculateSize(int flags, int flags2, void*) = 0; // 0x40 + virtual int CalculateSize2(int flags, int flags2, bool) = 0; // 0x48 + + netSyncNodeBase* m_NextSibling; //0x0008 + netSyncNodeBase* m_PrevSibling; //0x0010 + netSyncTree* m_Root; //0x0018 + netSyncNodeBase* m_Parent; //0x0020 + + uint32_t m_Flags1; //0x0028 + uint32_t m_Flags2; //0x002C + uint32_t m_Flags3; //0x0030 + + uint32_t m_Pad2; //0x0034 + + netSyncNodeBase* m_FirstChild; //0x0038 + }; //Size: 0x0040 + static_assert(sizeof(netSyncNodeBase) == 0x40); +#pragma pack(pop) +} \ No newline at end of file diff --git a/network/sync/netSyncTree.hpp b/network/sync/netSyncTree.hpp new file mode 100644 index 0000000..97f929d --- /dev/null +++ b/network/sync/netSyncTree.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "netSyncNodeBase.hpp" + +namespace rage +{ +#pragma pack(push, 8) + class netSyncTree + { + public: + char pad_0000[176]; //0x0000 + netSyncNodeBase* m_NextSyncNode; //0x00B0 + netSyncNodeBase* m_LastSyncNode; //0x00B8 + uint32_t m_NodeCount; //0x00C0 + uint32_t m_SyncNodeCount; //0x00C4 + char pad_00C8[24]; //0x00C8 + netSyncNodeBase* m_Nodes[74]; //0x00E0 + uint32_t m_NodeMaxCount; //0x0330 + netSyncNodeBase* m_SyncNodes[64]; //0x0338 + uint32_t m_SyncNodeMaxCount; //0x0538 + char pad_053C[900]; //0x053C + }; //Size: 0x08C0 + static_assert(sizeof(rage::netSyncTree) == 0x8C0); +#pragma pack(pop) +} \ No newline at end of file diff --git a/network/sync/object/CObjectCreationData.hpp b/network/sync/object/CObjectCreationData.hpp new file mode 100644 index 0000000..3643237 --- /dev/null +++ b/network/sync/object/CObjectCreationData.hpp @@ -0,0 +1,13 @@ +#pragma once +#include + +// TODO +class CObjectCreationData +{ +public: + char pad_0000[284]; //0x0000 + uint32_t m_ObjectType; //0x011C + uint32_t m_ModelHash; //0x0120 + char pad_0124[76]; //0x0124 +}; //Size: 0x0170 +static_assert(sizeof(CObjectCreationData) == 0x170); \ No newline at end of file diff --git a/network/sync/ped/CPedCreationData.hpp b/network/sync/ped/CPedCreationData.hpp new file mode 100644 index 0000000..029dddb --- /dev/null +++ b/network/sync/ped/CPedCreationData.hpp @@ -0,0 +1,15 @@ +#pragma once +#include + +// TODO +class CPedCreationData +{ +public: + char pad_0000[4]; //0x0000 + uint32_t m_PopulationType; //0x0004 + uint32_t m_ModelHash; //0x0008 + char pad_000C[18]; //0x000C + bool m_BannedPed; //0x001E + char pad_001F[13]; //0x001F +}; //Size: 0x002C +static_assert(sizeof(CPedCreationData) == 0x2C); \ No newline at end of file diff --git a/network/sync/ped/CPedTaskTreeData.hpp b/network/sync/ped/CPedTaskTreeData.hpp new file mode 100644 index 0000000..d6f43ae --- /dev/null +++ b/network/sync/ped/CPedTaskTreeData.hpp @@ -0,0 +1,45 @@ +#pragma once +#include + +class CPedTaskData +{ +public: + uint32_t m_TaskType; //0x0000 + char pad_0004[16]; //0x0004 +}; //Size: 0x0014 +static_assert(sizeof(CPedTaskData) == 0x14); + +class CPedTaskTree +{ +public: + uint32_t m_TreeType; //0x0000 + char pad_0004[4]; //0x0004 unused + uint32_t m_NumTasks; //0x0008 + bool m_SequenceTree; //0x000C + class CPedTaskData m_Tasks[12]; //0x0010 + char pad_0100[16]; //0x0100 unused +}; //Size: 0x0110 +static_assert(sizeof(CPedTaskTree) == 0x110); + +class CPedTaskTreeData +{ +public: + class CPedTaskTree m_Trees[5]; //0x0000 + char pad_0550[4]; //0x0550 unused + uint32_t m_ScriptCommand; //0x0554 + uint32_t m_ScriptTaskStage; //0x0558 + + int GetNumTaskTrees() + { + switch (m_Trees[0].m_TreeType) + { + case 0: return 5; + case 1: return 2; + case 2: return 0; + case 3: return 1; + } + + return 0; + } +}; //Size: 0x055C +static_assert(sizeof(CPedTaskTreeData) == 0x55C); diff --git a/network/sync/physical/CPhysicalAttachData.hpp b/network/sync/physical/CPhysicalAttachData.hpp new file mode 100644 index 0000000..bd01bb5 --- /dev/null +++ b/network/sync/physical/CPhysicalAttachData.hpp @@ -0,0 +1,21 @@ +#pragma once +#include +#include "rage/vector.hpp" +#include + +#pragma pack(push, 8) +class CPhysicalAttachData +{ +public: + bool m_IsAttached; //0x0000 + uint16_t m_AttachObjectId; //0x0002 + alignas(16) rage::fvector3 m_Offset; //0x0010 + rage::fvector4 m_Orientation; //0x0020 + rage::fvector3 m_ParentOffset; //0x0030 + uint16_t m_OtherAttachBone; //0x0040 + uint16_t m_AttachBone; //0x0042 + uint32_t m_AttachFlags; //0x0044 + char pad_0048[24]; //0x0048 +}; //Size: 0x0060 +#pragma pack(pop) +static_assert(sizeof(CPhysicalAttachData) == 0x60); \ No newline at end of file diff --git a/network/sync/pickup/CPickupCreationData.hpp b/network/sync/pickup/CPickupCreationData.hpp new file mode 100644 index 0000000..19b42f7 --- /dev/null +++ b/network/sync/pickup/CPickupCreationData.hpp @@ -0,0 +1,12 @@ +#pragma once +#include + +class CPickupCreationData +{ +public: + char pad_0000[68]; //0x0000 + uint32_t m_PickupHash; //0x0044 + uint32_t m_ModelHash; //0x0048 + char pad_004C[236]; //0x004C +}; //Size: 0x0138 +static_assert(sizeof(CPickupCreationData) == 0x138); \ No newline at end of file diff --git a/network/sync/player/CPlayerAppearanceData.hpp b/network/sync/player/CPlayerAppearanceData.hpp new file mode 100644 index 0000000..e771a02 --- /dev/null +++ b/network/sync/player/CPlayerAppearanceData.hpp @@ -0,0 +1,12 @@ +#pragma once +#include + +class CPlayerAppearanceData +{ +public: + char pad_0000[23612]; //0x0000 + uint32_t m_ModelHash; //0x5C3C + char pad_5C40[7]; //0x5C40 + bool m_BannedPlayerModel; //0x5C47 +}; //Size: 0x5C48 +static_assert(sizeof(CPlayerAppearanceData) == 0x5C48); \ No newline at end of file diff --git a/network/sync/vehicle/CVehicleCreationData.hpp b/network/sync/vehicle/CVehicleCreationData.hpp new file mode 100644 index 0000000..d553f55 --- /dev/null +++ b/network/sync/vehicle/CVehicleCreationData.hpp @@ -0,0 +1,13 @@ +#pragma once +#include + +class CVehicleCreationData +{ +public: + char pad_0000[4]; //0x0000 + uint32_t m_PopulationType; //0x0004 + char pad_0008[4]; //0x0008 + uint32_t m_ModelHash; //0x000C + char pad_0010[24]; //0x0010 +}; //Size: 0x0028 +static_assert(sizeof(CVehicleCreationData) == 0x28); \ No newline at end of file diff --git a/network/sync/vehicle/CVehicleProximityMigrationData.hpp b/network/sync/vehicle/CVehicleProximityMigrationData.hpp new file mode 100644 index 0000000..e526774 --- /dev/null +++ b/network/sync/vehicle/CVehicleProximityMigrationData.hpp @@ -0,0 +1,21 @@ +#pragma once +#include "rage/vector.hpp" + +#pragma pack(push, 8) +class CVehicleProximityMigrationData +{ +public: + uint32_t m_NumPassengers; //0x0000 + bool m_PassengersActive[17]; //0x0004 + uint16_t m_PassengerObjectIds[17]; //0x0016 + bool m_OverridePopulationType; //0x0038 + uint32_t m_PopulationType; //0x003C + uint32_t m_Flags; //0x0040 + uint32_t m_Timestamp; //0x0044 + bool m_HasPositionData; //0x0048 + alignas(16) rage::fvector3 m_Position; //0x0050 + rage::vector3 m_Velocity; //0x0060 + uint32_t m_UnkAmount; //0x006C +}; //Size: 0x0070 +static_assert(sizeof(CVehicleProximityMigrationData) == 0x70); +#pragma pack(pop) \ No newline at end of file diff --git a/rage/atPlayerBits.hpp b/rage/atPlayerBits.hpp new file mode 100644 index 0000000..f7614bf --- /dev/null +++ b/rage/atPlayerBits.hpp @@ -0,0 +1,31 @@ +#pragma once + +#pragma pack(push, 8) +namespace rage +{ + class atPlayerBits + { + constexpr static int MAX_PLAYERS = 32; + int m_PlayerBits[MAX_PLAYERS / 32]; + + public: + bool IsSet(int id) + { + return _bittest((const long*)&m_PlayerBits[id / 32], id % 32); + } + + void Set(int id) + { + m_PlayerBits[id / 32] |= (1 << (id % 32)); + } + + void Clear(int id) + { + m_PlayerBits[id / 32] &= ~(1 << (id % 32)); + } + + // TODO: bit count, CNetGamePlayer... + }; + static_assert(sizeof(rage::atPlayerBits) == 4); +} +#pragma pack(pop) \ No newline at end of file diff --git a/rage/tlsContext.hpp b/rage/tlsContext.hpp index 1f7293b..95369d1 100644 --- a/rage/tlsContext.hpp +++ b/rage/tlsContext.hpp @@ -9,9 +9,11 @@ namespace rage #pragma pack(push, 8) class tlsContext { - char pad[0x1700]; public: - bool m_RunningScript; // 0x1700 + char pad[0x410]; // 0x0000 + int m_SyncThreadIndex; // 0x0410 + char pad2[0x12EC]; // 0x0414 + bool m_RunningScript; // 0x1700 #if _WIN32 static tlsContext* Get() @@ -22,5 +24,5 @@ namespace rage #endif }; #pragma pack(pop) - static_assert(sizeof(rage::tlsContext) == 0x1701); + static_assert(sizeof(rage::tlsContext) == 0x1704); } \ No newline at end of file diff --git a/rage/vector.hpp b/rage/vector.hpp index 71087ed..7a92b6e 100644 --- a/rage/vector.hpp +++ b/rage/vector.hpp @@ -84,4 +84,4 @@ namespace rage typedef vector4 fvector4; typedef matrix34 fmatrix34; typedef matrix44 fmatrix44; -} \ No newline at end of file +} diff --git a/rdr2.rcnet b/rdr2.rcnet index e44c271ade997956128db62364fd6c797dae1291..eddc6d2d358a6f0d25e47306b4839680272460ff 100644 GIT binary patch literal 16597 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 +#include "../rage/joaat.hpp" + +#pragma pack(push, 8) +namespace rage +{ + class datBitBuffer; + class netLoggingInterface; + class scrThread; + + class scriptIdBase + { + public: + virtual ~scriptIdBase() = default; + + // Assumes the script thread's identity. + virtual void FromThread(scrThread*) {}; + + // Returns whether the hash of the script id is valid. + virtual bool IsValid() { return false; }; + + // Gets the hash of the script id. + virtual joaat_t* GetHash(joaat_t* out) { return 0; }; + + // Gets an unknown value from the script id. + virtual std::uint32_t* GetInstanceHash(std::uint32_t* out) { return 0; }; + + // Serializes the script id from the buffer. + virtual void Deserialize(datBitBuffer* buffer) {}; + + // Serializes the script id to the buffer. + virtual void Serialize(datBitBuffer* buffer) {}; + + // Calculates bitbuffer size. + virtual std::uint32_t CalculateSize() { return 0; }; + + // Calls _0x40 and returns its value added to another value. (packed size?) + virtual std::uint32_t CalculateSize2() { return 0; }; + + // Gets the hash of the script id again. + virtual joaat_t GetHash2() { return 0; } + + // Copies the information of other to this object. + virtual void FromScriptId(scriptIdBase* other) {} + + // Returns whether the other script id is equal. + virtual bool operator==(scriptIdBase*) { return false; }; + + virtual bool SameScriptHash(scriptIdBase*) { return false; }; + }; +} +#pragma pack(pop) \ No newline at end of file