Skip to content

Commit 9a357b1

Browse files
authored
adds missing exec error (#26)
1 parent 0e68059 commit 9a357b1

File tree

4 files changed

+141
-65
lines changed

4 files changed

+141
-65
lines changed

ecsact/entt/runtime.hh

Lines changed: 99 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -586,12 +586,13 @@ private:
586586
const auto system_id = ecsact_id_cast<ecsact_system_like_id>(SystemT::id);
587587

588588
const void* action_data = nullptr;
589-
auto each_cb = [&](auto& view, auto& assoc_views, auto entity) {
590-
if constexpr(!mp_empty<ChildSystemsListT>::value) {
591-
system_execution_context<SystemT>
592-
ctx(info, system_id, view, assoc_views, entity, parent, action_data);
593-
_execute_systems_list<ChildSystemsListT>(info, ctx.cptr(), actions);
594-
}
589+
590+
auto each_cb = [&](auto& view, auto& assoc_views, auto entity) {
591+
if constexpr(!mp_empty<ChildSystemsListT>::value) {
592+
system_execution_context<SystemT>
593+
ctx(info, system_id, view, assoc_views, entity, parent, action_data);
594+
_execute_systems_list<ChildSystemsListT>(info, ctx.cptr(), actions);
595+
}
595596
};
596597

597598
if constexpr(is_action<SystemT>()) {
@@ -660,53 +661,55 @@ private:
660661
auto assoc_views = system_association_views<SystemT>(info.registry);
661662
auto assoc_views_itrs = system_association_views_iterators(assoc_views);
662663
const void* action_data = nullptr;
663-
auto itr_view = [&] {
664-
for(auto entity : view) {
665-
bool missing_assoc_entities = false;
666-
mp_for_each<mp_iota_c<mp_size<associations>::value>>([&](auto I) {
667-
using boost::mp11::mp_at;
668-
using boost::mp11::mp_size_t;
669-
670-
using Assoc = mp_at<associations, mp_size_t<I>>;
671-
using ComponentT = typename Assoc::component_type;
672-
673-
auto& assoc_view = std::get<I>(assoc_views);
674-
auto& assoc_view_itr = std::get<I>(assoc_views_itrs);
675-
constexpr std::size_t offset = Assoc::field_offset;
676-
assert(view.contains(entity));
677-
auto& comp = view.template get<ComponentT>(entity);
678-
auto field_entity_value = *reinterpret_cast<const ecsact_entity_id*>(
679-
reinterpret_cast<const char*>(&comp) + offset
680-
);
681-
auto entt_field_entity_value =
682-
info.get_entt_entity_id(field_entity_value);
683-
684-
bool found_associated_entity = false;
685-
for(; assoc_view_itr != assoc_view.end(); ++assoc_view_itr) {
686-
found_associated_entity = *assoc_view_itr ==
687-
entt_field_entity_value;
688-
if(found_associated_entity) {
689-
break;
690-
}
691-
}
692-
693-
if(!found_associated_entity) {
694-
missing_assoc_entities = true;
695-
}
696-
});
697-
698-
if(!missing_assoc_entities) {
699-
_execute_system_user_itr<SystemT, ChildSystemsListT>(
700-
info,
701-
view,
702-
assoc_views,
703-
entity,
704-
parent,
705-
action_data,
706-
actions
707-
);
708-
}
709-
}
664+
665+
auto itr_view = [&] {
666+
for(auto entity : view) {
667+
bool missing_assoc_entities = false;
668+
mp_for_each<mp_iota_c<mp_size<associations>::value>>([&](auto I) {
669+
using boost::mp11::mp_at;
670+
using boost::mp11::mp_size_t;
671+
672+
using Assoc = mp_at<associations, mp_size_t<I>>;
673+
using ComponentT = typename Assoc::component_type;
674+
675+
auto& assoc_view = std::get<I>(assoc_views);
676+
auto& assoc_view_itr = std::get<I>(assoc_views_itrs);
677+
constexpr auto offset = Assoc::field_offset;
678+
assert(view.contains(entity));
679+
auto& comp = view.template get<ComponentT>(entity);
680+
681+
auto field_entity_value = *reinterpret_cast<const ecsact_entity_id*>(
682+
reinterpret_cast<const char*>(&comp) + offset
683+
);
684+
auto entt_field_entity_value =
685+
info.get_entt_entity_id(field_entity_value);
686+
687+
bool found_associated_entity = false;
688+
for(; assoc_view_itr != assoc_view.end(); ++assoc_view_itr) {
689+
found_associated_entity = *assoc_view_itr ==
690+
entt_field_entity_value;
691+
if(found_associated_entity) {
692+
break;
693+
}
694+
}
695+
696+
if(!found_associated_entity) {
697+
missing_assoc_entities = true;
698+
}
699+
});
700+
701+
if(!missing_assoc_entities) {
702+
_execute_system_user_itr<SystemT, ChildSystemsListT>(
703+
info,
704+
view,
705+
assoc_views,
706+
entity,
707+
parent,
708+
action_data,
709+
actions
710+
);
711+
}
712+
}
710713
};
711714

712715
if constexpr(is_action<SystemT>()) {
@@ -1094,6 +1097,32 @@ private:
10941097
});
10951098
}
10961099

1100+
auto _validate_action(ecsact_registry_id registry_id, ecsact_action& action)
1101+
-> ecsact_execute_systems_error {
1102+
using boost::mp11::mp_for_each;
1103+
1104+
auto& info = _registries.at(registry_id);
1105+
auto result = ECSACT_EXEC_SYS_OK;
1106+
1107+
mp_for_each<typename package::actions>([&]<typename A>(A) {
1108+
if(A::id != action.action_id) {
1109+
return;
1110+
}
1111+
constexpr auto fields_info = ecsact::fields_info<A>();
1112+
for(auto& field : fields_info) {
1113+
if(field.storage_type == ECSACT_ENTITY_TYPE) {
1114+
auto entity_field =
1115+
field.template get<ecsact_entity_id>(action.action_data);
1116+
if(!info.entities_map.contains(entity_field)) {
1117+
result = ECSACT_EXEC_SYS_ERR_ACTION_ENTITY_INVALID;
1118+
}
1119+
}
1120+
}
1121+
});
1122+
1123+
return result;
1124+
}
1125+
10971126
public:
10981127
#ifdef ECSACT_ENTT_RUNTIME_DYNAMIC_SYSTEM_IMPLS
10991128
bool set_system_execution_impl(
@@ -1115,10 +1144,24 @@ public:
11151144
const ecsact_execution_options* execution_options_list,
11161145
std::optional<execution_events_collector> events_collector
11171146
) {
1118-
std::mutex mutex;
1119-
auto& info = _registries.at(reg_id);
1147+
auto mutex = std::mutex{};
1148+
auto& info = _registries.at(reg_id);
1149+
auto exec_err = ECSACT_EXEC_SYS_OK;
11201150
info.mutex = std::ref(mutex);
11211151

1152+
if(execution_options_list != nullptr) {
1153+
for(int n = 0; execution_count > n; ++n) {
1154+
auto opts = execution_options_list[n];
1155+
for(auto act_idx = 0; opts.actions_length > act_idx; ++act_idx) {
1156+
auto& act = opts.actions[act_idx];
1157+
exec_err = _validate_action(reg_id, act);
1158+
if(exec_err != ECSACT_EXEC_SYS_OK) {
1159+
return exec_err;
1160+
}
1161+
}
1162+
}
1163+
}
1164+
11221165
for(int n = 0; execution_count > n; ++n) {
11231166
actions_span_t actions;
11241167
if(execution_options_list != nullptr) {
@@ -1142,7 +1185,7 @@ public:
11421185
_clear_event_markers(info);
11431186

11441187
info.mutex = std::nullopt;
1145-
return ECSACT_EXEC_SYS_OK;
1188+
return exec_err;
11461189
}
11471190
};
11481191

runtime/core.template.cc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
using namespace ecsact_entt_rt;
66

77
ecsact_registry_id ecsact_create_registry(const char* registry_name) {
8-
return static_cast<ecsact_registry_id>(runtime.create_registry(registry_name)
9-
);
8+
return runtime.create_registry(registry_name);
109
}
1110

1211
void ecsact_destroy_registry(ecsact_registry_id reg_id) {

runtime/test/runtime_test.cc

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,29 @@ void runtime_test::OtherEntitySystem::impl(context& ctx) {
2929
void runtime_test::MakeAnother::impl(context& ctx) {
3030
}
3131

32-
void runtime_test::TrivialRemove::impl(context& ctx) {
32+
void runtime_test::AlwaysRemove::impl(context& ctx) {
3333
// This trivial remove should not even be required:
3434
// SEE: https://github.com/ecsact-dev/ecsact_lang_cpp/issues/80
35-
std::cerr << "TriviaLRemove impl called (SHOULD NOT HAPPEN)\n";
35+
std::cerr << "AlwaysRemove impl called (SHOULD NOT HAPPEN)\n";
3636
std::cerr.flush();
3737
std::abort();
3838
}
3939

40-
void runtime_test::AlwaysRemove::impl(context& ctx) {
40+
void runtime_test::TrivialRemove::impl(context& ctx) {
4141
// This trivial remove should not even be required:
4242
// SEE: https://github.com/ecsact-dev/ecsact_lang_cpp/issues/80
43-
std::cerr << "AlwaysRemove impl called (SHOULD NOT HAPPEN)\n";
43+
std::cerr << "TriviaLRemove impl called (SHOULD NOT HAPPEN)\n";
4444
std::cerr.flush();
4545
std::abort();
4646
}
4747

48+
void runtime_test::AssocTestAction::impl(context& ctx) {
49+
ctx.add(OtherEntityComponent{
50+
.num = 42,
51+
.target = ctx.action().assoc_entity,
52+
});
53+
}
54+
4855
TEST(Core, CreateRegistry) {
4956
auto reg_id = ecsact_create_registry("CreateRegistry");
5057
EXPECT_NE(reg_id, ecsact_invalid_registry_id);
@@ -275,9 +282,9 @@ TEST(Core, TrivialRemoveEvent) {
275282
}
276283

277284
TEST(Core, DynamicSystemImpl) {
278-
ecsact::core::registry reg("DynamicSystemImpl");
279-
auto entity = reg.create_entity();
280-
auto other_entity = reg.create_entity();
285+
auto reg = ecsact::core::registry("DynamicSystemImpl");
286+
auto entity = reg.create_entity();
287+
auto other_entity = reg.create_entity();
281288

282289
ComponentA comp{.a = 42};
283290
reg.add_component(entity, comp);
@@ -318,6 +325,26 @@ TEST(Core, DynamicSystemImpl) {
318325
EXPECT_EQ(comp_get.a, comp.a);
319326
}
320327

328+
TEST(Core, ExecuteSystemsErrors) {
329+
auto reg = ecsact::core::registry("ExecuteSystemsErrors");
330+
auto comp = OtherEntityComponent{
331+
.num = 42,
332+
.target = static_cast<ecsact_entity_id>(4000),
333+
};
334+
auto options = ecsact_execution_options{};
335+
auto test_action = runtime_test::AssocTestAction{};
336+
auto test_action_c = ecsact_action{
337+
.action_id = runtime_test::AssocTestAction::id,
338+
.action_data = &test_action,
339+
};
340+
341+
options.actions_length = 1;
342+
options.actions = &test_action_c;
343+
auto exec_err = ecsact_execute_systems(reg.id(), 1, &options, nullptr);
344+
345+
EXPECT_EQ(exec_err, ECSACT_EXEC_SYS_ERR_ACTION_ENTITY_INVALID);
346+
}
347+
321348
#ifdef ECSACT_ENTT_TEST_STATIC_SYSTEM_IMPL
322349
TEST(Core, StaticSystemImpl) {
323350
auto reg_id = ecsact_create_registry("StaticSystemImpl");

runtime/test/runtime_test.ecsact

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,10 @@ action MakeAnother {
4040
required OtherEntityComponent;
4141
}
4242
}
43+
44+
action AssocTestAction {
45+
entity assoc_entity;
46+
readwrite ComponentA;
47+
adds OtherEntityComponent;
48+
}
49+

0 commit comments

Comments
 (0)