mission_script_lua_event_api.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. #include <string_view>
  2. #include "mission_script_lua_event_internal.h"
  3. #include "mission_script_lua_internal.h"
  4. namespace sunrise::server::activity::mission::lua_vm::detail {
  5. /** Resolves a typed event directly from its native enum. */
  6. [[nodiscard]] std::string_view event_kind_name(lua_State* state, host::EventKind kind) noexcept {
  7. (void)state;
  8. switch (kind) {
  9. case host::EventKind::fireteamState:
  10. return "fireteamState";
  11. case host::EventKind::senseUpdate:
  12. return "sensorSenseUpdated";
  13. case host::EventKind::clientStateChanged:
  14. return "clientStateChanged";
  15. case host::EventKind::regionChanged:
  16. return "regionChanged";
  17. case host::EventKind::incidentReceived:
  18. return "incidentReceived";
  19. case host::EventKind::timerElapsed:
  20. return "timerElapsed";
  21. case host::EventKind::effectResult:
  22. return "effectResult";
  23. case host::EventKind::phaseEntered:
  24. return "phaseEntered";
  25. case host::EventKind::triggerEntered:
  26. return "triggerEntered";
  27. case host::EventKind::triggerExited:
  28. return "triggerExited";
  29. case host::EventKind::triggerState:
  30. return "triggerState";
  31. case host::EventKind::squadState:
  32. return "squadState";
  33. case host::EventKind::squadProvoked:
  34. return "squadProvoked";
  35. case host::EventKind::entitySpawned:
  36. return "entitySpawned";
  37. case host::EventKind::entityDied:
  38. return "entityDied";
  39. case host::EventKind::sceneFinished:
  40. return "sceneFinished";
  41. case host::EventKind::objectiveProgress:
  42. return "objectiveProgress";
  43. case host::EventKind::entitySlotsRequested:
  44. return "entitySlotsRequested";
  45. case host::EventKind::sessionJoined:
  46. return "sessionJoined";
  47. case host::EventKind::sessionLeft:
  48. return "sessionLeft";
  49. case host::EventKind::playerTrigger:
  50. return "playerTrigger";
  51. case host::EventKind::cinematicStarted:
  52. return "cinematicStarted";
  53. case host::EventKind::cinematicSkipRequested:
  54. return "cinematicSkipRequested";
  55. case host::EventKind::cinematicTerminated:
  56. return "cinematicTerminated";
  57. case host::EventKind::actorPathState:
  58. return "actorPathState";
  59. case host::EventKind::objectInteracted:
  60. return "objectInteracted";
  61. case host::EventKind::damageState:
  62. return "damageState";
  63. case host::EventKind::deviceState:
  64. return "deviceState";
  65. case host::EventKind::objectState:
  66. return "objectState";
  67. case host::EventKind::ghostLinkState:
  68. return "ghostLinkState";
  69. case host::EventKind::clientMessageReceived:
  70. return "clientMessageReceived";
  71. case host::EventKind::authStateCommitted:
  72. return "authStateCommitted";
  73. case host::EventKind::authStateTransportStaged:
  74. return "authStateTransportStaged";
  75. case host::EventKind::authStateCanceled:
  76. return "authStateCanceled";
  77. case host::EventKind::incidentQueued:
  78. return "incidentQueued";
  79. case host::EventKind::incidentTransportStaged:
  80. return "incidentTransportStaged";
  81. case host::EventKind::incidentCanceled:
  82. return "incidentCanceled";
  83. case host::EventKind::incidentRefused:
  84. return "incidentRefused";
  85. case host::EventKind::scriptableOverrideCommitted:
  86. return "scriptableOverrideCommitted";
  87. case host::EventKind::scriptableOverrideTransportStaged:
  88. return "scriptableOverrideTransportStaged";
  89. case host::EventKind::scriptableOverrideCanceled:
  90. return "scriptableOverrideCanceled";
  91. case host::EventKind::operatorRefused:
  92. return "operatorRefused";
  93. }
  94. return "unknown";
  95. }
  96. [[nodiscard]] bool event_surface_visible(lua_State* state, host::EventKind kind) noexcept {
  97. return !event_kind_name(state, kind).empty();
  98. }
  99. /** @return The view metatable one kind is pushed with. */
  100. [[nodiscard]] const char* event_metatable(host::EventKind kind) noexcept {
  101. switch (kind) {
  102. case host::EventKind::fireteamState:
  103. return kFireteamStateEventMetatable;
  104. case host::EventKind::senseUpdate:
  105. return kSenseUpdateEventMetatable;
  106. case host::EventKind::clientStateChanged:
  107. return kClientStateChangedEventMetatable;
  108. case host::EventKind::regionChanged:
  109. return kRegionChangedEventMetatable;
  110. case host::EventKind::incidentReceived:
  111. return kIncidentReceivedEventMetatable;
  112. case host::EventKind::clientMessageReceived:
  113. return kClientMessageEventMetatable;
  114. case host::EventKind::authStateCommitted:
  115. return kAuthStateCommittedEventMetatable;
  116. case host::EventKind::authStateTransportStaged:
  117. return kAuthStateTransportStagedEventMetatable;
  118. case host::EventKind::authStateCanceled:
  119. return kAuthStateCanceledEventMetatable;
  120. case host::EventKind::incidentQueued:
  121. return kIncidentQueuedEventMetatable;
  122. case host::EventKind::incidentTransportStaged:
  123. return kIncidentTransportStagedEventMetatable;
  124. case host::EventKind::incidentCanceled:
  125. return kIncidentCanceledEventMetatable;
  126. case host::EventKind::incidentRefused:
  127. return kIncidentRefusedEventMetatable;
  128. case host::EventKind::scriptableOverrideCommitted:
  129. return kScriptableOverrideCommittedEventMetatable;
  130. case host::EventKind::scriptableOverrideTransportStaged:
  131. return kScriptableOverrideTransportStagedEventMetatable;
  132. case host::EventKind::scriptableOverrideCanceled:
  133. return kScriptableOverrideCanceledEventMetatable;
  134. case host::EventKind::operatorRefused:
  135. return kOperatorRefusedEventMetatable;
  136. case host::EventKind::effectResult:
  137. return kEffectResultEventMetatable;
  138. case host::EventKind::triggerEntered:
  139. return kTriggerEnteredEventMetatable;
  140. case host::EventKind::triggerExited:
  141. return kTriggerExitedEventMetatable;
  142. case host::EventKind::triggerState:
  143. return kTriggerStateEventMetatable;
  144. case host::EventKind::squadState:
  145. return kSquadStateEventMetatable;
  146. case host::EventKind::squadProvoked:
  147. return kSquadProvokedEventMetatable;
  148. case host::EventKind::entitySpawned:
  149. return kEntitySpawnedEventMetatable;
  150. case host::EventKind::entityDied:
  151. return kEntityDiedEventMetatable;
  152. case host::EventKind::sceneFinished:
  153. return kSceneFinishedEventMetatable;
  154. case host::EventKind::objectiveProgress:
  155. return kObjectiveProgressEventMetatable;
  156. case host::EventKind::phaseEntered:
  157. return kPhaseEnteredEventMetatable;
  158. case host::EventKind::timerElapsed:
  159. return kTimerElapsedEventMetatable;
  160. case host::EventKind::entitySlotsRequested:
  161. return kEntitySlotsRequestedEventMetatable;
  162. case host::EventKind::sessionJoined:
  163. return kSessionJoinedEventMetatable;
  164. case host::EventKind::sessionLeft:
  165. return kSessionLeftEventMetatable;
  166. case host::EventKind::playerTrigger:
  167. return kPlayerTriggerEventMetatable;
  168. case host::EventKind::cinematicStarted:
  169. return kCinematicStartedEventMetatable;
  170. case host::EventKind::cinematicSkipRequested:
  171. case host::EventKind::cinematicTerminated:
  172. return kCinematicTerminatedEventMetatable;
  173. case host::EventKind::actorPathState:
  174. return kActorPathEventMetatable;
  175. case host::EventKind::objectInteracted:
  176. case host::EventKind::damageState:
  177. case host::EventKind::objectState:
  178. return kObjectInteractionEventMetatable;
  179. case host::EventKind::deviceState:
  180. return kDeviceStateEventMetatable;
  181. case host::EventKind::ghostLinkState:
  182. return kGhostLinkEventMetatable;
  183. }
  184. return kSenseUpdateEventMetatable;
  185. }
  186. /**
  187. * Reads one event argument of any view.
  188. * @param index Stack index of the argument.
  189. * @return The event. The argument's metatable name must carry the event view prefix.
  190. */
  191. [[nodiscard]] const host::Event& check_event(lua_State* state, int index) {
  192. if (lua_type(state, index) == LUA_TUSERDATA && lua_getmetatable(state, index) != 0) {
  193. const bool named = lua_getfield(state, -1, "__name") == LUA_TSTRING;
  194. const bool view = named && lua_string_view(state, -1).starts_with(kEventMetatablePrefix);
  195. lua_pop(state, 2);
  196. if (view) {
  197. return static_cast<const EventHandle*>(lua_touserdata(state, index))->value;
  198. }
  199. }
  200. raise_lua_error(state, "mission event expected");
  201. }
  202. /**
  203. * Pushes kind, sequence or source_generation.
  204. * @param key Member the script asked for.
  205. * @return True when this helper owns that key.
  206. */
  207. bool push_common_member(lua_State* state, const host::Event& event, std::string_view key) {
  208. if (key == "kind") {
  209. lua_pushinteger(state, static_cast<lua_Integer>(event.kind));
  210. return true;
  211. }
  212. if (key == "sequence") {
  213. push_u64_string(state, event.sequence);
  214. return true;
  215. }
  216. if (key == "source_generation") {
  217. push_u64_string(state, event.sourceGeneration);
  218. return true;
  219. }
  220. if (key == "attempt_generation") {
  221. push_u64_string(state, event.attemptGeneration);
  222. return true;
  223. }
  224. return false;
  225. }
  226. bool push_mission_sequence_member(lua_State* state,
  227. const host::Event& event,
  228. std::string_view key) {
  229. if (key != "mission_sequence") {
  230. return false;
  231. }
  232. push_u64_string(state, event.missionSequence);
  233. return true;
  234. }
  235. bool push_state_revision_member(lua_State* state, const host::Event& event, std::string_view key) {
  236. if (key != "state_revision") {
  237. return false;
  238. }
  239. push_u64_string(state, event.stateRevision);
  240. return true;
  241. }
  242. /**
  243. * Pushes the identity of the one slot an event was observed on.
  244. * @param key Member the script asked for.
  245. * @return True when this helper owns that key.
  246. */
  247. bool push_slot_identity_member(lua_State* state, const host::Event& event, std::string_view key) {
  248. if (key == "registry_key") {
  249. lua_pushinteger(state, event.firstRegistryKey);
  250. } else if (key == "object_tag") {
  251. lua_pushinteger(state, event.slotObjectTag);
  252. } else if (key == "slot_index") {
  253. lua_pushinteger(state, event.firstSlotIndex);
  254. } else if (key == "slot_type") {
  255. lua_pushinteger(state, event.firstSlotType);
  256. } else if (key == "slot") {
  257. Impl* const impl = impl_from_state(state);
  258. SlotDefinition definition{};
  259. const host::SenseObservationKey identity{.registryKey = event.firstRegistryKey,
  260. .objectTag = event.slotObjectTag,
  261. .senseSchema = event.slotSenseSchema,
  262. .slotIndex = event.firstSlotIndex,
  263. .slotType = event.firstSlotType};
  264. if (impl == nullptr || impl->definitions.resolveSenseSlot == nullptr
  265. || !impl->definitions.resolveSenseSlot(
  266. impl->definitions.context, identity, definition)) {
  267. lua_pushnil(state);
  268. } else {
  269. push_handle(state, kSlotMetatable, SlotHandle{definition.localRow});
  270. }
  271. } else {
  272. return false;
  273. }
  274. return true;
  275. }
  276. /**
  277. * Pushes one of the four bounded outer counts of a msg-19 body.
  278. * @param key Member the script asked for.
  279. * @return True when this helper owns that key.
  280. */
  281. bool push_incident_body_member(lua_State* state, const host::Event& event, std::string_view key) {
  282. if (key == "incident_target") {
  283. lua_pushinteger(state, event.incidentTarget);
  284. } else if (key == "incident_extra_targets") {
  285. lua_pushinteger(state, event.incidentExtraTargets);
  286. } else if (key == "incident_selector_bytes") {
  287. lua_pushinteger(state, event.incidentSelectorBytes);
  288. } else if (key == "incident_payload_bytes") {
  289. lua_pushinteger(state, event.incidentPayloadBytes);
  290. } else {
  291. return false;
  292. }
  293. return true;
  294. }
  295. void register_event_metatables(lua_State* state) {
  296. register_input_event_metatables(state);
  297. register_delivery_event_metatables(state);
  298. register_derived_event_metatables(state);
  299. }
  300. } // namespace sunrise::server::activity::mission::lua_vm::detail