entity per world
This commit is contained in:
1 parent
16ba641d8a
commit
b70e2d21d2
15 files changed
+694
-19
No files matched your search
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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),
|
||||
|
||||
|
||||
Reference in new issue
Block a user