-
Notifications
You must be signed in to change notification settings - Fork 15
Extended usage of Flecs #181
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
3675f1d
eb6529f
8c4a7b4
7eb340b
d69aa9e
13a618d
ebaa697
4d0304a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,7 @@ | |
|
|
||
| #include "game_rpc/set_frame.h" | ||
| #include "game_rpc/set_transform.h" | ||
| #include "networking/messages/game_sync/entity_messages.h" | ||
|
|
||
| namespace Framework::World { | ||
| EngineError ClientEngine::Init() { | ||
|
|
@@ -21,6 +22,19 @@ namespace Framework::World { | |
|
|
||
| _queryGetEntityByServerID = _world->query_builder<Modules::Base::ServerID>().build(); | ||
|
|
||
| // Observer to maintain ServerID cache | ||
| _world->observer<Modules::Base::ServerID>("ServerIDCacheUpdate") | ||
| .event(flecs::OnSet) | ||
| .each([this](flecs::entity e, Modules::Base::ServerID& sid) { | ||
| _serverIdCache[sid.id] = e; | ||
| }); | ||
|
|
||
| _world->observer<Modules::Base::ServerID>("ServerIDCacheRemove") | ||
| .event(flecs::OnRemove) | ||
| .each([this](flecs::entity e, Modules::Base::ServerID& sid) { | ||
| _serverIdCache.erase(sid.id); | ||
| }); | ||
|
Comment on lines
+25
to
+36
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Talked to creator of flecs Sander and he suggested this can be improved by using combination of "world.set_entity_range()" and "world.make_alive()" methods. Don't worry about big id's of entities because https://www.flecs.dev/flecs/md_docs_2FAQ.html#why-are-my-entity-ids-so-large Then simple function can be created to do simple bit check to know what on what side entity belong to. It means you no longer even need ServerID component. |
||
|
|
||
| return EngineError::ENGINE_NONE; | ||
| } | ||
|
|
||
|
|
@@ -33,14 +47,11 @@ namespace Framework::World { | |
| } | ||
|
|
||
| flecs::entity ClientEngine::GetEntityByServerID(flecs::entity_t id) const { | ||
| flecs::entity ent = {}; | ||
| _queryGetEntityByServerID.each([&ent, id](flecs::entity e, Modules::Base::ServerID& rhs) { | ||
| if (id == rhs.id) { | ||
| ent = e; | ||
| return; | ||
| } | ||
| }); | ||
| return ent; | ||
| auto it = _serverIdCache.find(id); | ||
| if (it != _serverIdCache.end() && it->second.is_alive()) { | ||
| return it->second; | ||
| } | ||
| return flecs::entity::null(); | ||
| } | ||
|
|
||
| flecs::entity_t ClientEngine::GetServerID(flecs::entity entity) { | ||
|
|
@@ -58,6 +69,7 @@ namespace Framework::World { | |
|
|
||
| auto &sid = e.ensure<Modules::Base::ServerID>(); | ||
| sid.id = serverID; | ||
| e.modified<Modules::Base::ServerID>(); | ||
| return e; | ||
| } | ||
|
|
||
|
|
@@ -72,10 +84,17 @@ namespace Framework::World { | |
| const auto rs = it.field<Modules::Base::Streamable>(1); | ||
|
|
||
| for (auto i : it) { | ||
| const auto &es = &rs[i]; | ||
|
|
||
| if (es->GetBaseEvents().updateProc && es->performTickUpdates && Framework::World::Engine::IsEntityOwner(it.entity(i), myGUID.g)) { | ||
| es->GetBaseEvents().updateProc(_networkPeer, (SLNet::UNASSIGNED_RAKNET_GUID).g, it.entity(i)); | ||
| const auto e = it.entity(i); | ||
|
|
||
| // Send updates for entities we own | ||
| if (!e.has<Modules::Base::NoTickUpdates>() && Framework::World::Engine::IsEntityOwner(e, myGUID.g)) { | ||
| const auto sid = e.get<Modules::Base::ServerID>(); | ||
| if (sid) { | ||
| Framework::Networking::Messages::GameSyncEntityUpdate entityUpdate; | ||
| entityUpdate.FromParameters(tr[i], 0); | ||
| entityUpdate.SetServerID(sid->id); | ||
| _networkPeer->Send(entityUpdate, (SLNet::UNASSIGNED_RAKNET_GUID).g); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -98,8 +117,8 @@ namespace Framework::World { | |
| } | ||
| } | ||
|
|
||
| if (str.modEvents.disconnectProc) { | ||
| str.modEvents.disconnectProc(e); | ||
| if (str.disconnectProc) { | ||
| str.disconnectProc(e); | ||
| } | ||
|
|
||
| e.destruct(); | ||
|
|
@@ -142,8 +161,8 @@ namespace Framework::World { | |
| *tr = rhs; | ||
|
|
||
| const auto str = entity.get_mut<Modules::Base::Streamable>(); | ||
| if (str->modEvents.updateTransformProc) { | ||
| str->modEvents.updateTransformProc(entity); | ||
| if (str && str->updateTransformProc) { | ||
| str->updateTransformProc(entity); | ||
| } | ||
| } | ||
| } // namespace Framework::World | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,6 +22,19 @@ namespace Framework::World { | |
| _allStreamableEntities = _world->query_builder<Modules::Base::Transform, Modules::Base::Streamable>().build(); | ||
| _findAllStreamerEntities = _world->query_builder<Modules::Base::Streamer>().build(); | ||
|
|
||
| // Observer to maintain GUID cache | ||
| _world->observer<Modules::Base::Streamer>("GUIDCacheUpdate") | ||
| .event(flecs::OnSet) | ||
| .each([this](flecs::entity e, Modules::Base::Streamer& s) { | ||
| _guidCache[s.guid] = e; | ||
| }); | ||
|
|
||
| _world->observer<Modules::Base::Streamer>("GUIDCacheRemove") | ||
| .event(flecs::OnRemove) | ||
| .each([this](flecs::entity e, Modules::Base::Streamer& s) { | ||
| _guidCache.erase(s.guid); | ||
| }); | ||
|
|
||
| return EngineError::ENGINE_NONE; | ||
| } | ||
|
|
||
|
|
@@ -53,13 +66,11 @@ namespace Framework::World { | |
| } | ||
|
|
||
| flecs::entity Engine::GetEntityByGUID(uint64_t guid) const { | ||
| flecs::entity ourEntity = {}; | ||
| _findAllStreamerEntities.each([&ourEntity, guid](flecs::entity e, Modules::Base::Streamer &s) { | ||
| if (ourEntity == flecs::entity::null() && s.guid == guid) { | ||
| ourEntity = e; | ||
| } | ||
| }); | ||
| return ourEntity; | ||
| auto it = _guidCache.find(guid); | ||
| if (it != _guidCache.end() && it->second.is_alive()) { | ||
| return it->second; | ||
| } | ||
| return flecs::entity::null(); | ||
| } | ||
|
|
||
| flecs::entity Engine::WrapEntity(flecs::entity_t serverID) const { | ||
|
|
@@ -68,10 +79,77 @@ namespace Framework::World { | |
|
|
||
| void Engine::PurgeAllResourceEntities() const { | ||
| _world->defer_begin(); | ||
| _findAllResourceEntities.each([this](flecs::entity e, Modules::Base::RemovedOnResourceReload &rhs) { | ||
| if (e.is_alive()) | ||
| e.add<Modules::Base::PendingRemoval>(); | ||
| _findAllResourceEntities.run([this](flecs::iter& it) { | ||
| while (it.next()) { | ||
| for (auto i : it) { | ||
| auto e = it.entity(i); | ||
| if (e.is_alive()) | ||
| e.add<Modules::Base::PendingRemoval>(); | ||
| } | ||
| } | ||
| }); | ||
| _world->defer_end(); | ||
| } | ||
|
|
||
| flecs::entity Engine::GetOrCreateVirtualWorld(int worldId) { | ||
| auto it = _virtualWorldCache.find(worldId); | ||
| if (it != _virtualWorldCache.end() && it->second.is_alive()) { | ||
| return it->second; | ||
| } | ||
|
|
||
| // Create a new virtual world entity | ||
| std::string name = "VirtualWorld_" + std::to_string(worldId); | ||
| auto worldEntity = _world->entity(name.c_str()); | ||
| worldEntity.set<Modules::Base::VirtualWorld>({worldId}); | ||
| _virtualWorldCache[worldId] = worldEntity; | ||
| return worldEntity; | ||
| } | ||
|
|
||
| void Engine::SetEntityVirtualWorld(flecs::entity e, int worldId) { | ||
| if (!e.is_valid() || !e.is_alive()) | ||
| return; | ||
|
|
||
| // Remove from any existing virtual world | ||
| e.remove<Modules::Base::InVirtualWorld>(flecs::Wildcard); | ||
|
|
||
| // Add to new virtual world (world ID 0 means no world / default) | ||
| if (worldId != 0) { | ||
| auto worldEntity = GetOrCreateVirtualWorld(worldId); | ||
| e.add<Modules::Base::InVirtualWorld>(worldEntity); | ||
| } | ||
|
|
||
| // Also update the legacy field for backward compatibility | ||
| auto streamable = e.get_mut<Modules::Base::Streamable>(); | ||
| if (streamable) { | ||
| streamable->virtualWorld = worldId; | ||
| } | ||
| } | ||
|
|
||
| int Engine::GetEntityVirtualWorld(flecs::entity e) const { | ||
| if (!e.is_valid() || !e.is_alive()) | ||
| return 0; | ||
|
|
||
| // Try to get from relation first | ||
| int worldId = 0; | ||
| e.each<Modules::Base::InVirtualWorld>([&worldId](flecs::entity worldEntity) { | ||
| auto vw = worldEntity.get<Modules::Base::VirtualWorld>(); | ||
| if (vw) { | ||
| worldId = vw->id; | ||
| } | ||
| }); | ||
|
|
||
| // Fallback to legacy field if no relation | ||
| if (worldId == 0) { | ||
| auto streamable = e.get<Modules::Base::Streamable>(); | ||
| if (streamable) { | ||
| worldId = streamable->virtualWorld; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. in my opinion streamable should not have virtual world and by default entity is in main world id 0 |
||
| } | ||
| } | ||
|
|
||
| return worldId; | ||
| } | ||
|
|
||
| bool Engine::AreInSameVirtualWorld(flecs::entity a, flecs::entity b) const { | ||
| return GetEntityVirtualWorld(a) == GetEntityVirtualWorld(b); | ||
| } | ||
| } // namespace Framework::World | ||
Uh oh!
There was an error while loading. Please reload this page.