ongoing refactor of serialization and various cleanup
This commit is contained in:
@@ -205,36 +205,36 @@ The canonical allocation function is defined in `EntityManager.h`:
|
||||
The implementation replaces the flawed `RegisterEntity` routine in [`Game/Entity/EntityManager.cpp`](file:///w:/Classified/Juliet/Game/Entity/EntityManager.cpp):
|
||||
|
||||
```cpp
|
||||
[[nodiscard]] Entity* AllocateEntity(EntityManager& manager, Class* classPtr)
|
||||
[[nodiscard]] Entity* AllocateEntity(EntityManager& manager, Class* derivedClassPtr)
|
||||
{
|
||||
Assert(classPtr != nullptr);
|
||||
Assert(classPtr->kind < ENTITY(Count));
|
||||
Assert(classPtr->size_of >= sizeof(entity_template));
|
||||
Assert(classPtr->alignment > 0);
|
||||
Assert(derivedClassPtr != nullptr);
|
||||
Assert(derivedClassPtr->kind < ENTITY(Count));
|
||||
Assert(derivedClassPtr->size_of >= sizeof(entity_template));
|
||||
Assert(derivedClassPtr->alignment > 0);
|
||||
|
||||
// 1. Allocate uninitialized Base Entity in the contiguous VectorArena
|
||||
Entity baseTemplate{};
|
||||
baseTemplate.ID = EntityManager::ID++;
|
||||
baseTemplate.Kind = classPtr;
|
||||
baseTemplate.Derived = nullptr;
|
||||
baseTemplate.X = 0.0f;
|
||||
baseTemplate.Y = 0.0f;
|
||||
baseTemplate.Z = 0.0f;
|
||||
baseTemplate.IsDirty = true;
|
||||
baseTemplate.ID = EntityManager::ID++;
|
||||
baseTemplate.DerivedKind = derivedClassPtr;
|
||||
baseTemplate.Derived = nullptr;
|
||||
baseTemplate.X = 0.0f;
|
||||
baseTemplate.Y = 0.0f;
|
||||
baseTemplate.Z = 0.0f;
|
||||
baseTemplate.IsDirty = true;
|
||||
|
||||
manager.Entities.PushBack(baseTemplate);
|
||||
Entity* basePtr = manager.Entities.Back();
|
||||
Assert(basePtr != nullptr);
|
||||
|
||||
// 2. Allocate zeroed derived component memory in the typed arena
|
||||
typed_entity_array& typedArray = manager.by_type[classPtr->kind];
|
||||
typed_entity_array& typedArray = manager.by_type[derivedClassPtr->kind];
|
||||
Assert(typedArray.arena != nullptr);
|
||||
|
||||
void* rawMemory = ArenaPushSize(
|
||||
typedArray.arena,
|
||||
classPtr->size_of,
|
||||
classPtr->alignment,
|
||||
true JULIET_DEBUG_PARAM(kEntity_type_names[classPtr->kind]));
|
||||
derivedClassPtr->size_of,
|
||||
derivedClassPtr->alignment,
|
||||
true JULIET_DEBUG_PARAM(kEntity_type_names[derivedClassPtr->kind]));
|
||||
Assert(rawMemory != nullptr);
|
||||
|
||||
auto* derivedTemplate = reinterpret_cast<entity_template*>(rawMemory);
|
||||
@@ -330,9 +330,9 @@ entity_instance
|
||||
0x0100000000000042
|
||||
; class
|
||||
Inert
|
||||
; base_version
|
||||
; version
|
||||
1
|
||||
; derived_version
|
||||
; class_version
|
||||
1
|
||||
; position
|
||||
0.43 0.32 1.56
|
||||
@@ -342,7 +342,8 @@ Inert
|
||||
|
||||
#### Important: No Header Structs for Derived Types
|
||||
- **Derived types NEVER require their own file header**: You do **not** write an `InertHeader`, `DoorHeader`, or `PlayerHeader`. Derived types only serialize their own member variables.
|
||||
- **No binary `EntityFileHeader` struct is needed**: Under the `; variable_name\nvalues` text format, there is no packed binary C-struct header at all. The common properties (`; id`, `; class`, `; base_version`, `; derived_version`, `; position`) are standard text Key-Value nodes read by the exact same `archive` parser.
|
||||
- **Universal `; version` + optional `; class_version`**: Every `.jasset` file has a universal `; version` tag. For entity assets, `; version` governs base entity properties (`kEntityBaseVersion`), while an optional `; class_version` governs derived class properties (`Class::Version`). Non-entity assets like `WorldSettings.jasset` only have `; version`.
|
||||
- **No binary `EntityFileHeader` struct is needed**: Under the `; variable_name\nvalues` text format, there is no packed binary C-struct header at all. The common properties (`; id`, `; class`, `; version`, `; class_version`, `; position`) are standard text Key-Value nodes read by the exact same `archive` parser.
|
||||
|
||||
### 4.2 Eliminating Intermediate Stack Allocations
|
||||
Under the new pipeline:
|
||||
@@ -351,7 +352,7 @@ Under the new pipeline:
|
||||
3. The engine reads `; class` (e.g. `"Inert"`) and resolves `Class* classPtr = FindClassByName(className)`.
|
||||
4. `AllocateEntity(manager, classPtr)` is called immediately. Memory for both base and derived components is allocated in-place in their permanent engine arenas.
|
||||
5. Base properties (`id`, `position`, etc.) are read directly into `*basePtr` via `SerializeEntityBase`.
|
||||
6. `classPtr->serialize_fct(ar, basePtr->Derived, derivedVersion)` is called. Derived fields stream **directly into the typed arena** without temporary staging buffers or stack copies.
|
||||
6. `classPtr->serialize_fct(ar, basePtr->Derived, classVersion)` is called. Derived fields stream **directly into the typed arena** without temporary staging buffers or stack copies.
|
||||
|
||||
### 4.3 Runtime Class Resolution
|
||||
To ensure fast and safe type lookup during file deserialization:
|
||||
@@ -440,18 +441,13 @@ To ensure fast and safe type lookup during file deserialization:
|
||||
Entity* basePtr = AllocateEntity(manager, classPtr);
|
||||
Assert(basePtr != nullptr);
|
||||
|
||||
// 3. Read base versions and properties in-place
|
||||
uint16 baseVersion = 1;
|
||||
uint16 derivedVersion = 1;
|
||||
SerializeProp(ar, "base_version", baseVersion);
|
||||
SerializeProp(ar, "derived_version", derivedVersion);
|
||||
// 3. Serialize Base Entity in-place using Entity::Kind
|
||||
SerializeClassInstance(ar, Entity::Kind, basePtr);
|
||||
|
||||
SerializeEntityBase(ar, *basePtr, baseVersion);
|
||||
|
||||
// 4. Stream derived properties in-place directly into the typed arena
|
||||
if (classPtr->serialize_fct != nullptr)
|
||||
// 4. Stream derived properties in-place using basePtr->DerivedKind
|
||||
if (basePtr->DerivedKind != nullptr && basePtr->Derived != nullptr)
|
||||
{
|
||||
classPtr->serialize_fct(ar, basePtr->Derived, derivedVersion);
|
||||
SerializeClassInstance(ar, basePtr->DerivedKind, basePtr->Derived);
|
||||
}
|
||||
|
||||
// Freshly loaded entity matches disk state exactly
|
||||
@@ -663,13 +659,15 @@ To solve this, `Entity` in [`Game/Entity/Entity.h`](file:///w:/Classified/Juliet
|
||||
```cpp
|
||||
struct Entity final
|
||||
{
|
||||
EntityID ID = 0;
|
||||
Class* Kind = nullptr;
|
||||
DerivedType Derived = nullptr;
|
||||
float X = 0.0f;
|
||||
float Y = 0.0f;
|
||||
float Z = 0.0f;
|
||||
bool IsDirty = false;
|
||||
DECLARE_ENTITY() // static Class* Kind; (Entity's own Class descriptor)
|
||||
|
||||
EntityID ID = 0;
|
||||
Class* DerivedKind = nullptr; // Pointer to derived class descriptor (e.g. Inert::Kind)
|
||||
DerivedType Derived = nullptr; // Pointer to derived component memory
|
||||
float X = 0.0f;
|
||||
float Y = 0.0f;
|
||||
float Z = 0.0f;
|
||||
bool IsDirty = false;
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user