Nebula
Loading...
Searching...
No Matches
world.h
Go to the documentation of this file.
1#pragma once
2//------------------------------------------------------------------------------
9//------------------------------------------------------------------------------
10#include "core/refcounted.h"
11#include "entity.h"
12#include "entitypool.h"
13#include "component.h"
15#include "util/queue.h"
16#include "category.h"
17#include "processorid.h"
18#include "processor.h"
20#include "frameevent.h"
21#include "util/fourcc.h"
22
23namespace MemDb
24{
25class Database;
26}
27namespace Util
28{
29class Blob;
30}
31
32namespace Game
33{
34
35class PackedLevel;
36
38World* GetWorld(WorldHash worldHash);
40World* GetWorld(WorldId worldId);
41
42// which mode a world is currently running in. A processor only runs if its phase
43// allows the mode the world is in.
44enum WorldMode : uint8_t
45{
46 EditorMode = 0, // world is not simulating
47 PlayMode = 1, // world is running gameplay
48};
49
50// returns the phase bit that corresponds to a world mode
51inline ProcessorPhase
53{
54 return mode == PlayMode ? PlayPhase : EditorPhase;
55}
56
57//------------------------------------------------------------------------------
84class World
85{
86public:
87 // Generally, only the game server should create worlds
89 ~World();
90
92 WorldHash GetWorldHash() const;
94 WorldId GetWorldId() const;
95
97 Entity CreateEntity(bool immediate = true);
99 void DeleteEntity(Entity entity);
100
102 bool IsValid(Entity entity) const;
104 bool HasInstance(Entity entity) const;
105
108
110 template <typename TYPE>
111 TYPE* AddComponent(Entity entity);
114 template <typename TYPE>
115 void AddComponent(Entity entity, TYPE const& component);
117 void* AddComponent(Entity entity, ComponentId component);
119 void* AddComponent(Entity entity, ComponentId component, const void* value);
120
122 template <typename TYPE>
123 bool HasComponent(Entity entity) const;
125 bool HasComponent(Entity entity, ComponentId component) const;
126
128 template <typename TYPE>
129 void RemoveComponent(Entity entity);
131 void RemoveComponent(Entity entity, ComponentId component);
132
134 template <typename TYPE>
135 void SetComponent(Entity entity, TYPE const& value);
137 template <typename TYPE>
138 TYPE GetComponent(Entity entity);
139
141 void MarkAsModified(Game::Entity entity);
142
144 Dataset Query(Filter filter);
148
151
155 void UnloadLevel(PackedLevel* level);
157 bool ExportLevel(Util::String const& path);
158
161
164
165 // -- Internal methods -- Use with caution! --
166
168 MemDb::RowId GetInstance(Entity entity) const;
170 void SetComponentValue(Entity entity, ComponentId component, void* value, uint64_t size);
172 void ReinitializeComponent(Entity entity, ComponentId component, void* value, uint64_t size);
176 static void Override(World* src, World* dst);
180 void DeallocateEntityId(Entity entity);
184 MemDb::RowId AllocateInstance(Entity entity, MemDb::TableId table, Util::Blob const* const data = nullptr);
186 void InitializeInstance(Entity entity);
188 void InitializeInstance(Entity entity, MemDb::TableId tableId, MemDb::RowId row);
189 void FinalizeAllocate(Entity entity);
191 void DeallocateInstance(MemDb::TableId table, MemDb::RowId instance);
193 void DeallocateInstance(Entity entity);
195 void Defragment(MemDb::TableId tableId);
197 void* GetInstanceBuffer(MemDb::TableId const tableId, uint16_t partitionId, ComponentId const component);
199 void* GetColumnData(MemDb::TableId const tableId, uint16_t partitionId, MemDb::ColumnIndex const column);
206
209
210 void RenderDebug();
211
212private:
213 friend class GameServer;
214 friend class PackedLevel;
215
220
225
227 {
229 ComponentId componentId = ComponentId::Invalid();
231 void* data = nullptr;
232 };
233
239
240 // These functions are called from game server
241 void Start();
242 void BeginFrame();
243 void SimFrame();
244 void EndFrame();
245 void OnLoad();
246 void OnSave();
247 void ManageEntities();
248 void Reset();
249 void PrefilterProcessors();
251 void ClearDecayBuffers();
252
255
257 MemDb::RowId Migrate(Entity entity, MemDb::TableId newTable);
259 void Migrate(
260 Util::Array<Entity> const& entities,
261 MemDb::TableId fromTable,
262 MemDb::TableId newTable,
264 );
265
267 void DecayComponent(ComponentId component, MemDb::TableId tableId, MemDb::ColumnIndex column, MemDb::RowId instance);
268
271
276
300 bool cacheValid = false;
307};
308
309//------------------------------------------------------------------------------
312inline WorldHash
314{
315 return this->hash;
316}
317
318//------------------------------------------------------------------------------
321inline WorldId
323{
324 return this->worldId;
325}
326
327//------------------------------------------------------------------------------
330template <typename TYPE>
331inline void
332World::SetComponent(Entity entity, TYPE const& value)
333{
334#if NEBULA_DEBUG
335 n_assert2(
336 !this->pipeline.IsRunningAsync(),
337 "Settings components in arbitrary entities while executing an async processor is currently not supported!"
338 );
339#endif
340
341#if NEBULA_DEBUG
342 n_assert2(
344 "SetComponent: Provided value's type is not the correct size for the given ComponentId."
345 );
346#endif
347 EntityMapping mapping = this->GetEntityMapping(entity);
348 TYPE* ptr = (TYPE*)this->GetInstanceBuffer(mapping.table, mapping.instance.partition, GetComponentId<TYPE>());
349 *(ptr + mapping.instance.index) = value;
350}
351
352//------------------------------------------------------------------------------
355template <typename TYPE>
356inline TYPE
358{
359#if NEBULA_DEBUG
360 n_assert2(
361 !this->pipeline.IsRunningAsync(),
362 "Getting components from entities while executing an async processor is currently not supported!"
363 );
364#endif
365
366#if NEBULA_DEBUG
367 n_assert2(
369 "GetComponent: Provided value's type is not the correct size for the given ComponentId."
370 );
371#endif
372 EntityMapping mapping = this->GetEntityMapping(entity);
373 TYPE* ptr = (TYPE*)this->GetInstanceBuffer(mapping.table, mapping.instance.partition, GetComponentId<TYPE>());
374 return *(ptr + mapping.instance.index);
375}
376
377//------------------------------------------------------------------------------
380template <typename TYPE>
381inline void
383{
384#if NEBULA_DEBUG
385 n_assert2(
386 !this->pipeline.IsRunningAsync(),
387 "Removing components from entities while executing an async processor is currently not supported!"
388 );
389#endif
391 .entity = entity,
392 .componentId = Game::GetComponentId<TYPE>(),
393 };
394 this->removeComponentQueue.Append(cmd);
395}
396
397//------------------------------------------------------------------------------
400template <typename TYPE>
401inline bool
403{
404 return this->HasComponent(entity, Game::GetComponentId<TYPE>());
405}
406
407//------------------------------------------------------------------------------
410template <typename TYPE>
411inline TYPE*
413{
414 /*
415 We could possibly support this by either having thread local allocators and
416 staged queues and gathering after the processors have finished (must clear
417 allocators by issuing a separate job for this at the end of the frame), or by
418 just introducing a simple mutex.
419 */
420#if NEBULA_DEBUG
421 n_assert2(
422 !this->pipeline.IsRunningAsync(), "Adding component to entities while in an async processor is currently not supported!"
423 );
424#endif
426#if NEBULA_DEBUG
427 n_assert(MemDb::AttributeRegistry::TypeSize(id) == sizeof(TYPE));
428 //n_assert(!this->HasComponent<TYPE>(entity));
429#endif
430 TYPE* data = this->componentStageAllocator.Alloc<TYPE>();
431 const void* defaultValue = MemDb::AttributeRegistry::DefaultValue(id);
432 Memory::Copy(defaultValue, data, sizeof(TYPE));
433
435 .entity = entity,
436 .componentId = id,
437 .dataSize = sizeof(TYPE),
438 .data = data,
439 };
440 this->addStagedQueue.Append(cmd);
441
443 ComponentInterface* cInterface;
444 cInterface = static_cast<ComponentInterface*>(attr);
445
446 if (this->componentInitializationEnabled && cInterface->Init != nullptr)
447 {
448 // run initialization function if it exists.
449 cInterface->Init(this, entity, data);
450 }
451
452 return data;
453}
454
455//------------------------------------------------------------------------------
458template <typename TYPE>
459inline void
460World::AddComponent(Entity entity, TYPE const& component)
461{
462#if NEBULA_DEBUG
463 n_assert2(
464 !this->pipeline.IsRunningAsync(), "Adding component to entities while in an async processor is currently not supported!"
465 );
466#endif
468#if NEBULA_DEBUG
469 n_assert(MemDb::AttributeRegistry::TypeSize(id) == sizeof(TYPE));
470 //n_assert(!this->HasComponent<TYPE>(entity));
471#endif
472 TYPE* data = this->componentStageAllocator.Alloc<TYPE>();
473 Memory::Copy(&component, data, sizeof(TYPE));
474
476 .entity = entity,
477 .componentId = id,
478 .dataSize = sizeof(TYPE),
479 .data = data,
480 };
481 this->addStagedQueue.Append(cmd);
482
484 ComponentInterface* cInterface;
485 cInterface = static_cast<ComponentInterface*>(attr);
486
487 if (this->componentInitializationEnabled && cInterface->Init != nullptr)
488 {
489 // run initialization function if it exists.
490 cInterface->Init(this, entity, data);
491 }
492}
493
494template <>
496template <>
498template <>
500
501template <>
503template <>
505template <>
507
508} // namespace Game
These are registered to the attribute registry so that we can add more functionality to attributes.
Definition component.h:75
ComponentInitFunc Init
Definition component.h:91
Generation pool.
Definition entitypool.h:22
Definition frameevent.h:115
bool IsRunningAsync()
check if the pipeline is currently executing an async frame event batch
Definition frameevent.cc:541
Represents a level that can be instantiated into a world.
Definition level.h:38
A container of entities, their components, and processors.
Definition world.h:85
PackedLevel * PreloadLevel(Util::String const &path)
preload a level that can be instantiated
Definition world.cc:86
void MoveInstance(MemDb::Table::Partition *partition, MemDb::RowId from, MemDb::RowId to)
Move a instance/row within a partition.
Definition world.cc:1387
Dataset Query(Filter filter)
Query the entity database using specified filter set. This does NOT wait for resources to be availabl...
Definition world.cc:1791
void AddStagedComponentsToEntity(Entity entity, AddStagedComponentCommand *cmds, SizeT numCmds)
Adds all components in cmds to entity.
Definition world.cc:968
Entity AllocateEntityId()
Allocate an entity id. Use this with caution!
Definition world.cc:498
bool componentInitializationEnabled
Disable if initialization of components is not required (ex. when running as editor db).
Definition world.h:205
EntityPool pool
used to allocate entity ids for this world
Definition world.h:278
Util::Array< RemoveComponentCommand > removeComponentQueue
Stores all deferred remove component commands.
Definition world.h:296
ComponentDecayBuffer const GetDecayBuffer(ComponentId component)
Get a decay buffer for the given component.
Definition world.cc:815
Ptr< MemDb::Database > db
contains all entity instances
Definition world.h:284
WorldId GetWorldId() const
Returns the world ID for this world. This corresponds to Game::Entity::world.
Definition world.h:322
bool IsValid(Entity entity) const
Check if an entity ID is still valid.
Definition world.cc:840
EntityMapping GetEntityMapping(Entity entity) const
Returns the entity mapping of an entity.
Definition world.cc:859
TYPE GetComponent(Entity entity)
Get an entitys component.
Definition world.h:357
void PrefilterProcessors()
Definition world.cc:590
void ClearDecayBuffers()
Clears all decay buffers. This is called by the game server automatically.
Definition world.cc:827
bool HasComponent(Entity entity) const
Check if entity has a specific component.
Definition world.h:402
void ExecuteAddComponentCommands()
dispatches all staged components to be added to entities
Definition world.cc:890
Entity CreateEntity(bool immediate=true)
Create a new empty entity.
Definition world.cc:664
void RenderDebug()
Definition world.cc:1498
bool cacheValid
Set to true if the caches for the frame pipeline are valid.
Definition world.h:300
Util::Queue< AllocateInstanceCommand > allocQueue
Stores all deferred allocation commands.
Definition world.h:290
void SetComponentValue(Entity entity, ComponentId component, void *value, uint64_t size)
Set the value of a component by providing a pointer and type size.
Definition world.cc:1442
void Reset()
Definition world.cc:645
void SimFrame()
Definition world.cc:546
void DeleteEntity(Entity entity)
Delete entity.
Definition world.cc:687
void ReinitializeComponent(Entity entity, ComponentId component, void *value, uint64_t size)
Set the value of a component by providing a pointer and type size, then reinitialize the component.
Definition world.cc:1460
void UnloadLevel(PackedLevel *level)
unload a preloaded level
Definition world.cc:302
bool HasInstance(Entity entity) const
Check if an entity has an instance. It might be valid, but not have received an instance just after i...
Definition world.cc:849
MemDb::RowId AllocateInstance(Entity entity)
Allocate an entity instance in default (empty) table without initializing components....
Definition world.cc:1190
FramePipeline pipeline
The frame pipeline for this world.
Definition world.h:302
World(WorldHash hash, WorldId id)
Definition world.cc:50
void FinalizeAllocate(Entity entity)
Definition world.cc:1276
SizeT GetNumInstances(MemDb::TableId tid)
Get total number of instances in an entity table.
Definition world.cc:881
friend class PackedLevel
Definition world.h:214
void * GetColumnData(MemDb::TableId const tableId, uint16_t partitionId, MemDb::ColumnIndex const column)
Get a pointer to the first instance of a column in a partition of an entity table....
Definition world.cc:1113
Util::FixedArray< ComponentDecayBuffer > componentDecayTable
Contains all the component decay buffers. Lookup directly via ComponentId.
Definition world.h:306
MemDb::TableId CreateEntityTable(EntityTableCreateInfo const &info)
Create a table in the entity database that has a specific set of components.
Definition world.cc:1132
void DecayComponent(ComponentId component, MemDb::TableId tableId, MemDb::ColumnIndex column, MemDb::RowId instance)
Copies the component to the decay table.
Definition world.cc:709
void RemoveComponentsFromEntity(Entity entity, RemoveComponentCommand *cmds, SizeT numCmds)
Removes all components in cmds from entity.
Definition world.cc:1037
void RemoveComponent(Entity entity)
Remove a component from an entity.
Definition world.h:382
void ExecuteRemoveComponentCommands()
dispatches all staged components to be removed from entities
Definition world.cc:930
friend class GameServer
Definition world.h:213
void DeallocateEntityId(Entity entity)
Deallocate an entity id. Use this with caution!
Definition world.cc:514
WorldMode mode
the mode this world is currently running in, which decides which processors execute
Definition world.h:208
Util::Array< EntityMapping > entityMap
maps entity index to table+row pair
Definition world.h:282
FramePipeline & GetFramePipeline()
Get the frame pipeline.
Definition world.cc:1766
void BeginFrame()
Definition world.cc:536
MemDb::RowId GetInstance(Entity entity) const
Get instance of entity.
Definition world.cc:1123
WorldId worldId
world id
Definition world.h:288
void Start()
Definition world.cc:525
void EndFrame()
Definition world.cc:556
Ptr< MemDb::Database > GetDatabase()
Get the entity database. Be careful when directly modifying the database, as some information is only...
Definition world.cc:655
WorldHash GetWorldHash() const
Returns the world hash for this world.
Definition world.h:313
void Defragment(MemDb::TableId tableId)
Defragment an entity table.
Definition world.cc:1417
void DeallocateInstance(MemDb::TableId table, MemDb::RowId instance)
Deallocate an entity instance. Use this with caution!
Definition world.cc:1289
MemDb::RowId Migrate(Entity entity, MemDb::TableId newTable)
Migrate an entity from it's current table to a different table.
Definition world.cc:1327
static void Override(World *src, World *dst)
Copy src over dst without initializing components. This is extremely destructive.
Definition world.cc:1734
void ManageEntities()
Definition world.cc:600
TYPE * AddComponent(Entity entity)
Create a component. This queues the component in a command buffer to be added later.
Definition world.h:412
Util::Queue< DeallocInstanceCommand > deallocQueue
Stores all deferred deallocation commands.
Definition world.h:292
void * GetInstanceBuffer(MemDb::TableId const tableId, uint16_t partitionId, ComponentId const component)
Get a pointer to the first instance of a component in a partition of an entity table....
Definition world.cc:1095
void OnSave()
Definition world.cc:581
Util::Array< AddStagedComponentCommand > addStagedQueue
Stores all deferred add staged component commands.
Definition world.h:294
bool ExportLevel(Util::String const &path)
Export the world as a level.
Definition world.cc:311
Memory::ArenaAllocator< 4096_KB > componentStageAllocator
Allocator for staged components.
Definition world.h:298
void OnLoad()
Definition world.cc:572
SizeT numEntities
Number of entities alive.
Definition world.h:280
MemDb::TableId defaultTableId
The default table that empty entities are instantiated into.
Definition world.h:304
void MarkAsModified(Game::Entity entity)
Mark an entity as modified in its table.
Definition world.cc:1775
void SetComponent(Entity entity, TYPE const &value)
Set the value of an entitys component.
Definition world.h:332
WorldHash hash
world hash
Definition world.h:286
void InitializeInstance(Entity entity)
Initialize all components on an allocated entity instance.
Definition world.cc:1239
Definition attribute.h:29
static void const *const DefaultValue(AttributeId descriptor)
get attribute default value pointer
Definition attributeregistry.h:269
static SizeT TypeSize(AttributeId descriptor)
get type size by attribute id
Definition attributeregistry.h:247
static Attribute * GetAttribute(AttributeId descriptor)
get attribute description by id
Definition attributeregistry.h:229
Definition database.h:28
Represents a partition within a Table in MemDb.
Definition table.h:205
Allocates memory in chunks.
Definition arenaallocator.h:36
T * Alloc()
allocate new object, and calls constructor, but beware because this allocator does not run the destru...
Definition arenaallocator.h:186
Nebula's smart pointer class which manages the life time of RefCounted objects.
Definition ptr.h:38
Nebula's dynamic array class.
Definition array.h:61
The Util::Blob class encapsulates a chunk of raw memory into a C++ object which can be copied,...
Definition blob.h:22
Implements a fixed size one-dimensional array.
Definition fixedarray.h:20
Nebula's queue class (a FIFO container).
Definition queue.h:22
Nebula's universal string class.
Definition string.h:50
#define n_assert2(exp, msg)
Definition debug.h:59
#define n_assert(exp)
Definition debug.h:58
Resolves local hierarchical transforms into the mandatory world transform components.
Definition graphicsmanager.h:66
MemDb::AttributeId ComponentId
Definition componentid.h:15
uint32_t Filter
Opaque filter identifier.
Definition filter.h:26
ComponentId GetComponentId()
Returns a component id, based on template type.
Definition component.h:120
WorldMode
Definition world.h:45
@ EditorMode
Definition world.h:46
@ PlayMode
Definition world.h:47
uint32_t WorldId
Definition entity.h:28
World * GetWorld(WorldHash hash)
returns a world by hash
Definition world.cc:33
ComponentId GetComponentId(Util::StringAtom name)
Returns a component id.
Definition component.h:139
ProcessorPhase PhaseForMode(WorldMode mode)
Definition world.h:52
ProcessorPhase
which world mode a processor is allowed to run in
Definition processor.h:24
@ PlayPhase
Definition processor.h:26
@ EditorPhase
Definition processor.h:25
Attribute.
Definition attribute.h:26
void Copy(const void *from, void *to, size_t numBytes)
Copy a chunk of memory (note the argument order is different from memcpy()!
Definition osxmemory.cc:213
A quad tree designed to return regions of free 2D space.
Definition Random.cs:4
Contains data for components flagged with COMPONENTFLAG_DECAY, that has been deleted this frame.
Definition component.h:47
A dataset that contains views into category tables.
Definition dataset.h:23
An entity is essentially just an Id with some utility functions attached.
Definition entity.h:35
static constexpr Entity Invalid()
Definition entity.h:138
Maps an entity to a table and instance id.
Definition entity.h:87
MemDb::RowId instance
Definition entity.h:89
MemDb::TableId table
Definition entity.h:88
Definition category.h:18
A component that stores the orientation of an entity.
Definition orientation.h:18
A component that stores the position of an entity in world space coordinates.
Definition position.h:19
A component that stores the scale of an entity.
Definition scale.h:18
ComponentId componentId
Definition world.h:229
SizeT dataSize
Definition world.h:230
void * data
Definition world.h:231
Game::Entity entity
Definition world.h:228
Game::Entity entity
Definition world.h:218
Game::Entity entity
Definition world.h:223
ComponentId componentId
Definition world.h:237
Entity entity
Definition world.h:236
Definition entity.h:29
column id
Definition tableid.h:38
row identifier
Definition tableid.h:18
uint16_t partition
Definition tableid.h:19
uint16_t index
Definition tableid.h:20
Table identifier.
Definition tableid.h:14
int SizeT
Definition types.h:42