added class dependency generator for IDA scripts, so you can simply copy paste the generated header file and it should compile fine (more to test when I have time)

This commit is contained in:
EricPlayZ
2025-04-04 01:55:30 +03:00
parent ef14ed13c5
commit 5564beddb8
2 changed files with 115 additions and 56 deletions

View File

@ -1,4 +1,5 @@
import os
from typing import Optional
from ExportClassH import JSONGen, Utils, Config
from ExportClassH.ClassDefs import ParsedClass, ParsedFunction, ParsedClassVar
@ -123,16 +124,18 @@ def GenerateClassContent(targetClass: ParsedClass, indentLevel: str) -> list[str
hasAnyContent = bool(contentLines)
# Insert access specifier if needed
if not firstVarOrFuncAccess and targetClass.type == "class":
if not firstVarOrFuncAccess and targetClass.type == "class" and hasAnyContent:
contentLines.insert(1, f"{indentLevel}public:")
childClassDefinitions: list[str] = []
for parsedClass in targetClass.childClasses.values():
classDefinition = GenerateClassDefinition(parsedClass, indentLevel + "\t")
classContent = GenerateClassContent(parsedClass, indentLevel + "\t")
childClassesLen = len(targetClass.childClasses.values())
for i, parsedClass in enumerate(targetClass.childClasses.values()):
childClassDefinition = GenerateClassDefinition(parsedClass, indentLevel + "\t")
childClasSContent = GenerateClassContent(parsedClass, indentLevel + "\t")
if i != 0 and (i != childClassesLen or hasAnyContent):
childClassDefinitions.append("")
childClassDefinitions.extend(classDefinition[:len(classDefinition) - 1] + classContent + classDefinition[len(classDefinition) - 1:])
childClassDefinitions.append("")
childClassDefinitions.extend(childClassDefinition[:len(childClassDefinition) - 1] + childClasSContent + childClassDefinition[len(childClassDefinition) - 1:])
if (hasAnyContent):
contentLines.insert(0, "#pragma region GENERATED by ExportClassToCPPH.py")
@ -154,11 +157,49 @@ def GenerateClassDefinition(targetClass: ParsedClass, indentLevel: str, forwardD
classDefLines.append(f"{indentLevel}}};")
return classDefLines
def GenerateClassDependencyDefinition(classDependency: str, indentLevel: str, parsedClassesDict: dict[str, ParsedClass]) -> list[str]:
"""Generate a class definition from a list of methods."""
classDependencyList = Utils.SplitByClassSeparatorOutsideTemplates(classDependency)
classDependencyListLen = len(classDependencyList)
alreadyCheckedDependenciesList: list[str] = []
currentClassDependency: Optional[ParsedClass] = None
classDefLines: list[str] = []
classDefBracketClosingLines: list[str] = []
for i, dependency in enumerate(classDependencyList, 1):
alreadyCheckedDependenciesList.append(dependency)
if not currentClassDependency:
currentClassDependency = parsedClassesDict.get(dependency)
if not currentClassDependency:
continue
else:
currentClassDependency = currentClassDependency.childClasses.get("::".join(alreadyCheckedDependenciesList))
if not currentClassDependency:
continue
canCurrentClassHaveEnclosure = currentClassDependency.type != "enum" and classDependencyListLen > 1 and i != classDependencyListLen
classDefLines.append(f"{indentLevel}{currentClassDependency.type} {currentClassDependency.name}{' {' if canCurrentClassHaveEnclosure else ';'}")
if canCurrentClassHaveEnclosure:
if currentClassDependency.type == "class":
classDefLines.append(f"{indentLevel}public:")
classDefBracketClosingLines.append(f"{indentLevel}}};")
indentLevel += "\t"
classDefLines.extend(classDefBracketClosingLines)
return classDefLines
def GenerateHeaderCode(targetClass: ParsedClass, parsedClassesDict: dict[str, ParsedClass]) -> list[str]:
"""Generate header code for a standard class (not nested)."""
global indentLevel
fullClassDefinition: list[str] = []
for classDependency in targetClass.classDependencies:
classDependencyDefinition = GenerateClassDependencyDefinition(classDependency, indentLevel, parsedClassesDict)
fullClassDefinition.extend(classDependencyDefinition)
fullClassDefinition.append("")
for namespace in targetClass.parentNamespaces:
fullClassDefinition.append(f"{indentLevel}namespace {namespace} {{")
indentLevel += "\t"
@ -241,10 +282,10 @@ def ExportClassHeaders():
parsedClassesDict = JSONGen.GetAllParsedClasses()
JSONGen.MoveChildClasses(parsedClassesDict)
for (parsedClassName, parsedClass) in parsedClassesDict.items():
for parsedClass in parsedClassesDict.values():
headerCodeLines = GenerateHeaderCode(parsedClass, parsedClassesDict)
headerCode: str = "\n".join(headerCodeLines)
WriteHeaderToFile(parsedClass, headerCode, f"{parsedClass.name}.h" if parsedClass.type != "namespace" else "")
# classDefinition = GenerateClassDefinition(parsedClass, indentLevel)
# classContent = GenerateClassContent(parsedClass, indentLevel)

View File

@ -1,6 +1,72 @@
#pragma once
#include <EGSDK\Imports.h>
namespace cbs {
class CPcidPath;
};
namespace cbs {
class CEntity;
};
namespace cbs {
class CEntityPointer;
};
namespace cbs {
class CPointer;
};
namespace cbs {
class CPcidPathView;
};
namespace cbs {
enum pcid_t;
};
namespace ttl {
class string_const;
};
class SpawnContext;
class ILevel;
class mtx34;
namespace Replication {
class CreateObjectOptions;
};
struct PresetId;
namespace ttl {
class set;
};
class CRTTIField;
namespace cbs {
struct WorldIndex;
};
namespace ttl {
class string_base;
};
namespace cbs {
class PrefabEntityComponent;
};
namespace ttl {
class span;
};
namespace ttl {
class vector;
};
namespace cbs {
#pragma region GENERATED by ExportClassToCPPH.py
enum pcid_t;
@ -95,10 +161,8 @@ namespace cbs {
#pragma endregion
};
public:
class CPointer;
public:
class CSystemWorldData;
class CBaseObject {
@ -675,7 +739,6 @@ namespace cbs {
public:
#pragma region GENERATED by ExportClassToCPPH.py
struct ResultType;
GAME_IMPORT CEntityGenerator(cbs::CEntityGenerator&&);
GAME_IMPORT CEntityGenerator(cbs::Prefab const*, SpawnContext&);
GAME_IMPORT CEntityGenerator();
@ -1723,7 +1786,6 @@ namespace cbs {
struct SVirtualField;
enum ESavePrefabHierarchy;
GAME_IMPORT static char const* const EXTDTL_FLT_POSTFIX;
GAME_IMPORT static char const* const EXT_FLT_POSTFIX;
GAME_IMPORT static char const* const FLT_POSTFIX;
@ -2658,7 +2720,6 @@ namespace cbs {
GAME_IMPORT bool IsEmpty();
#pragma endregion
};
GAME_IMPORT static uint32_t const UNAVAILABLE_IDX;
GAME_IMPORT static bool __INTERNAL_crtti_fields_initialized_field;
GAME_IMPORT static class rtti::Type& m_RTTI;
@ -2885,7 +2946,6 @@ namespace cbs {
#pragma endregion
};
public:
class ICallable;
struct WorldIndex;
@ -3230,7 +3290,6 @@ namespace cbs {
struct SAudioHook;
struct SPlayingEventParams;
GAME_IMPORT static bool __INTERNAL_crtti_fields_initialized_field;
GAME_IMPORT static class rtti::Type& m_RTTI;
GAME_IMPORT static class cbs::CComponentSystem<class cbs::CoAudioEventControl, class cbs::CSystemWorldData<class cbs::CoAudioEventControl>>& s_System;
@ -3726,7 +3785,6 @@ namespace cbs {
public:
#pragma region GENERATED by ExportClassToCPPH.py
struct PinnedPointer;
GAME_IMPORT class cbs::CBaseObject* AllocateComponent(cbs::WorldIndex, cbs::SystemIndex);
GAME_IMPORT void DeallocateComponent(cbs::detail::Handle);
GAME_IMPORT class cbs::CBaseObject* GetComponentImpl(cbs::detail::Handle);
@ -4006,7 +4064,6 @@ namespace cbs {
#pragma endregion
};
public:
class ComponentPoolEnumerator;
enum ComponentPoolEnumeratorMode;
@ -4638,7 +4695,6 @@ namespace cbs {
#pragma endregion
};
public:
class CAbstractSystem;
class CEntityMgr {
@ -4665,17 +4721,14 @@ namespace cbs {
#pragma endregion
};
public:
class CComponentSystem;
public:
class CComponentBaseSystem;
struct SPrefabConfigurationOverrideInfo;
enum VisitResult;
public:
class CSystem;
class PrefabAreaComponent {
@ -6009,7 +6062,6 @@ namespace cbs {
GAME_IMPORT virtual enum cbs::VisitResult Visit(cbs::PrefabEntityComponentHierarchy const&);
#pragma endregion
};
GAME_IMPORT PrefabDataRetrieval(cbs::Prefab const*, cbs::CPcidPath const&);
GAME_IMPORT void DumpResults(fs::ifile&) const;
GAME_IMPORT bool Execute();
@ -9504,11 +9556,9 @@ namespace cbs {
GAME_IMPORT void Send() const;
#pragma endregion
};
};
namespace msg {
public:
class SingleMessagePipeOut;
class IMessageData {
@ -10331,7 +10381,6 @@ namespace cbs {
#pragma endregion
};
public:
class MessagePipeId;
class MessageTransmitterPipe {
@ -10427,14 +10476,11 @@ namespace cbs {
GAME_IMPORT virtual void OnReceive(CRTTIObject*, cbs::msg::Message const&);
#pragma endregion
};
};
namespace detail {
struct MessagePipeReceiver;
};
};
namespace ps {
@ -10524,7 +10570,6 @@ namespace cbs {
public:
#pragma region GENERATED by ExportClassToCPPH.py
enum GUARD_STATE;
GAME_IMPORT static bool s_ForceBakeData;
GAME_IMPORT static enum cbs::ps::CStorage::GUARD_STATE s_Guard;
GAME_IMPORT static int s_StaticEntitiesRestoreDefaultsCounter;
@ -10872,16 +10917,13 @@ namespace cbs {
struct FromStringOptions;
enum EStringPathFormat;
GAME_IMPORT static class cbs::ps::IStorage* GetInstance();
#pragma endregion
};
enum ReplicationRule;
public:
class CStorageReplicator;
};
namespace prefabs {
@ -10890,7 +10932,6 @@ namespace cbs {
public:
#pragma region GENERATED by ExportClassToCPPH.py
struct ValueView;
private:
GAME_IMPORT GamePrefabValuesContainer(void*);
public:
@ -10936,11 +10977,9 @@ namespace cbs {
namespace impl {
#pragma region GENERATED by ExportClassToCPPH.py
struct MemoryDesc;
GAME_IMPORT void DumpPrefabElementPaths(CLevel const*);
#pragma endregion
};
GAME_IMPORT uint64_t GTotalApplyValuesTime;
GAME_IMPORT uint64_t GTotalCreatePVCTime;
@ -10973,7 +11012,6 @@ namespace cbs {
#pragma endregion
};
public:
class IPropertySet;
class IProperty {
@ -10994,13 +11032,11 @@ namespace cbs {
};
struct PropertyId;
};
namespace Call {
#pragma region GENERATED by ExportClassToCPPH.py
enum TYPE;
GAME_IMPORT static class IRTTIEnumerationTyped<enum cbs::Call::TYPE> const* GetRTTI();
#pragma endregion
};
@ -11031,62 +11067,47 @@ namespace cbs {
namespace EAreaType {
#pragma region GENERATED by ExportClassToCPPH.py
enum TYPE;
GAME_IMPORT static class IRTTIEnumerationTyped<enum cbs::simple::EAreaType::TYPE> const* GetRTTI();
#pragma endregion
};
namespace FRendering {
enum TYPE;
};
};
namespace contracts {
public:
class ApiFindComponent;
public:
class ApiFindComponentExact;
public:
class ApiGatherComponents;
public:
class ApiGetInterface;
public:
class ApiInvalidatePointer;
public:
class ApiComponentOnEntityChanged;
public:
class ApiModifyMessagePipeReceivers;
public:
class ApiEntityInterfaceChainAccess;
};
namespace EActivityState {
#pragma region GENERATED by ExportClassToCPPH.py
enum TYPE;
GAME_IMPORT static class IRTTIEnumerationTyped<enum cbs::EActivityState::TYPE> const* GetRTTI();
#pragma endregion
};
namespace detail {
enum Handle;
};
namespace FComponent {
#pragma region GENERATED by ExportClassToCPPH.py
enum TYPE;
GAME_IMPORT static class IRTTIEnumerationTyped<enum cbs::FComponent::TYPE> const* GetRTTI();
#pragma endregion
};
@ -11094,7 +11115,6 @@ namespace cbs {
namespace FEntity {
#pragma region GENERATED by ExportClassToCPPH.py
enum TYPE;
GAME_IMPORT static class IRTTIEnumerationTyped<enum cbs::FEntity::TYPE> const* GetRTTI();
#pragma endregion
};
@ -11109,9 +11129,7 @@ namespace cbs {
GAME_IMPORT void* Reallocate(cbs::memory::Category, void*, uint64_t);
#pragma endregion
};
};
GAME_IMPORT class cbs::PrefabManager* g_PrefabManager;
GAME_IMPORT bool operator==(cbs::CPcidPath const&, cbs::CPcidPath const&);