mission_script_lua_key_api.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // Mission identity types. Each one is minted from a name or a key the runtime already checked, so
  2. // a script holds the identity instead of spelling it.
  3. #include <cstdint>
  4. #include <string_view>
  5. #include "mission_script_lua_internal.h"
  6. namespace sunrise::server::activity::mission::lua_vm::detail {
  7. namespace {
  8. /** Compares two keys the runtime minted. Concatenating a decimal string reaches nothing. */
  9. [[nodiscard]] int request_key_matches(lua_State* state) {
  10. const auto* const handle =
  11. static_cast<const RequestKeyHandle*>(luaL_checkudata(state, 1, kRequestKeyMetatable));
  12. const auto* const other =
  13. static_cast<const RequestKeyHandle*>(luaL_checkudata(state, 2, kRequestKeyMetatable));
  14. lua_pushboolean(state, handle->key == other->key ? 1 : 0);
  15. return 1;
  16. }
  17. [[nodiscard]] int request_key_index(lua_State* state) {
  18. static_cast<void>(luaL_checkudata(state, 1, kRequestKeyMetatable));
  19. const std::string_view key = lua_string_view(state, 2);
  20. if (key == "matches") {
  21. lua_pushcfunction(state, &request_key_matches);
  22. } else if (key == "value") {
  23. const auto* handle = static_cast<const RequestKeyHandle*>(luaL_checkudata(state, 1, kRequestKeyMetatable));
  24. push_u64_string(state, handle->key);
  25. } else {
  26. lua_pushnil(state);
  27. }
  28. return 1;
  29. }
  30. /** Lua index for one timer reference: its key and name. */
  31. [[nodiscard]] int timer_ref_index(lua_State* state) {
  32. const auto* const handle =
  33. static_cast<const TimerRefHandle*>(luaL_checkudata(state, 1, kTimerRefMetatable));
  34. const std::string_view key = lua_string_view(state, 2);
  35. if (key == "name") {
  36. const std::string_view name = state_key_view(handle->key);
  37. lua_pushlstring(state, name.data(), name.size());
  38. } else {
  39. lua_pushnil(state);
  40. }
  41. return 1;
  42. }
  43. [[nodiscard]] int timer_ref_collection_resolve(lua_State* state) {
  44. static_cast<void>(luaL_checkudata(state, 1, kTimerRefCollectionMetatable));
  45. StateKey key{};
  46. if (!parse_state_key(state, 2, key)) {
  47. return luaL_argerror(state, 2, "mission timer name is invalid");
  48. }
  49. push_timer_ref(state, key);
  50. return 1;
  51. }
  52. /** Lua index for the timer reference collection: `count` and `at`, else nil. */
  53. [[nodiscard]] int timer_ref_collection_index(lua_State* state) {
  54. static_cast<void>(luaL_checkudata(state, 1, kTimerRefCollectionMetatable));
  55. const std::string_view key = lua_string_view(state, 2);
  56. if (key == "resolve") {
  57. lua_pushcfunction(state, &timer_ref_collection_resolve);
  58. } else if (key == "capacity") {
  59. lua_pushinteger(state, static_cast<lua_Integer>(kTimerCapacity));
  60. } else {
  61. lua_pushnil(state);
  62. }
  63. return 1;
  64. }
  65. /** Lua index for one variable reference: its key and name. */
  66. [[nodiscard]] int variable_ref_index(lua_State* state) {
  67. const auto* const handle =
  68. static_cast<const VariableRefHandle*>(luaL_checkudata(state, 1, kVariableRefMetatable));
  69. const std::string_view key = lua_string_view(state, 2);
  70. if (key == "name") {
  71. const std::string_view name = state_key_view(handle->key);
  72. lua_pushlstring(state, name.data(), name.size());
  73. } else {
  74. lua_pushnil(state);
  75. }
  76. return 1;
  77. }
  78. [[nodiscard]] int variable_ref_collection_resolve(lua_State* state) {
  79. static_cast<void>(luaL_checkudata(state, 1, kVariableRefCollectionMetatable));
  80. StateKey key{};
  81. if (!parse_state_key(state, 2, key)) {
  82. return luaL_argerror(state, 2, "mission variable name is invalid");
  83. }
  84. push_variable_ref(state, key);
  85. return 1;
  86. }
  87. /** Lua index for the variable reference collection: `count` and `at`, else nil. */
  88. [[nodiscard]] int variable_ref_collection_index(lua_State* state) {
  89. static_cast<void>(luaL_checkudata(state, 1, kVariableRefCollectionMetatable));
  90. const std::string_view key = lua_string_view(state, 2);
  91. if (key == "resolve") {
  92. lua_pushcfunction(state, &variable_ref_collection_resolve);
  93. } else if (key == "capacity") {
  94. lua_pushinteger(state, static_cast<lua_Integer>(kVariableCapacity));
  95. } else {
  96. lua_pushnil(state);
  97. }
  98. return 1;
  99. }
  100. } // namespace
  101. void push_request_key(lua_State* state, std::uint64_t key) {
  102. push_handle(state, kRequestKeyMetatable, RequestKeyHandle{key});
  103. }
  104. void push_timer_ref(lua_State* state, const StateKey& key) {
  105. push_handle(state, kTimerRefMetatable, TimerRefHandle{key});
  106. }
  107. void push_variable_ref(lua_State* state, const StateKey& key) {
  108. push_handle(state, kVariableRefMetatable, VariableRefHandle{key});
  109. }
  110. void register_key_metatables(lua_State* state) {
  111. register_metatable(state, kRequestKeyMetatable, &request_key_index);
  112. register_metatable(state, kTimerRefMetatable, &timer_ref_index);
  113. register_metatable(state, kTimerRefCollectionMetatable, &timer_ref_collection_index);
  114. register_metatable(state, kVariableRefMetatable, &variable_ref_index);
  115. register_metatable(state, kVariableRefCollectionMetatable, &variable_ref_collection_index);
  116. }
  117. /** Pushes one recognized key-context member. @return False when the key is not ours. */
  118. bool push_key_context_member(lua_State* state, std::string_view key) {
  119. if (key == "timers") {
  120. push_handle(state, kTimerRefCollectionMetatable, TimerRefCollectionHandle{});
  121. return true;
  122. }
  123. if (key == "variables") {
  124. push_handle(state, kVariableRefCollectionMetatable, VariableRefCollectionHandle{});
  125. return true;
  126. }
  127. return false;
  128. }
  129. } // namespace sunrise::server::activity::mission::lua_vm::detail