entity per world

This commit is contained in:
Patedam committed 2026-10-16 21:33:57 -04:00
1 parent 16ba641d8a
commit b70e2d21d2
15 files changed
+694 -19

No files matched your search

+42
View File
@@ -21,6 +21,48 @@ internal void serialize(Archive& ar, uint16 /*version*/, Entity& entity)
SERIALIZE(ar, position, entity.position);
}
String format_entity_id(NonNullPtr<Arena> arena, EntityID entity_id)
{
// Format:
// U = UserID
// LC = Local Entity Counter
// UU_LCLCLCLCLCLCLC
uint8 user_id = get_user_id(entity_id);
uint64 counter = get_local_counter(entity_id);
constexpr size_t kBufferSize = 18;
char* buffer = ArenaPushArray<char>(arena, kBufferSize);
Assert(buffer);
juliet_snprintf(buffer, kBufferSize, "%02X_%014llX", (unsigned int)user_id, counter);
return { buffer, kBufferSize - 1 };
}
bool parse_entity_id(String str, EntityID& out_id)
{
bool result = false;
out_id = kInvalid_entity_id;
if (!(str.Size != 17 || str.Str == nullptr || str.Str[2] != '_'))
{
char user_hex[3]{ str.Str[0], str.Str[1], '\0' };
char* end = user_hex;
uint8 user_id = strtoul(user_hex, &end, 16);
if (end != user_hex && user_id != kInvalid_user_id)
{
char* counter_hex = str.Str + 3;
end = counter_hex;
uint64 counter = strtoull(counter_hex, &end, 16);
if (end != counter_hex && counter < kEntityID_user_id_mask)
{
out_id = make_entity_id(user_id, counter);
result = true;
}
}
}
return result;
}
const Class* resolve_entity_class(uint8 kind, uint32 crc)
{
Assert(kind <= ENTITY(Count));
+32
View File
@@ -30,6 +30,32 @@ concept EntityConcept = requires(EntityType entity) {
requires std::same_as<decltype(entity.base), Entity*>;
};
inline constexpr EntityID make_entity_id(uint8 user_id, uint64 local_counter)
{
Assert(user_id != kInvalid_user_id);
Assert((local_counter & kEntityID_user_id_mask) == kInvalid_entity_id);
EntityID result = kInvalid_user_id;
result = ((EntityID)user_id << kEntityID_user_id_shift) | (local_counter & kEntityID_user_id_mask);
return result;
}
inline constexpr uint8 get_user_id(EntityID entity_id)
{
return (((uint8)entity_id & kEntityID_user_id_mask) << kEntityID_user_id_shift);
}
inline constexpr uint64 get_local_counter(EntityID entity_id)
{
return (uint64)entity_id & kEntityID_user_id_mask;
}
inline constexpr bool is_entity_id_valid(EntityID entity_id)
{
bool result = entity_id != kInvalid_entity_id;
return result;
}
template <typename EntityType>
requires EntityConcept<EntityType>
[[nodiscard]] bool IsA(const Entity* entity)
@@ -66,6 +92,12 @@ template <typename EntityType>
void serialize(Archive& ar, NonNullPtr<Entity> entity);
JULIET_API uint8 get_local_user_id();
JULIET_API String format_entity_id(NonNullPtr<Arena> arena, EntityID id);
JULIET_API bool parse_entity_id(String str, EntityID& outId);
[[nodiscard]] const Class* find_class_by_name(String name);
[[nodiscard]] const Class* resolve_entity_class(uint8 kind, uint32 crc);
+25
View File
@@ -7,6 +7,7 @@
#include <Entity/entity_types.h>
#include <game.h>
#include <Graphics/MeshRenderer.h>
#include "Engine/user.h"
EntityID EntityManager::ID = 0;
@@ -45,6 +46,17 @@ EntityManager& GetEntityManager()
return *entityManager;
}
EntityID generate_next_entity_id(EntityManager& manager)
{
UserID user = get_local_user_id();
Assert(user != kInvalid_user_id);
Assert(manager.next_local_counter != kEntityID_user_id_mask);
EntityID new_id = make_entity_id(user, manager.next_local_counter);
manager.next_local_counter += 1ULL;
return new_id;
}
EntityTemplate* RegisterEntity(EntityManager& manager, Entity* base, DerivedType entity)
{
base->ID = EntityManager::ID++;
@@ -143,3 +155,16 @@ Entity* deserialize_entity(Archive& ar, EntityManager& manager)
return entity_base;
}
void update_local_counter(EntityManager& manager, EntityID entity_id)
{
uint8 user_id = get_local_user_id();
if (get_user_id(entity_id) == user_id)
{
uint64 counter = get_local_counter(entity_id);
if (counter >= manager.next_local_counter)
{
manager.next_local_counter = counter + 1ULL;
}
}
}
+3 -1
View File
@@ -18,6 +18,7 @@ struct typed_entity_array
struct EntityManager
{
static EntityID ID;
uint64 next_local_counter = 1ULL;
// TODO: Should be a pool
VectorArena<Entity, 100'000> Entities;
@@ -31,4 +32,5 @@ EntityManager& GetEntityManager();
EntityTemplate* RegisterEntity(EntityManager& manager, Entity* base, DerivedType entity);
[[nodiscard]] Entity* allocate_entity(EntityManager& manager, NonNullPtr<const Class> derived_type_class);
void UpdateEntityManager(EntityManager& manager);
[[nodisacrd]] Entity* deserialize_entity(Archive& archive, EntityManager& manager);
[[nodiscard]] Entity* deserialize_entity(Archive& archive, EntityManager& manager);
void update_local_counter(EntityManager& manager, EntityID entity_id);
+6
View File
@@ -7,6 +7,12 @@ struct Class;
using DerivedType = void*;
using EntityID = uint64_t;
constexpr uint8 kInvalid_user_id = 0U;
constexpr EntityID kInvalid_entity_id = 0ULL;
constexpr EntityID kEntityID_user_id_shift = 56ULL;
constexpr EntityID kEntityID_user_id_mask = 0xFF00'0000'0000'0000ULL;
// clang-format off
#define ENTITY_TYPE_LIST(X) X(Inert),