From 37b0b6ea8205b3416ff01e9e497a426d48a935cc Mon Sep 17 00:00:00 2001 From: Goober5000 Date: Tue, 8 Sep 2026 10:50:53 -0400 Subject: [PATCH] Standardize isValid across the Lua API by making the types auto-generate it (#7761) * Automatically generate the isValid() Lua API function for handle types If an ADE object's stored type has an isValid() member, ade_obj now registers an isValid function for it automatically. An explicit ADE_FUNC(isValid, ...) declared after the ADE_OBJ replaces the generated one, so types with special semantics (e.g. sound) keep their own. The 67 hand-written functions that merely delegated to the member are removed, and 26 types that previously exposed no isValid() gain one. Co-Authored-By: Claude Fable 5.1 * Add ADE_OBJ_VALIDATOR for index-based Lua handles Int-index handles (shipclass, weaponclass, team, etc.) can now declare their validity predicate with a single ADE_OBJ_VALIDATOR or ADE_OBJ_VALIDATOR_RANGE line after the ADE_OBJ. The registered validator drives the generated isValid() function and is also honored by ade_set_args when the mod table asks for nil instead of invalid objects, which previously never applied to these handles. The 19 hand-written range-check functions are replaced, and loadout_ship, default_primary, default_secondary, and support_rearm_pool_team gain isValid(). Add a validator to HudGauge while we're at it. Also fully qualify the scripting namespace in LuaConvert.h so its templates can be instantiated from the unit tests. Co-Authored-By: Claude Fable 5.1 --------- Co-authored-by: Claude Fable 5.1 --- code/scripting/ade.cpp | 19 ++- code/scripting/ade.h | 33 +++++- code/scripting/ade_api.h | 112 ++++++++++++++++-- code/scripting/ade_args.h | 5 +- code/scripting/api/objs/LuaEnum.cpp | 9 -- code/scripting/api/objs/audio_stream.cpp | 16 +-- .../scripting/api/objs/background_element.cpp | 10 -- code/scripting/api/objs/camera.cpp | 12 -- code/scripting/api/objs/cockpit_display.cpp | 38 ------ code/scripting/api/objs/comm_order.cpp | 11 +- code/scripting/api/objs/debris.cpp | 9 -- code/scripting/api/objs/decaldefinition.cpp | 13 +- code/scripting/api/objs/event.cpp | 13 +- code/scripting/api/objs/execution_context.cpp | 15 --- code/scripting/api/objs/executor.cpp | 18 --- code/scripting/api/objs/eye.cpp | 10 -- code/scripting/api/objs/file.cpp | 12 -- code/scripting/api/objs/fireballclass.cpp | 13 +- code/scripting/api/objs/font.cpp | 9 -- code/scripting/api/objs/gamehelp.cpp | 9 -- code/scripting/api/objs/goal.cpp | 11 +- code/scripting/api/objs/hudconfig.cpp | 32 ----- code/scripting/api/objs/hudgauge.cpp | 1 + code/scripting/api/objs/intelentry.cpp | 13 +- code/scripting/api/objs/mc_info.cpp | 13 -- code/scripting/api/objs/medals.cpp | 9 -- code/scripting/api/objs/message.cpp | 21 +--- code/scripting/api/objs/missionhotkey.cpp | 9 -- code/scripting/api/objs/missionlog.cpp | 18 --- code/scripting/api/objs/model.cpp | 111 ----------------- code/scripting/api/objs/model_path.cpp | 23 ---- code/scripting/api/objs/modelinstance.cpp | 36 ------ code/scripting/api/objs/movie_player.cpp | 18 --- code/scripting/api/objs/multi_objects.cpp | 112 ------------------ code/scripting/api/objs/object.cpp | 9 -- code/scripting/api/objs/order.cpp | 18 --- code/scripting/api/objs/parse_object.cpp | 9 -- code/scripting/api/objs/particle.cpp | 12 -- code/scripting/api/objs/physics_info.cpp | 9 -- code/scripting/api/objs/player.cpp | 12 -- code/scripting/api/objs/propclass.cpp | 18 +-- code/scripting/api/objs/rank.cpp | 9 -- code/scripting/api/objs/sexpvar.cpp | 12 -- code/scripting/api/objs/shields.cpp | 9 -- code/scripting/api/objs/ship_bank.cpp | 18 --- .../api/objs/ship_registry_entry.cpp | 13 +- code/scripting/api/objs/shipclass.cpp | 15 +-- code/scripting/api/objs/shiptype.cpp | 13 +- code/scripting/api/objs/shipwepselect.cpp | 1 + code/scripting/api/objs/sound.cpp | 28 +---- code/scripting/api/objs/sound.h | 2 + code/scripting/api/objs/species.cpp | 13 +- code/scripting/api/objs/streaminganim.cpp | 9 -- code/scripting/api/objs/subsystem.cpp | 9 -- .../scripting/api/objs/support_rearm_pool.cpp | 1 + code/scripting/api/objs/team.cpp | 13 +- code/scripting/api/objs/team_colors.cpp | 18 +-- code/scripting/api/objs/techroom.cpp | 10 -- code/scripting/api/objs/texture.cpp | 9 -- code/scripting/api/objs/volumetric.cpp | 15 --- code/scripting/api/objs/waypoint.cpp | 9 -- code/scripting/api/objs/weaponclass.cpp | 13 +- code/scripting/api/objs/wing.cpp | 13 +- code/scripting/api/objs/wingformation.cpp | 13 +- code/scripting/lua/LuaConvert.h | 8 +- test/src/scripting/api/base.cpp | 80 +++++++++++++ .../base/autoIsValid/data/scripts/test.lua | 16 +++ .../base/intValidator/data/scripts/test.lua | 7 ++ 68 files changed, 294 insertions(+), 982 deletions(-) create mode 100644 test/test_data/scripting/base/autoIsValid/data/scripts/test.lua create mode 100644 test/test_data/scripting/base/intValidator/data/scripts/test.lua diff --git a/code/scripting/ade.cpp b/code/scripting/ade.cpp index 44bff2bb35..8d1f25bbdb 100644 --- a/code/scripting/ade.cpp +++ b/code/scripting/ade.cpp @@ -316,7 +316,8 @@ int ade_table_entry::SetTable(lua_State* L, int p_amt_ldx, int p_mtb_ldx) // when using va_args for some reason. lua_pushstring(L, ""); lua_pushboolean(L, 0); - lua_pushcclosure(L, Function, 2); + lua_pushlightuserdata(L, Obj_upvalue); // upvalue(3) = Reference to ade_obj, if this is a generated function + lua_pushcclosure(L, Function, 3); } nset++; break; @@ -430,7 +431,7 @@ int ade_table_entry::SetTable(lua_State* L, int p_amt_ldx, int p_mtb_ldx) lua_pushstring(L, "__gc"); lua_pushfstring(L, "%s Destructor", GetName()); // upvalue(1) = function name lua_pushboolean(L, 0); // upvalue(2) = setting true/false - lua_pushlightuserdata(L, Destructor_upvalue); // upvalue(3) = Reference to ade_obj + lua_pushlightuserdata(L, Obj_upvalue); // upvalue(3) = Reference to ade_obj lua_pushcclosure(L, Destructor, 3); lua_rawset(L, mtb_ldx); } @@ -488,6 +489,20 @@ int ade_table_entry::SetTable(lua_State* L, int p_amt_ldx, int p_mtb_ldx) size_t ade_table_entry::AddSubentry(ade_table_entry& n_ate) { ade_table_entry ate = n_ate; ate.ParentIdx = Idx; + + // If a subentry with this name already exists (e.g. an explicitly declared function overriding one that was + // automatically generated), replace it in place so that both Lua and the documentation see only the latest one + if (ate.Name != nullptr) { + for (size_t i = 0; i < Num_subentries; i++) { + auto& existing = ade_manager::getInstance()->getEntry(Subentries[i]); + if (existing.Name != nullptr && strcmp(existing.Name, ate.Name) == 0) { + ate.Idx = existing.Idx; + existing = ate; + return ate.Idx; + } + } + } + size_t new_idx = ade_manager::getInstance()->addTableEntry(ate); //WMC - Oi. Moving the Ade_table_entries vector diff --git a/code/scripting/ade.h b/code/scripting/ade.h index 8c6b195206..dc6636784d 100644 --- a/code/scripting/ade.h +++ b/code/scripting/ade.h @@ -60,7 +60,7 @@ const size_t ODATA_PTR_SIZE = (size_t) -1; const int ADE_FUNCNAME_UPVALUE_INDEX = 1; const int ADE_SETTING_UPVALUE_INDEX = 2; -const int ADE_DESTRUCTOR_OBJ_UPVALUE_INDEX = 3; // Upvalue which stores the reference to the ade_obj of a destructor +const int ADE_OBJ_UPVALUE_INDEX = 3; // Upvalue which stores the reference to the ade_obj for destructors and generated functions #define ADE_SETTING_VAR lua_toboolean(L,lua_upvalueindex(ADE_SETTING_UPVALUE_INDEX)) template @@ -130,8 +130,14 @@ class ade_table_entry { //Functions/virtfuncs lua_CFunction Function = nullptr; + // Reference to the ade_obj, passed as an upvalue to Function (for generated functions) and Destructor + void* Obj_upvalue = nullptr; + + // For Objects, an optional validity predicate taking a pointer to the stored value. Set via ADE_OBJ_VALIDATOR; + // takes precedence over the stored type's isValid() member. + bool (*Validator)(const void*) = nullptr; + // For Objects, the destructor of the object - void* Destructor_upvalue = nullptr; lua_CFunction Destructor = nullptr; size_t Size = 0; @@ -245,6 +251,29 @@ struct ade_is_valid ().isValid()), 0)> : std: } }; +/** + * @brief Determines whether a value stored in an API object is valid + * + * A validator registered (via ADE_OBJ_VALIDATOR) on the object's table entry, or on that of any object it derives + * from, takes precedence; otherwise the stored type's isValid() member is used, and types without one are always + * considered valid. + * + * @param idx The table entry index of the API object + * @param value The stored value + */ +template +bool ade_object_is_valid(size_t idx, const T& value) +{ + for (size_t i = idx; i != UINT_MAX; i = ade_manager::getInstance()->getEntry(i).DerivatorIdx) + { + const auto& entry = ade_manager::getInstance()->getEntry(i); + if (entry.Validator != nullptr) + return entry.Validator(&value); + } + + return ade_is_valid::get(value); +} + /** * @brief Converts an object index to something that can be used with ade_set_args. * diff --git a/code/scripting/ade_api.h b/code/scripting/ade_api.h index b538a006ba..489f477560 100644 --- a/code/scripting/ade_api.h +++ b/code/scripting/ade_api.h @@ -98,21 +98,52 @@ class ade_obj : public ade_lib_handle { static int lua_destructor(lua_State* L) { auto* obj = - static_cast*>(lua_touserdata(L, lua_upvalueindex(ADE_DESTRUCTOR_OBJ_UPVALUE_INDEX))); + static_cast*>(lua_touserdata(L, lua_upvalueindex(ADE_OBJ_UPVALUE_INDEX))); StoreType* value = nullptr; if (!ade_get_args(L, "o", obj->GetPtr(&value))) { return 0; } - if (value == nullptr) { - return 0; - } - value->~StoreType(); return 0; } + // Automatically generated isValid() API function for types whose StoreType has an isValid() member or which have + // a validator registered via ADE_OBJ_VALIDATOR. An explicit ADE_FUNC(isValid, ...) declared after the ADE_OBJ + // replaces this one. + static int lua_isValid(lua_State* L) + { + auto* obj = + static_cast*>(lua_touserdata(L, lua_upvalueindex(ADE_OBJ_UPVALUE_INDEX))); + StoreType* value = nullptr; + if (!ade_get_args(L, "o", obj->GetPtr(&value))) { + return 0; // nil + } + + return ade_set_args(L, "b", ade_object_is_valid(obj->GetIdx(), *value)); + } + + // Registers the generated isValid() function as a member of this object. Safe to call more than once. + void registerIsValid() const + { + ade_table_entry func; + + func.Name = "isValid"; + func.Instanced = true; + func.Type = 'u'; + func.Function = lua_isValid; + func.Obj_upvalue = const_cast(static_cast(this)); + func.Arguments = nullptr; + func.Description = "Detects whether handle is valid"; + func.ReturnType = "boolean"; + func.ReturnDescription = "true if valid, false if handle is invalid, nil if a syntax/type error occurs"; + + ade_manager::getInstance()->getEntry(LibIdx).AddSubentry(func); + } + public: + using value_type = StoreType; + ade_obj(const char* in_name, const char* in_desc, const ade_lib_handle* in_deriv = nullptr, size_t size = 0, ade_serialize_func serializer = nullptr, ade_deserialize_func deserializer = nullptr) { ade_table_entry ate; @@ -132,11 +163,25 @@ class ade_obj : public ade_lib_handle { // If this type is not trivial then we need to have a destructor // This is mildly dangerous since "this" will only remain valid if it was constructed statically. Since this // value is only used once at program startup it should be relatively safe - ate.Destructor_upvalue = static_cast(this); - ate.Destructor = lua_destructor; + ate.Obj_upvalue = static_cast(this); + ate.Destructor = lua_destructor; } LibIdx = ade_manager::getInstance()->addTableEntry(ate); + + // If the stored type can report its validity, expose that to Lua automatically. Derived types inherit + // this from their base object (which in all current cases stores the same type), so skip it for those. + if (ade_is_valid::value && in_deriv == nullptr) { + registerIsValid(); + } + } + + // Registers a validity predicate for this object, used by the generated isValid() function and by ade_set_args + // when returning nil instead of invalid objects. Use the ADE_OBJ_VALIDATOR macro rather than calling this directly. + void setValidator(bool (*fn)(const void*)) const + { + ade_manager::getInstance()->getEntry(LibIdx).Validator = fn; + registerIsValid(); } // WMC - Use this to store object data for return, or for setting as a global @@ -219,8 +264,61 @@ class ade_obj : public ade_lib_handle { * @ingroup ade_api */ #define ADE_OBJ_DERIV(field, type, name, desc, deriv) \ + static_assert(std::is_same>::value_type>::value, \ + "A derived API object must store the same type as the object it derives from"); \ ADE_OBJ_DERIV_IMPL(field, type, name, desc, &SCP_TOKEN_CONCAT(get_, deriv)(), ade_multi_serializer) +/** + * Validator registration class. Use the ADE_OBJ_VALIDATOR macro rather than declaring one of these directly. + * + * @ingroup ade_api + */ +class ade_validator { + public: + template + ade_validator(const ade_obj& obj, bool (*fn)(const void*)) + { + obj.setValidator(fn); + } +}; + +/** + * @brief Declare a validity predicate for an API object + * + * This generates an isValid() function for the object, and also lets the engine return nil instead of an invalid + * handle when the mod table option for that is set. Use this for objects whose stored type cannot report its own + * validity (e.g. an int index into a table); objects whose stored type has an isValid() member get this automatically. + * + * @param field The name of the object field (e.g. l_Shipclass) + * @param var The name by which the stored value is referred to in the expression + * @param expr An expression yielding true when the value is valid; evaluated each time validity is checked + * + * @ingroup ade_api + */ +#define ADE_OBJ_VALIDATOR(field, var, expr) \ + static bool SCP_TOKEN_CONCAT(field, _validator)(const void* ade_validator_value) \ + { \ + const auto& var = \ + *static_cast::value_type*>(ade_validator_value); \ + return (expr); \ + } \ + static ::scripting::ade_validator SCP_TOKEN_CONCAT(field, _validator_registrar)(SCP_TOKEN_CONCAT(get_, field)(), \ + SCP_TOKEN_CONCAT(field, _validator)) + +/** + * @brief Declare an index-based API object as valid for the range [0, upper) + * + * Shorthand for ADE_OBJ_VALIDATOR for the common case of an int index. The upper bound is evaluated each time + * validity is checked, so it can (and usually should) be a function call or a container size. + * + * @param field The name of the object field (e.g. l_Shipclass) + * @param upper The exclusive upper bound of the valid range + * + * @ingroup ade_api + */ +#define ADE_OBJ_VALIDATOR_RANGE(field, upper) ADE_OBJ_VALIDATOR(field, idx, idx >= 0 && idx < (upper)) + /** * @brief Declare an API object but don't define it * diff --git a/code/scripting/ade_args.h b/code/scripting/ade_args.h index 09226a4116..b0a1ccbcd9 100644 --- a/code/scripting/ade_args.h +++ b/code/scripting/ade_args.h @@ -307,8 +307,9 @@ void set_single_arg(lua_State* L, char fmt, ade_odata_setter&& od) Assertion(fmt == 'o', "Invalid format character '%c' for object type!", fmt); if (Lua_API_returns_nil_instead_of_invalid_object) { - // If the underlying type has an isValid, it'll be evaluated; otherwise it'll be always true. - bool isValid = ade_is_valid::get(od.value); + // A registered validator wins; otherwise, if the underlying type has an isValid, it'll be evaluated; + // otherwise it'll be always true. + bool isValid = ade_object_is_valid(od.idx, od.value); if (!isValid) { lua_pushnil(L); diff --git a/code/scripting/api/objs/LuaEnum.cpp b/code/scripting/api/objs/LuaEnum.cpp index 3e42776e87..ab3e4691a8 100644 --- a/code/scripting/api/objs/LuaEnum.cpp +++ b/code/scripting/api/objs/LuaEnum.cpp @@ -128,14 +128,5 @@ ADE_FUNC(removeEnumItem, return ADE_RETURN_FALSE; } -ADE_FUNC(isValid, l_LuaEnum, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - lua_enum_h lua_enum; - if (!ade_get_args(L, "o", l_LuaEnum.Get(&lua_enum))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", lua_enum.isValid()); -} - } // namespace api } // namespace scripting diff --git a/code/scripting/api/objs/audio_stream.cpp b/code/scripting/api/objs/audio_stream.cpp index 2f34e49edb..3c8de7f1eb 100644 --- a/code/scripting/api/objs/audio_stream.cpp +++ b/code/scripting/api/objs/audio_stream.cpp @@ -8,6 +8,7 @@ namespace api { //**********HANDLE: Asteroid ADE_OBJ_NO_MULTI(l_AudioStream, int, "audio_stream", "An audio stream handle"); +ADE_OBJ_VALIDATOR(l_AudioStream, idx, idx >= 0); ADE_FUNC(play, l_AudioStream, @@ -161,20 +162,5 @@ ADE_FUNC(getDuration, l_AudioStream, nullptr, "Gets the duration of the stream", return ade_set_args(L, "f", (float)audiostream_get_duration(streamHandle)); } -ADE_FUNC(isValid, - l_AudioStream, - nullptr, - "Determines if the handle is valid", - "boolean", - "true if valid, false otherwise") -{ - int streamHandle = -1; - if (!ade_get_args(L, "o", l_AudioStream.Get(&streamHandle))) { - return ADE_RETURN_FALSE; - } - - return ade_set_args(L, "b", streamHandle >= 0); -} - } // namespace api } // namespace scripting diff --git a/code/scripting/api/objs/background_element.cpp b/code/scripting/api/objs/background_element.cpp index 6cfcaab258..a3ee92b946 100644 --- a/code/scripting/api/objs/background_element.cpp +++ b/code/scripting/api/objs/background_element.cpp @@ -26,16 +26,6 @@ bool background_el_h::isValid() const } } -ADE_FUNC(isValid, l_BackgroundElement, nullptr, "Determines if this handle is valid", "boolean", - "true if valid, false if not.") -{ - background_el_h* el = nullptr; - if (!ade_get_args(L, "o", l_BackgroundElement.GetPtr(&el))) - return ADE_RETURN_FALSE; - - return ade_set_args(L, "b", el->isValid()); -} - ADE_VIRTVAR(Orientation, l_BackgroundElement, "orientation", "Backround element orientation (treating the angles as correctly calculated)", "orientation", "Orientation, or null orientation if handle is invalid") { background_el_h* el = nullptr; diff --git a/code/scripting/api/objs/camera.cpp b/code/scripting/api/objs/camera.cpp index 789012ca13..3e798b4dd9 100644 --- a/code/scripting/api/objs/camera.cpp +++ b/code/scripting/api/objs/camera.cpp @@ -25,18 +25,6 @@ ADE_FUNC(__tostring, l_Camera, NULL, "Camera name", "string", "Camera name, or a return ade_set_args(L, "s", cid.getCamera()->get_name()); } -ADE_FUNC(isValid, l_Camera, NULL, "True if valid, false or nil if not", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - camid cid; - if(!ade_get_args(L, "o", l_Camera.Get(&cid))) - return ADE_RETURN_NIL; - - if(!cid.isValid()) - return ADE_RETURN_FALSE; - - return ADE_RETURN_TRUE; -} - ADE_VIRTVAR(Name, l_Camera, "string", "New camera name", "string", "Camera name") { camid cid; diff --git a/code/scripting/api/objs/cockpit_display.cpp b/code/scripting/api/objs/cockpit_display.cpp index 02cd6dfb6a..76b1b285d8 100644 --- a/code/scripting/api/objs/cockpit_display.cpp +++ b/code/scripting/api/objs/cockpit_display.cpp @@ -168,16 +168,6 @@ ADE_FUNC(getOffset, return ade_set_args(L, "ii", cdi->offset[0], cdi->offset[1]); } -ADE_FUNC(isValid, l_DisplayInfo, NULL, "Detects whether this handle is valid", "boolean", "true if valid false otherwise") -{ - cockpit_disp_info_h *cdh = NULL; - - if (!ade_get_args(L, "o", l_DisplayInfo.GetPtr(&cdh))) - return ADE_RETURN_FALSE; - - return ade_set_args(L, "b", cdh->isValid()); -} - cockpit_display_h::cockpit_display_h() : m_obj_num( -1 ), m_display_num( INVALID_ID ) {} @@ -354,16 +344,6 @@ ADE_FUNC(getOffset, return ade_set_args(L, "ii", cd->offset[0], cd->offset[1]); } -ADE_FUNC(isValid, l_CockpitDisplay, NULL, "Detects whether this handle is valid or not", "boolean", "true if valid, false otherwise") -{ - cockpit_display_h *cdh = NULL; - - if (!ade_get_args(L, "o", l_CockpitDisplay.GetPtr(&cdh))) - return ADE_RETURN_FALSE; - - return ade_set_args(L, "b", cdh->isValid()); -} - cockpit_displays_info_h::cockpit_displays_info_h() : m_ship_info_idx( -1 ) {} cockpit_displays_info_h::cockpit_displays_info_h(int ship_info_idx) { @@ -485,15 +465,6 @@ ADE_INDEXER(l_CockpitDisplayInfos, "number/string", } } -ADE_FUNC(isValid, l_CockpitDisplayInfos, NULL, "Detects whether this handle is valid", "boolean", "true if valid, false otehrwise") -{ - cockpit_displays_info_h *cdih = NULL; - if (!ade_get_args(L, "o", l_CockpitDisplayInfos.GetPtr(&cdih))) - return ADE_RETURN_FALSE; - - return ade_set_args(L, "b", cdih->isValid()); -} - cockpit_displays_h::cockpit_displays_h() : m_obj_num( -1 ) {} cockpit_displays_h::cockpit_displays_h(int obj_num) : m_obj_num( obj_num ) {} @@ -600,15 +571,6 @@ ADE_INDEXER(l_CockpitDisplays, "number/string", "Gets a cockpit display from the } } -ADE_FUNC(isValid, l_CockpitDisplays, NULL, "Detects whether this handle is valid or not", "boolean", "true if valid, false otherwise") -{ - cockpit_displays_h *cdh = NULL; - if(!ade_get_args(L, "o", l_CockpitDisplays.GetPtr(&cdh))) - return ADE_RETURN_FALSE; - - return ade_set_args(L, "b", cdh->isValid()); -} - } } diff --git a/code/scripting/api/objs/comm_order.cpp b/code/scripting/api/objs/comm_order.cpp index 89baa85475..bc4811a750 100644 --- a/code/scripting/api/objs/comm_order.cpp +++ b/code/scripting/api/objs/comm_order.cpp @@ -6,6 +6,7 @@ namespace scripting::api { //**********HANDLE: mission goals ADE_OBJ_NO_MULTI(l_Comm_Item, int, "comm_item", "Comm Item handle"); +ADE_OBJ_VALIDATOR(l_Comm_Item, idx, MsgItems.in_bounds(idx)); ADE_VIRTVAR(Name, l_Comm_Item, nullptr, "The name of the comm item", "string", "The comm item name") { @@ -73,14 +74,4 @@ ADE_FUNC(selectItem, l_Comm_Item, nullptr, "Selects the item and either proceeds return ADE_RETURN_TRUE; } -ADE_FUNC(isValid, l_Comm_Item, nullptr, "Detect if the handle is valid", "boolean", "true if valid, false otherwise") -{ - int current = -1; - - if (!ade_get_args(L, "o", l_Comm_Item.Get(¤t))) - return ADE_RETURN_FALSE; - - return ade_set_args(L, "b", MsgItems.in_bounds(current)); -} - } // namespace scripting::api diff --git a/code/scripting/api/objs/debris.cpp b/code/scripting/api/objs/debris.cpp index 7ff9e93a73..716f4d0b97 100644 --- a/code/scripting/api/objs/debris.cpp +++ b/code/scripting/api/objs/debris.cpp @@ -130,15 +130,6 @@ ADE_FUNC(getDebrisRadius, l_Debris, NULL, "The radius of this debris piece", "nu return ade_set_error(L, "f", pm->submodel[db->submodel_num].rad); } -ADE_FUNC(isValid, l_Debris, NULL, "Return if this debris handle is valid", "boolean", "true if valid false otherwise") -{ - object_h *oh; - if(!ade_get_args(L, "o", l_Debris.GetPtr(&oh))) - return ADE_RETURN_FALSE; - - return ade_set_args(L, "b", oh != NULL && oh->isValid()); -} - ADE_FUNC(isGeneric, l_Debris, nullptr, "Return if this debris is the generic debris model, not a model subobject", "boolean", "true if Debris_model") { object_h *oh; diff --git a/code/scripting/api/objs/decaldefinition.cpp b/code/scripting/api/objs/decaldefinition.cpp index 84bb6306eb..2809a58286 100644 --- a/code/scripting/api/objs/decaldefinition.cpp +++ b/code/scripting/api/objs/decaldefinition.cpp @@ -13,6 +13,7 @@ namespace api { //**********HANDLE: DecalDefinitionclass ADE_OBJ(l_DecalDefinitionclass, int, "decaldefinition", "Decal definition handle"); +ADE_OBJ_VALIDATOR(l_DecalDefinitionclass, idx, decals::DecalDefinitions.in_bounds(idx)); ADE_FUNC(__tostring, l_DecalDefinitionclass, nullptr, "Decal definition name", "string", "Decal definition unique id, or an empty string if handle is invalid") { @@ -42,18 +43,6 @@ ADE_FUNC(__eq, l_DecalDefinitionclass, "decaldefinition, decaldefinition", "Chec return ade_set_args(L, "b", idx1 == idx2); } -ADE_FUNC(isValid, l_DecalDefinitionclass, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if invalid, nil if a syntax/type error occurs") -{ - int idx; - if (!ade_get_args(L, "o", l_DecalDefinitionclass.Get(&idx))) - return ADE_RETURN_NIL; - - if (idx < 0 || idx >= static_cast(decals::DecalDefinitions.size())) - return ADE_RETURN_FALSE; - - return ADE_RETURN_TRUE; -} - ADE_VIRTVAR(Name, l_DecalDefinitionclass, "string", "Decal definition name", "string", "Decal definition name, or empty string if handle is invalid") { int idx; diff --git a/code/scripting/api/objs/event.cpp b/code/scripting/api/objs/event.cpp index e4e61f3585..8eae5fb1f8 100644 --- a/code/scripting/api/objs/event.cpp +++ b/code/scripting/api/objs/event.cpp @@ -8,6 +8,7 @@ namespace scripting::api { //**********HANDLE: mission event ADE_OBJ(l_Event, int, "mission_event", "Mission event handle"); +ADE_OBJ_VALIDATOR(l_Event, idx, Mission_events.in_bounds(idx)); ADE_VIRTVAR(Name, l_Event, "string", "Mission event name", "string", nullptr) { @@ -142,16 +143,4 @@ ADE_VIRTVAR(Score, l_Event, "number", "Event score", "number", "Event score, or return ade_set_args(L, "i", mep->score); } -ADE_FUNC(isValid, l_Event, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - int idx; - if (!ade_get_args(L, "o", l_Event.Get(&idx))) - return ADE_RETURN_NIL; - - if (idx < 0 || idx >= (int)Mission_events.size()) - return ADE_RETURN_FALSE; - - return ADE_RETURN_TRUE; -} - } diff --git a/code/scripting/api/objs/execution_context.cpp b/code/scripting/api/objs/execution_context.cpp index 36121615d7..5a53a27d2d 100644 --- a/code/scripting/api/objs/execution_context.cpp +++ b/code/scripting/api/objs/execution_context.cpp @@ -48,20 +48,5 @@ ADE_FUNC(determineState, } } -ADE_FUNC(isValid, - l_ExecutionContext, - nullptr, - "Determines if the handle is valid", - "boolean", - "true if valid, false otherwise") -{ - execution_context_h* context = nullptr; - if (!ade_get_args(L, "o", l_ExecutionContext.GetPtr(&context))) { - return ADE_RETURN_FALSE; - } - - return ade_set_args(L, "b", context != nullptr && context->isValid()); -} - } // namespace api } // namespace scripting diff --git a/code/scripting/api/objs/executor.cpp b/code/scripting/api/objs/executor.cpp index 8e26d97450..2f4b0d5788 100644 --- a/code/scripting/api/objs/executor.cpp +++ b/code/scripting/api/objs/executor.cpp @@ -60,23 +60,5 @@ ADE_FUNC(schedule, return ADE_RETURN_TRUE; } -ADE_FUNC(isValid, - l_Executor, - nullptr, - "Determined if this handle is valid", - "boolean", - "true if valid, false otherwise.") -{ - executor_h* executor = nullptr; - if (!ade_get_args(L, "o", l_Executor.GetPtr(&executor))) { - return ADE_RETURN_FALSE; - } - - if (executor == nullptr || !executor->isValid()) { - return ADE_RETURN_FALSE; - } - return ADE_RETURN_TRUE; -} - } // namespace api } // namespace scripting diff --git a/code/scripting/api/objs/eye.cpp b/code/scripting/api/objs/eye.cpp index c444a63856..34f16755b9 100644 --- a/code/scripting/api/objs/eye.cpp +++ b/code/scripting/api/objs/eye.cpp @@ -68,16 +68,6 @@ ADE_VIRTVAR(Position, l_Eyepoint, "vector", "Eyepoint location (Local vector)", return ade_set_args(L, "o", l_Vector.Set(pm->view_positions[eh->eye_idx].pnt)); } -ADE_FUNC(isValid, l_Eyepoint, nullptr, "Detect whether this handle is valid", "boolean", "true if valid false otherwise") -{ - eye_h* eh = nullptr; - if (!ade_get_args(L, "o", l_Eyepoint.GetPtr(&eh))) { - return ADE_RETURN_FALSE; - } - - return ade_set_args(L, "b", eh->isValid()); -} - ADE_FUNC_DEPRECATED(IsValid, l_Eyepoint, nullptr, diff --git a/code/scripting/api/objs/file.cpp b/code/scripting/api/objs/file.cpp index e3ce260a32..08a0904bd9 100644 --- a/code/scripting/api/objs/file.cpp +++ b/code/scripting/api/objs/file.cpp @@ -26,18 +26,6 @@ void cfile_h::close() //**********HANDLE: File ADE_OBJ(l_File, cfile_h, "file", "File handle"); -ADE_FUNC(isValid, l_File, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - cfile_h* cfp = nullptr; - if (!ade_get_args(L, "o", l_File.GetPtr(&cfp))) - return ADE_RETURN_NIL; - - if (cfp == nullptr || !cfp->isValid()) - return ADE_RETURN_FALSE; - - return ADE_RETURN_TRUE; -} - ADE_FUNC(close, l_File, NULL, "Instantly closes file and invalidates all file handles", NULL, NULL) { cfile_h* cfp = nullptr; diff --git a/code/scripting/api/objs/fireballclass.cpp b/code/scripting/api/objs/fireballclass.cpp index dacbe8e805..214d57a295 100644 --- a/code/scripting/api/objs/fireballclass.cpp +++ b/code/scripting/api/objs/fireballclass.cpp @@ -11,6 +11,7 @@ namespace api { //**********HANDLE: Fireballclass ADE_OBJ(l_Fireballclass, int, "fireballclass", "Fireball class handle"); +ADE_OBJ_VALIDATOR(l_Fireballclass, idx, Fireball_info.in_bounds(idx)); ADE_FUNC(__tostring, l_Fireballclass, NULL, "Fireball class name", "string", "Fireball class unique id, or an empty string if handle is invalid") { @@ -100,18 +101,6 @@ ADE_VIRTVAR(FPS, l_Fireballclass, NULL, "The FPS with which this fireball's anim return ade_set_args(L, "i", Fireball_info[idx].lod[0].fps); } -ADE_FUNC(isValid, l_Fireballclass, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - int idx; - if(!ade_get_args(L, "o", l_Fireballclass.Get(&idx))) - return ADE_RETURN_NIL; - - if (!SCP_vector_inbounds(Fireball_info, idx)) - return ADE_RETURN_FALSE; - - return ADE_RETURN_TRUE; -} - ADE_FUNC(getTableIndex, l_Fireballclass, NULL, "Gets the index value of the fireball class", "number", "index value of the fireball class") { int idx; diff --git a/code/scripting/api/objs/font.cpp b/code/scripting/api/objs/font.cpp index 46503d7f8d..080fa139ed 100644 --- a/code/scripting/api/objs/font.cpp +++ b/code/scripting/api/objs/font.cpp @@ -186,14 +186,5 @@ ADE_FUNC(hasCanScale, l_Font, nullptr, "True if this font is allowed to scale ba return ade_set_args(L, "b", fh != nullptr && fh->Get()->getScaleBehavior()); } -ADE_FUNC(isValid, l_Font, nullptr, "True if valid, false or nil if not", "boolean", "Detects whether handle is valid") -{ - font_h *fh = nullptr; - if (!ade_get_args(L, "o", l_Font.GetPtr(&fh))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", fh != nullptr && fh->isValid()); -} - } } // namespace scripting diff --git a/code/scripting/api/objs/gamehelp.cpp b/code/scripting/api/objs/gamehelp.cpp index f2c9ba3c78..b47a77ba51 100644 --- a/code/scripting/api/objs/gamehelp.cpp +++ b/code/scripting/api/objs/gamehelp.cpp @@ -24,15 +24,6 @@ bool help_section_h::isValid() const //**********HANDLE: help section ADE_OBJ(l_Help_Section, help_section_h, "help_section", "Help Section handle"); -ADE_FUNC(isValid, l_Help_Section, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - help_section_h current; - if (!ade_get_args(L, "o", l_Help_Section.Get(¤t))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", current.isValid()); -} - ADE_VIRTVAR(Title, l_Help_Section, nullptr, "The title of the help section", "string", "The title") { help_section_h current; diff --git a/code/scripting/api/objs/goal.cpp b/code/scripting/api/objs/goal.cpp index 59b9d02af8..d052a8f5c7 100644 --- a/code/scripting/api/objs/goal.cpp +++ b/code/scripting/api/objs/goal.cpp @@ -9,6 +9,7 @@ namespace scripting::api { //**********HANDLE: mission goal ADE_OBJ(l_Goal, int, "mission_goal", "Mission goal handle"); +ADE_OBJ_VALIDATOR(l_Goal, idx, Mission_goals.in_bounds(idx)); ADE_VIRTVAR(Name, l_Goal, nullptr, "The name of the goal", "string", "The goal name") { @@ -129,14 +130,4 @@ ADE_VIRTVAR(isGoalValid, l_Goal, nullptr, "The goal validity", "boolean", "true return ade_set_args(L, "b", !(Mission_goals[current].type & INVALID_GOAL)); } -ADE_FUNC(isValid, l_Goal, nullptr, "Detect if the handle is valid", "boolean", "true if valid, false otherwise") -{ - int current = -1; - - if (!ade_get_args(L, "o", l_Goal.Get(¤t))) - return ADE_RETURN_FALSE; - - return ade_set_args(L, "b", (current >= 0) && (current < (int)Mission_goals.size())); -} - } diff --git a/code/scripting/api/objs/hudconfig.cpp b/code/scripting/api/objs/hudconfig.cpp index 6bb42fb08f..e2a3aa458c 100644 --- a/code/scripting/api/objs/hudconfig.cpp +++ b/code/scripting/api/objs/hudconfig.cpp @@ -118,20 +118,6 @@ ADE_VIRTVAR(Color, l_HUD_Color_Preset, nullptr, "The name of this preset", "colo return ade_set_args(L, "o", l_Color.Set(c)); } -ADE_FUNC(isValid, - l_HUD_Color_Preset, - nullptr, - "Detects whether handle is valid", - "boolean", - "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - hud_color_preset_h current; - if (!ade_get_args(L, "o", l_HUD_Color_Preset.Get(¤t))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", current.isValid()); -} - //**********HANDLE: hud preset ADE_OBJ(l_HUD_Preset, hud_preset_h, "hud_preset", "Hud preset handle"); @@ -169,15 +155,6 @@ ADE_FUNC(deletePreset, l_HUD_Preset, nullptr, "Deletes the preset file", nullptr return ADE_RETURN_NIL; } -ADE_FUNC(isValid, l_HUD_Preset, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - hud_preset_h current; - if (!ade_get_args(L, "o", l_HUD_Preset.Get(¤t))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", current.isValid()); -} - //**********HANDLE: gauge config ADE_OBJ(l_Gauge_Config, gauge_config_h, "gauge_config", "Gauge config handle"); @@ -407,14 +384,5 @@ ADE_FUNC(setSelected, l_Gauge_Config, "boolean", "Sets if the gauge is the curre return ADE_RETURN_NIL; } -ADE_FUNC(isValid, l_Gauge_Config, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - gauge_config_h current; - if (!ade_get_args(L, "o", l_Gauge_Config.Get(¤t))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", current.isValid()); -} - } // namespace api } // namespace scripting \ No newline at end of file diff --git a/code/scripting/api/objs/hudgauge.cpp b/code/scripting/api/objs/hudgauge.cpp index 85ebdaa23f..31630d83e0 100644 --- a/code/scripting/api/objs/hudgauge.cpp +++ b/code/scripting/api/objs/hudgauge.cpp @@ -11,6 +11,7 @@ namespace scripting { namespace api { ADE_OBJ(l_HudGauge, HudGauge*, "HudGauge", "HUD Gauge handle"); +ADE_OBJ_VALIDATOR(l_HudGauge, gauge, gauge != nullptr); ADE_FUNC(isCustom, l_HudGauge, nullptr, "Custom HUD Gauge status", "boolean", "Returns true if this is a custom HUD gauge, or false if it is a non-custom (default) HUD gauge") { diff --git a/code/scripting/api/objs/intelentry.cpp b/code/scripting/api/objs/intelentry.cpp index 80ba5794f9..0ad62eb849 100644 --- a/code/scripting/api/objs/intelentry.cpp +++ b/code/scripting/api/objs/intelentry.cpp @@ -10,6 +10,7 @@ namespace api { //**********HANDLE: Intelentry ADE_OBJ(l_Intelentry, int, "intel_entry", "Intel entry handle"); +ADE_OBJ_VALIDATOR_RANGE(l_Intelentry, intel_info_size()); ADE_FUNC(__tostring, l_Intelentry, nullptr, "Intel entry name", "string", "Intel entry name, or an empty string if handle is invalid") { @@ -174,18 +175,6 @@ ADE_FUNC(hasCustomData, return ade_set_args(L, "b", result); } -ADE_FUNC(isValid, l_Intelentry, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - int idx; - if(!ade_get_args(L, "o", l_Intelentry.Get(&idx))) - return ADE_RETURN_NIL; - - if(idx < 0 || idx >= intel_info_size()) - return ADE_RETURN_FALSE; - - return ADE_RETURN_TRUE; -} - ADE_FUNC(getIntelEntryIndex, l_Intelentry, nullptr, "Gets the index value of the intel entry", "number", "index value of the intel entry") { int idx; diff --git a/code/scripting/api/objs/mc_info.cpp b/code/scripting/api/objs/mc_info.cpp index 4204300015..5a99e128d2 100644 --- a/code/scripting/api/objs/mc_info.cpp +++ b/code/scripting/api/objs/mc_info.cpp @@ -147,18 +147,5 @@ ADE_FUNC(getCollisionNormal, l_ColInfo, "[boolean local]", "The collision normal } } -ADE_FUNC(isValid, l_ColInfo, NULL, "Detects if this handle is valid", "boolean", "true if valid false otherwise") -{ - mc_info_h* info; - - if(!ade_get_args(L, "o", l_ColInfo.GetPtr(&info))) - return ADE_RETURN_FALSE; - - if (info->isValid()) - return ADE_RETURN_TRUE; - else - return ADE_RETURN_FALSE; -} - } } diff --git a/code/scripting/api/objs/medals.cpp b/code/scripting/api/objs/medals.cpp index 6062e3c5c4..2137f73a0d 100644 --- a/code/scripting/api/objs/medals.cpp +++ b/code/scripting/api/objs/medals.cpp @@ -29,15 +29,6 @@ bool medal_h::isRank() const //**********HANDLE: medal ADE_OBJ(l_Medal, medal_h, "medal", "Medal handle"); -ADE_FUNC(isValid, l_Medal, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - medal_h current; - if (!ade_get_args(L, "o", l_Medal.Get(¤t))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", current.isValid()); -} - ADE_VIRTVAR(Name, l_Medal, nullptr, "The name of the medal", "string", "The name") { medal_h current; diff --git a/code/scripting/api/objs/message.cpp b/code/scripting/api/objs/message.cpp index 8deee92e4c..32363a031e 100644 --- a/code/scripting/api/objs/message.cpp +++ b/code/scripting/api/objs/message.cpp @@ -15,6 +15,7 @@ namespace api { //**********HANDLE: Persona ADE_OBJ(l_Persona, int, "persona", "Persona handle"); +ADE_OBJ_VALIDATOR(l_Persona, idx, Personas.in_bounds(idx)); ADE_VIRTVAR(Name, l_Persona, "string", "The name of the persona", "string", "The name or empty string on error") { @@ -83,18 +84,9 @@ ADE_FUNC(hasCustomData, l_Persona, nullptr, "Detects whether the persona has any return ade_set_args(L, "b", result); } -ADE_FUNC(isValid, l_Persona, nullptr, "Detect if the handle is valid", "boolean", "true if valid, false otherwise") -{ - int idx = -1; - - if (!ade_get_args(L, "o", l_Persona.Get(&idx))) - return ADE_RETURN_FALSE; - - return ade_set_args(L, "b", SCP_vector_inbounds(Personas, idx)); -} - //**********HANDLE: Message ADE_OBJ(l_Message, int, "message", "Handle to a mission message"); +ADE_OBJ_VALIDATOR(l_Message, idx, Messages.in_bounds(idx)); ADE_VIRTVAR(Name, l_Message, "string", "The name of the message as specified in the mission file", "string", "The name or an empty string if handle is invalid") { @@ -216,15 +208,6 @@ ADE_FUNC(getMessage, l_Message, "[boolean replaceStuff = true]", "Gets the text } } -ADE_FUNC(isValid, l_Message, nullptr, "Checks if the message handle is valid", "boolean", "true if valid, false otherwise") -{ - int idx = -1; - if (!ade_get_args(L, "o", l_Message.Get(&idx))) - return ADE_RETURN_FALSE; - - return ade_set_args(L, "b", SCP_vector_inbounds(Messages, idx)); -} - } } diff --git a/code/scripting/api/objs/missionhotkey.cpp b/code/scripting/api/objs/missionhotkey.cpp index c207f2fa90..b964343ee5 100644 --- a/code/scripting/api/objs/missionhotkey.cpp +++ b/code/scripting/api/objs/missionhotkey.cpp @@ -31,15 +31,6 @@ bool hotkey_h::isValid() const //**********HANDLE: help section ADE_OBJ(l_Hotkey, hotkey_h, "hotkey_ship", "Hotkey handle"); -ADE_FUNC(isValid, l_Hotkey, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - hotkey_h current; - if (!ade_get_args(L, "o", l_Hotkey.Get(¤t))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", current.isValid()); -} - ADE_VIRTVAR(Text, l_Hotkey, nullptr, "The text of this hotkey line", "string", "The text") { hotkey_h current; diff --git a/code/scripting/api/objs/missionlog.cpp b/code/scripting/api/objs/missionlog.cpp index ca29616364..c70c3b62f3 100644 --- a/code/scripting/api/objs/missionlog.cpp +++ b/code/scripting/api/objs/missionlog.cpp @@ -46,15 +46,6 @@ bool message_entry_h::isValid() const //**********HANDLE: log entry ADE_OBJ(l_Log_Entry, log_entry_h, "log_entry", "Log Entry handle"); -ADE_FUNC(isValid, l_Log_Entry, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - log_entry_h current; - if (!ade_get_args(L, "o", l_Log_Entry.Get(¤t))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", current.isValid()); -} - ADE_VIRTVAR(Timestamp, l_Log_Entry, nullptr, "The timestamp of the log entry", "string", "The timestamp") { log_entry_h current; @@ -215,15 +206,6 @@ ADE_VIRTVAR(SegmentColors, //**********HANDLE: message entry ADE_OBJ(l_Message_Entry, message_entry_h, "message_entry", "Message Entry handle"); -ADE_FUNC(isValid, l_Message_Entry, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - message_entry_h current; - if (!ade_get_args(L, "o", l_Message_Entry.Get(¤t))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", current.isValid()); -} - ADE_VIRTVAR(Timestamp, l_Message_Entry, nullptr, "The timestamp of the message entry", "string", "The timestamp") { message_entry_h current; diff --git a/code/scripting/api/objs/model.cpp b/code/scripting/api/objs/model.cpp index e192610667..319105871e 100644 --- a/code/scripting/api/objs/model.cpp +++ b/code/scripting/api/objs/model.cpp @@ -327,15 +327,6 @@ ADE_FUNC(getDetailRoot, l_Model, "[number detailLevel]", "Returns the root submo return ade_set_args(L, "o", l_Submodel.Set(submodel_h(pm, pm->detail[detail]))); } -ADE_FUNC(isValid, l_Model, nullptr, "True if valid, false or nil if not", "boolean", "Detects whether handle is valid") -{ - model_h *mdl; - if (!ade_get_args(L, "o", l_Model.GetPtr(&mdl))) - return ADE_RETURN_FALSE; - - return ade_set_args(L, "b", mdl->isValid()); -} - ADE_VIRTVAR(Name, l_Submodel, nullptr, "Gets the submodel's name", "string", "The name or an empty string if invalid") { submodel_h *smh = nullptr; @@ -508,15 +499,6 @@ ADE_FUNC(getParent, l_Submodel, nullptr, "Gets the parent submodel of this submo return ade_set_args(L, "o", l_Submodel.Set(submodel_h(smh->GetModel(), sm->parent))); } -ADE_FUNC(isValid, l_Submodel, nullptr, "True if valid, false or nil if not", "boolean", "Detects whether handle is valid") -{ - submodel_h *smh; - if (!ade_get_args(L, "o", l_Submodel.GetPtr(&smh))) - return ADE_RETURN_FALSE; - - return ade_set_args(L, "b", smh->isValid()); -} - ADE_VIRTVAR(NoCollide, l_Submodel, nullptr, "Whether the submodel and its children ignore collisions", "boolean", "The flag, or error-false if invalid") { submodel_h* smh = nullptr; @@ -606,15 +588,6 @@ ADE_INDEXER(l_ModelSubmodels, "submodel", "number|string IndexOrName", "submodel return ade_set_args(L, "o", l_Submodel.Set(submodel_h(pm, index))); } -ADE_FUNC(isValid, l_ModelSubmodels, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if invalid, nil if a syntax/type error occurs") -{ - model_h *msh; - if (!ade_get_args(L, "o", l_ModelSubmodels.GetPtr(&msh))) - return ADE_RETURN_FALSE; - - return ade_set_args(L, "b", msh->isValid()); -} - //**********HANDLE: modeltextures ADE_OBJ(l_ModelTextures, model_h, "textures", "Array of textures"); @@ -682,15 +655,6 @@ ADE_INDEXER(l_ModelTextures, "texture", "number Index/string TextureName", "text return ade_set_args(L, "o", l_Texture.Set(texture_h(tinfo->GetTexture()))); } -ADE_FUNC(isValid, l_ModelTextures, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - model_h *mth; - if(!ade_get_args(L, "o", l_ModelTextures.GetPtr(&mth))) - return ADE_RETURN_FALSE; - - return ade_set_args(L, "b", mth->isValid()); -} - //**********HANDLE: eyepoints ADE_OBJ(l_ModelEyepoints, model_h, "eyepoints", "Array of model eye points"); @@ -730,15 +694,6 @@ ADE_INDEXER(l_ModelEyepoints, "eyepoint", "Gets an eyepoint handle", "eyepoint", return ade_set_args(L, "o", l_Eyepoint.Set(eye_h(pm->id, index))); } -ADE_FUNC(isValid, l_ModelEyepoints, NULL, "Detects whether handle is valid or not", "boolean", "true if valid false otherwise") -{ - model_h *eph; - if(!ade_get_args(L, "o", l_ModelEyepoints.GetPtr(&eph))) - return ADE_RETURN_FALSE; - - return ade_set_args(L, "b", eph->isValid()); -} - //**********HANDLE: thrusters ADE_OBJ(l_ModelThrusters, model_h, "thrusters", "The thrusters of a model"); @@ -777,15 +732,6 @@ ADE_INDEXER(l_ModelThrusters, "number Index", "Array of all thrusterbanks on thi return ade_set_args(L, "o", l_Thrusterbank.Set(thrusterbank_h(pm->id, idx))); } -ADE_FUNC(isValid, l_ModelThrusters, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - model_h *trh; - if(!ade_get_args(L, "o", l_ModelThrusters.GetPtr(&trh))) - return ADE_RETURN_FALSE; - - return ade_set_args(L, "b", trh->isValid()); -} - //**********HANDLE: thrusterbank ADE_OBJ(l_Thrusterbank, thrusterbank_h, "thrusterbank", "A model thrusterbank"); @@ -849,18 +795,6 @@ ADE_INDEXER(l_Thrusterbank, "number Index", "Array of glowpoint", "glowpoint", " return ade_set_args(L, "o", l_Glowpoint.Set(glowpoint_h(tbh->modelh.GetID(), -1, tbh->thrusterbank_index, idx))); } -ADE_FUNC(isValid, l_Thrusterbank, nullptr, "Detects if this handle is valid", "boolean", "true if this handle is valid, false otherwise") -{ - thrusterbank_h* trh; - if(!ade_get_args(L, "o", l_Thrusterbank.GetPtr(&trh))) - return ADE_RETURN_FALSE; - - if (!trh->isValid()) - return ADE_RETURN_FALSE; - - return ade_set_args(L, "b", trh->isValid()); -} - //**********HANDLE: glow point banks ADE_OBJ(l_ModelGlowpointbanks, model_h, "glowpointbanks", "Array of model glow point banks"); @@ -899,15 +833,6 @@ ADE_INDEXER(l_ModelGlowpointbanks, "glowpointbank", "Gets a glow point bank hand return ade_set_args(L, "o", l_Glowpointbank.Set(glowpointbank_h(pm->id, index))); } -ADE_FUNC(isValid, l_ModelGlowpointbanks, nullptr, "Detects whether handle is valid or not", "boolean", "true if valid false otherwise") -{ - model_h *modelh; - if(!ade_get_args(L, "o", l_ModelGlowpointbanks.GetPtr(&modelh))) - return ADE_RETURN_FALSE; - - return ade_set_args(L, "b", modelh->isValid()); -} - //**********HANDLE: glow point bank ADE_OBJ(l_Glowpointbank, glowpointbank_h, "glowpointbank", "A model glow point bank"); @@ -974,15 +899,6 @@ ADE_INDEXER(l_Glowpointbank, "glowpoint", "Gets a glow point handle", "glowpoint // NOTE: Any fields or functions of glowpointbank will need to take glowpoint_bank_overrides into account // ********** -ADE_FUNC(isValid, l_Glowpointbank, nullptr, "Detects whether handle is valid or not", "boolean", "true if valid false otherwise") -{ - glowpointbank_h* gpbh = nullptr; - if (!ade_get_args(L, "o", l_Glowpointbank.GetPtr(&gpbh))) - return ADE_RETURN_FALSE; - - return ade_set_args(L, "b", gpbh->isValid()); -} - //**********HANDLE: glowpoint ADE_OBJ(l_Glowpoint, glowpoint_h, "glowpoint", "A model glowpoint"); @@ -1083,16 +999,6 @@ ADE_VIRTVAR(Radius, l_Glowpoint, nullptr, "The radius of the glowpoint", "number return ade_set_args(L, "f", point->radius); } -ADE_FUNC(isValid, l_Glowpoint, NULL, "Returns whether this handle is valid or not", "boolean", "True if handle is valid, false otherwise") -{ - glowpoint_h glh; - - if(!ade_get_args(L, "o", l_Glowpoint.Get(&glh))) - return ADE_RETURN_FALSE; - - return ade_set_args(L, "b", glh.isValid()); -} - //**********HANDLE: dockingbays ADE_OBJ(l_ModelDockingbays, model_h, "dockingbays", "The docking bays of a model"); @@ -1312,22 +1218,5 @@ ADE_FUNC(computeDocker, l_Dockingbay, "dockingbay", return ade_set_args(L, "oo", l_Vector.Set(final_pos),l_Matrix.Set(matrix_h(&final_orient))); } -ADE_FUNC(isValid, l_Dockingbay, nullptr, "Detects whether is valid or not", "boolean", "true if valid, false otherwise") -{ - dockingbay_h* dbh = nullptr; - - if (!ade_get_args(L, "o", l_Dockingbay.GetPtr(&dbh))) - { - return ADE_RETURN_FALSE; - } - - if (dbh == nullptr) - { - return ADE_RETURN_FALSE; - } - - return ade_set_args(L, "b", dbh->isValid()); -} - } } diff --git a/code/scripting/api/objs/model_path.cpp b/code/scripting/api/objs/model_path.cpp index c1effaa51b..984b080aff 100644 --- a/code/scripting/api/objs/model_path.cpp +++ b/code/scripting/api/objs/model_path.cpp @@ -25,16 +25,6 @@ struct model_path_point_h { ADE_OBJ(l_ModelPathPoint, model_path_point_h, "modelpathpoint", "Point in a model path"); -ADE_FUNC(isValid, l_ModelPathPoint, nullptr, "Determines if the handle is valid", "boolean", - "True if valid, false otherwise") -{ - model_path_point_h* p = nullptr; - if (!ade_get_args(L, "o", l_ModelPathPoint.GetPtr(&p))) - return ADE_RETURN_FALSE; - - return ade_set_args(L, "b", p->isValid()); -} - ADE_VIRTVAR(Position, l_ModelPathPoint, "vector", "The current, global position of this path point.", "vector", "The current position of the point.") { @@ -102,19 +92,6 @@ ADE_FUNC(__len, l_ModelPath, nullptr, "Gets the number of points in this path", return ade_set_args(L, "i", static_cast(p->verts.size())); } -ADE_FUNC(isValid, l_ModelPath, nullptr, "Determines if the handle is valid", "boolean", - "True if valid, false otherwise") -{ - model_path_h* p = nullptr; - if (!ade_get_args(L, "o", l_ModelPath.GetPtr(&p))) - return ADE_RETURN_FALSE; - - if (p == nullptr) - return ADE_RETURN_FALSE; - - return ade_set_args(L, "b", p->isValid()); -} - ADE_INDEXER(l_ModelPath, "number", "Returns the point in the path with the specified index", "modelpathpoint", "The point or invalid handle if index is invalid") { diff --git a/code/scripting/api/objs/modelinstance.cpp b/code/scripting/api/objs/modelinstance.cpp index 48a7fa49e5..b93f70290a 100644 --- a/code/scripting/api/objs/modelinstance.cpp +++ b/code/scripting/api/objs/modelinstance.cpp @@ -97,15 +97,6 @@ ADE_INDEXER(l_ModelInstanceTextures, "number/string IndexOrTextureFilename", "Ar return ade_set_args(L, "o", l_Texture.Set(texture_h(pm->maps[final_index / TM_NUM_TYPES].textures[final_index % TM_NUM_TYPES].GetTexture()))); } -ADE_FUNC(isValid, l_ModelInstanceTextures, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - modelinstance_h *mih; - if(!ade_get_args(L, "o", l_ModelInstanceTextures.GetPtr(&mih))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", mih->isValid()); -} - ADE_OBJ(l_ModelInstance, modelinstance_h, "model_instance", "Model instance handle"); @@ -278,15 +269,6 @@ ADE_VIRTVAR(SubmodelInstances, l_ModelInstance, nullptr, "Submodel instances", " return ade_set_args(L, "o", l_ModelSubmodelInstances.Set(modelsubmodelinstances_h(pmi))); } -ADE_FUNC(isValid, l_ModelInstance, nullptr, "True if valid, false or nil if not", "boolean", "Detects whether handle is valid") -{ - modelinstance_h *mih; - if (!ade_get_args(L, "o", l_ModelInstance.GetPtr(&mih))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", mih->isValid()); -} - ADE_FUNC(getModelInstance, l_SubmodelInstance, nullptr, "Gets the model instance of this submodel", "model_instance", "A model instancve") { submodelinstance_h* smih; @@ -473,15 +455,6 @@ ADE_FUNC(findLocalPointAndOrientation, l_SubmodelInstance, "vector, orientation, return ade_set_args(L, "oo", l_Vector.Set(local_pnt), l_Matrix.Set(matrix_h(&local_orient))); } -ADE_FUNC(isValid, l_SubmodelInstance, nullptr, "True if valid, false or nil if not", "boolean", "Detects whether handle is valid") -{ - submodelinstance_h *smih; - if (!ade_get_args(L, "o", l_SubmodelInstance.GetPtr(&smih))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", smih->isValid()); -} - ADE_OBJ(l_ModelSubmodelInstances, modelsubmodelinstances_h, "submodel_instances", "Array of submodel instances"); @@ -556,14 +529,5 @@ ADE_INDEXER(l_ModelSubmodelInstances, "submodel_instance", "number|string IndexO return ade_set_args(L, "o", l_SubmodelInstance.Set(submodelinstance_h(pmi, index))); } -ADE_FUNC(isValid, l_ModelSubmodelInstances, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if invalid, nil if a syntax/type error occurs") -{ - modelsubmodelinstances_h *msih; - if (!ade_get_args(L, "o", l_ModelSubmodelInstances.GetPtr(&msih))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", msih->isValid()); -} - } } diff --git a/code/scripting/api/objs/movie_player.cpp b/code/scripting/api/objs/movie_player.cpp index 0f626b164a..525768693b 100644 --- a/code/scripting/api/objs/movie_player.cpp +++ b/code/scripting/api/objs/movie_player.cpp @@ -171,23 +171,5 @@ ADE_FUNC(stop, l_MoviePlayer, nullptr, return ADE_RETURN_NIL; } -ADE_FUNC(isValid, l_MoviePlayer, nullptr, "Determines if this handle is valid", "boolean", - "true if valid, false otherwise") -{ - movie_player_h* ph = nullptr; - if (!ade_get_args(L, "o", l_MoviePlayer.GetPtr(&ph))) - return ADE_RETURN_FALSE; - - if (ph == nullptr) { - return ADE_RETURN_FALSE; - } - - if (!ph->isValid()) { - return ADE_RETURN_FALSE; - } - - return ADE_RETURN_TRUE; -} - } // namespace api } // namespace scripting diff --git a/code/scripting/api/objs/multi_objects.cpp b/code/scripting/api/objs/multi_objects.cpp index 5ab8c27cb4..e7392a73a2 100644 --- a/code/scripting/api/objs/multi_objects.cpp +++ b/code/scripting/api/objs/multi_objects.cpp @@ -196,20 +196,6 @@ bool join_ship_choices_h::isValid() const //**********HANDLE: channel section ADE_OBJ(l_Channel, channel_h, "pxo_channel", "Channel Section handle"); -ADE_FUNC(isValid, - l_Channel, - nullptr, - "Detects whether handle is valid", - "boolean", - "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - channel_h current; - if (!ade_get_args(L, "o", l_Channel.Get(¤t))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", current.isValid()); -} - ADE_VIRTVAR(Name, l_Channel, nullptr, "The name of the channel", "string", "The name") { channel_h current; @@ -301,20 +287,6 @@ ADE_FUNC(joinChannel, l_Channel, nullptr, "Joins the specified channel", nullptr //**********HANDLE: net player section ADE_OBJ(l_NetPlayer, net_player_h, "net_player", "Net Player handle"); -ADE_FUNC(isValid, - l_NetPlayer, - nullptr, - "Detects whether handle is valid", - "boolean", - "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - net_player_h current; - if (!ade_get_args(L, "o", l_NetPlayer.Get(¤t))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", current.isValid()); -} - ADE_VIRTVAR(Name, l_NetPlayer, nullptr, "The player's callsign", "string", "The player callsign") { net_player_h current; @@ -507,20 +479,6 @@ ADE_FUNC(kickPlayer, l_NetPlayer, nullptr, "Kicks the player from the game", nul //**********HANDLE: mission section ADE_OBJ(l_NetMission, net_mission_h, "net_mission", "Net Mission handle"); -ADE_FUNC(isValid, - l_NetMission, - nullptr, - "Detects whether handle is valid", - "boolean", - "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - net_mission_h current; - if (!ade_get_args(L, "o", l_NetMission.Get(¤t))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", current.isValid()); -} - ADE_VIRTVAR(Name, l_NetMission, nullptr, "The name of the mission", "string", "The name") { net_mission_h current; @@ -683,20 +641,6 @@ ADE_VIRTVAR(Builtin, //**********HANDLE: campaign section ADE_OBJ(l_NetCampaign, net_campaign_h, "net_campaign", "Net Campaign handle"); -ADE_FUNC(isValid, - l_NetCampaign, - nullptr, - "Detects whether handle is valid", - "boolean", - "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - net_campaign_h current; - if (!ade_get_args(L, "o", l_NetCampaign.Get(¤t))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", current.isValid()); -} - ADE_VIRTVAR(Name, l_NetCampaign, nullptr, "The name of the mission", "string", "The name") { net_campaign_h current; @@ -859,20 +803,6 @@ ADE_VIRTVAR(Builtin, //**********HANDLE: netgame section ADE_OBJ(l_NetGame, net_game_h, "netgame", "Netgame handle"); -ADE_FUNC(isValid, - l_NetGame, - nullptr, - "Detects whether handle is valid", - "boolean", - "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - net_game_h current; - if (!ade_get_args(L, "o", l_NetGame.Get(¤t))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", current.isValid()); -} - ADE_VIRTVAR(Name, l_NetGame, nullptr, @@ -1294,20 +1224,6 @@ ADE_FUNC(setMission, //**********HANDLE: channel section ADE_OBJ(l_Active_Game, active_game_h, "active_game", "Active Game handle"); -ADE_FUNC(isValid, - l_Active_Game, - nullptr, - "Detects whether handle is valid", - "boolean", - "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - active_game_h current; - if (!ade_get_args(L, "o", l_Active_Game.Get(¤t))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", current.isValid()); -} - ADE_VIRTVAR(Status, l_Active_Game, nullptr, "The status of the game", "string", "The status") { active_game_h current; @@ -1508,20 +1424,6 @@ ADE_FUNC(setSelected, l_Active_Game, nullptr, "Sets the specified game as the se //**********HANDLE: channel section ADE_OBJ(l_Dogfight_Scores, dogfight_scores_h, "dogfight_scores", "Dogfight scores handle"); -ADE_FUNC(isValid, - l_Dogfight_Scores, - nullptr, - "Detects whether handle is valid", - "boolean", - "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - dogfight_scores_h current; - if (!ade_get_args(L, "o", l_Dogfight_Scores.Get(¤t))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", current.isValid()); -} - ADE_VIRTVAR(Callsign, l_Dogfight_Scores, nullptr, @@ -1558,20 +1460,6 @@ ADE_FUNC(getKillsOnPlayer, //**********HANDLE: join choice section ADE_OBJ(l_Join_Ship_Choice, join_ship_choices_h, "net_join_choice", "Join Choice handle"); -ADE_FUNC(isValid, - l_Join_Ship_Choice, - nullptr, - "Detects whether handle is valid", - "boolean", - "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - join_ship_choices_h current; - if (!ade_get_args(L, "o", l_Join_Ship_Choice.Get(¤t))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", current.isValid()); -} - ADE_VIRTVAR(Name, l_Join_Ship_Choice, nullptr, "Gets the name of the ship", diff --git a/code/scripting/api/objs/object.cpp b/code/scripting/api/objs/object.cpp index 6e2634bf37..b7ee58c149 100644 --- a/code/scripting/api/objs/object.cpp +++ b/code/scripting/api/objs/object.cpp @@ -353,15 +353,6 @@ ADE_FUNC(getSignature, l_Object, NULL, "Gets the object's unique signature", "nu return ade_set_args(L, "i", oh->sig); } -ADE_FUNC(isValid, l_Object, NULL, "Detects whether handle is valid", "boolean", "true if handle is valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - object_h *oh; - if(!ade_get_args(L, "o", l_Object.GetPtr(&oh))) - return ADE_RETURN_FALSE; - - return ade_set_args(L, "b", oh->isValid()); -} - ADE_FUNC(isExpiring, l_Object, nullptr, "Checks whether the object has the should-be-dead flag set, which will cause it to be deleted within one frame", "boolean", "true or false according to the flag, or nil if a syntax/type error occurs") { object_h* oh; diff --git a/code/scripting/api/objs/order.cpp b/code/scripting/api/objs/order.cpp index 9176413b0f..50be8522d7 100644 --- a/code/scripting/api/objs/order.cpp +++ b/code/scripting/api/objs/order.cpp @@ -559,15 +559,6 @@ ADE_VIRTVAR(PurgeWhenNewGoalAdded, l_Order, "boolean", "Whether this goal should return goal_flag_helper(L, AI::Goal_Flags::Purge_when_new_goal_added); } -ADE_FUNC(isValid, l_Order, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - order_h *ohp = NULL; - if(!ade_get_args(L, "o", l_Order.GetPtr(&ohp))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", ohp->isValid()); -} - //**********HANDLE: shiporders ADE_OBJ(l_ShipOrders, object_h, "shiporders", "Ship orders"); @@ -604,15 +595,6 @@ ADE_INDEXER(l_ShipOrders, "number Index", "Array of ship orders", "order", "Orde return ade_set_args(L, "o", l_Order.Set(order_h())); } -ADE_FUNC(isValid, l_ShipOrders, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - object_h *oh; - if(!ade_get_args(L, "o", l_ShipOrders.GetPtr(&oh))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", oh->isValid()); -} - } } diff --git a/code/scripting/api/objs/parse_object.cpp b/code/scripting/api/objs/parse_object.cpp index ffb8856924..e5d462bdb0 100644 --- a/code/scripting/api/objs/parse_object.cpp +++ b/code/scripting/api/objs/parse_object.cpp @@ -90,15 +90,6 @@ ADE_VIRTVAR( return ade_set_args(L, "s", poh->getObject()->get_display_name()); } -ADE_FUNC(isValid, l_ParseObject, nullptr, "Detect whether the parsed ship handle is valid", "boolean", "true if valid false otherwise") -{ - parse_object_h* poh = nullptr; - if (!ade_get_args(L, "o", l_ParseObject.GetPtr(&poh))) - return ADE_RETURN_FALSE; - - return ade_set_args(L, "b", poh->isValid()); -} - ADE_FUNC(getBreedName, l_ParseObject, nullptr, "Gets the FreeSpace type name", "string", "'Parse Object', or empty string if handle is invalid") { parse_object_h* poh = nullptr; diff --git a/code/scripting/api/objs/particle.cpp b/code/scripting/api/objs/particle.cpp index 46fea62a2e..1f6d7d8bd0 100644 --- a/code/scripting/api/objs/particle.cpp +++ b/code/scripting/api/objs/particle.cpp @@ -214,18 +214,6 @@ ADE_VIRTVAR(AttachedObject, l_Particle, "object", "The object this particle is a return ade_set_object_with_breed(L, -1); } -ADE_FUNC(isValid, l_Particle, NULL, "Detects whether this handle is valid", "boolean", "true if valid false if not") -{ - particle_h *ph = NULL; - if (!ade_get_args(L, "o", l_Particle.GetPtr(&ph))) - return ADE_RETURN_FALSE; - - if (ph == NULL) - return ADE_RETURN_FALSE; - - return ade_set_args(L, "b", ph->isValid()); -} - ADE_FUNC_DEPRECATED(setColor, l_Particle, "number r, number g, number b", "Sets the color for a particle. If the particle does not support color, the function does nothing. (Currently only debug particles support color.)", nullptr, nullptr, gameversion::version(25,0,0), "Debug particles are deprecated as of FSO 25.0.0! Use particles with a solid-color bitmap instead!") { LuaError(L, "Debug particles are deprecated as of FSO 25.0.0!"); diff --git a/code/scripting/api/objs/physics_info.cpp b/code/scripting/api/objs/physics_info.cpp index 32f764531d..44b9106c3b 100644 --- a/code/scripting/api/objs/physics_info.cpp +++ b/code/scripting/api/objs/physics_info.cpp @@ -413,15 +413,6 @@ ADE_VIRTVAR(GravityConst, l_Physics, "number", "Multiplier for the effect of gra return ade_set_args(L, "f", pih->pi->gravity_const); } -ADE_FUNC(isValid, l_Physics, NULL, "True if valid, false or nil if not", "boolean", "Detects whether handle is valid") -{ - physics_info_h *pih; - if(!ade_get_args(L, "o", l_Physics.GetPtr(&pih))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", pih->isValid()); -} - ADE_FUNC(getSpeed, l_Physics, NULL, "Gets total speed as of last frame", "number", "Total speed, or 0 if handle is invalid") { physics_info_h *pih; diff --git a/code/scripting/api/objs/player.cpp b/code/scripting/api/objs/player.cpp index 57744d1293..249b82d794 100644 --- a/code/scripting/api/objs/player.cpp +++ b/code/scripting/api/objs/player.cpp @@ -205,18 +205,6 @@ ADE_VIRTVAR(ShowSkipPopup, return ade_set_args(L, "b", plr->get()->show_skip_popup != 0); } -ADE_FUNC(isValid, l_Player, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - player_h* plr; - if (!ade_get_args(L, "o", l_Player.GetPtr(&plr))) - return ADE_RETURN_NIL; - - if (!plr->isValid()) - return ADE_RETURN_FALSE; - - return ADE_RETURN_TRUE; -} - ADE_FUNC(getName, l_Player, NULL, "Gets current player name", "string", "Player name, or empty string if handle is invalid") { player_h* plr; diff --git a/code/scripting/api/objs/propclass.cpp b/code/scripting/api/objs/propclass.cpp index 00532d6c33..cc0c97982f 100644 --- a/code/scripting/api/objs/propclass.cpp +++ b/code/scripting/api/objs/propclass.cpp @@ -7,6 +7,7 @@ namespace scripting::api { //**********HANDLE: Propclass ADE_OBJ(l_Propclass, int, "propclass", "Prop class handle"); +ADE_OBJ_VALIDATOR_RANGE(l_Propclass, prop_info_size()); ADE_FUNC(__tostring, l_Propclass, @@ -197,23 +198,6 @@ ADE_FUNC(hasCustomStrings, return ade_set_args(L, "b", result); } -ADE_FUNC(isValid, - l_Propclass, - nullptr, - "Detects whether handle is valid", - "boolean", - "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - int idx; - if (!ade_get_args(L, "o", l_Propclass.Get(&idx))) - return ADE_RETURN_NIL; - - if (idx < 0 || idx >= prop_info_size()) - return ADE_RETURN_FALSE; - - return ADE_RETURN_TRUE; -} - ADE_FUNC(renderTechModel, l_Propclass, "number X1, number Y1, number X2, number Y2, [number RotationPercent =0, number PitchPercent =0, number " diff --git a/code/scripting/api/objs/rank.cpp b/code/scripting/api/objs/rank.cpp index 5186a40c44..68f6689002 100644 --- a/code/scripting/api/objs/rank.cpp +++ b/code/scripting/api/objs/rank.cpp @@ -24,15 +24,6 @@ bool rank_h::isValid() const //**********HANDLE: rank ADE_OBJ(l_Rank, rank_h, "rank", "Rank handle"); -ADE_FUNC(isValid, l_Rank, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - rank_h current; - if (!ade_get_args(L, "o", l_Rank.Get(¤t))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", current.isValid()); -} - ADE_VIRTVAR(Name, l_Rank, nullptr, "The name of the rank", "string", "The name") { rank_h current; diff --git a/code/scripting/api/objs/sexpvar.cpp b/code/scripting/api/objs/sexpvar.cpp index 0a8ea4718d..530102b3c9 100644 --- a/code/scripting/api/objs/sexpvar.cpp +++ b/code/scripting/api/objs/sexpvar.cpp @@ -156,18 +156,6 @@ ADE_FUNC(__tostring, l_SEXPVariable, NULL, "Returns SEXP name", "string", "SEXP return ade_set_args(L, "s", Sexp_variables[svh->idx].variable_name); } -ADE_FUNC(isValid, l_SEXPVariable, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - sexpvar_h *svh = NULL; - if(!ade_get_args(L, "o", l_SEXPVariable.GetPtr(&svh))) - return ADE_RETURN_NIL; - - if(!svh->isValid()) - return ADE_RETURN_FALSE; - - return ADE_RETURN_TRUE; -} - ADE_FUNC(delete, l_SEXPVariable, NULL, "Deletes a SEXP Variable", "boolean", "True if successful, false if the handle is invalid") { sexpvar_h *svh = NULL; diff --git a/code/scripting/api/objs/shields.cpp b/code/scripting/api/objs/shields.cpp index 6485ac99e9..d8d9dd3e83 100644 --- a/code/scripting/api/objs/shields.cpp +++ b/code/scripting/api/objs/shields.cpp @@ -134,14 +134,5 @@ ADE_VIRTVAR(CombinedMax, l_Shields, "number", "Maximum shield hitpoints (for all return ade_set_args(L, "f", shield_get_max_strength(objh->objp())); } -ADE_FUNC(isValid, l_Shields, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - object_h *oh; - if(!ade_get_args(L, "o", l_Shields.GetPtr(&oh))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", oh->isValid()); -} - } } diff --git a/code/scripting/api/objs/ship_bank.cpp b/code/scripting/api/objs/ship_bank.cpp index d0b1b77599..ff3c8ab3d6 100644 --- a/code/scripting/api/objs/ship_bank.cpp +++ b/code/scripting/api/objs/ship_bank.cpp @@ -139,15 +139,6 @@ ADE_VIRTVAR(DualFire, l_WeaponBankType, "boolean", "Whether bank is in dual fire return ade_set_error(L, "b", false); } -ADE_FUNC(isValid, l_WeaponBankType, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - ship_banktype_h *sb; - if(!ade_get_args(L, "o", l_WeaponBankType.GetPtr(&sb))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", sb->isValid()); -} - ADE_FUNC(__len, l_WeaponBankType, NULL, "Number of weapons in the mounted bank", "number", "Number of bank weapons, or 0 if handle is invalid") { ship_banktype_h *sb=NULL; @@ -476,15 +467,6 @@ ADE_VIRTVAR(BurstSeed, l_WeaponBank, "number", "A random seed associated to the return ade_set_error(L, "i", -1); } -ADE_FUNC(isValid, l_WeaponBank, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - ship_bank_h *bh; - if(!ade_get_args(L, "o", l_WeaponBank.GetPtr(&bh))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", bh->isValid()); -} - } } diff --git a/code/scripting/api/objs/ship_registry_entry.cpp b/code/scripting/api/objs/ship_registry_entry.cpp index 1b31821712..2b4471da80 100644 --- a/code/scripting/api/objs/ship_registry_entry.cpp +++ b/code/scripting/api/objs/ship_registry_entry.cpp @@ -13,6 +13,7 @@ namespace api { //**********HANDLE: ShipRegistryEntry ADE_OBJ(l_ShipRegistryEntry, int, "ship_registry_entry", "Ship entry handle"); +ADE_OBJ_VALIDATOR(l_ShipRegistryEntry, idx, Ship_registry.in_bounds(idx)); ADE_VIRTVAR(Name, l_ShipRegistryEntry, nullptr, "Name of ship", "string", "Ship name, or empty string if handle is invalid") { @@ -29,18 +30,6 @@ ADE_VIRTVAR(Name, l_ShipRegistryEntry, nullptr, "Name of ship", "string", "Ship return ade_set_args(L, "s", Ship_registry[idx].name); } -ADE_FUNC(isValid, l_ShipRegistryEntry, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if invalid, nil if a syntax/type error occurs") -{ - int idx; - if (!ade_get_args(L, "o", l_ShipRegistryEntry.Get(&idx))) - return ADE_RETURN_NIL; - - if (idx < 0 || (size_t)idx >= Ship_registry.size()) - return ADE_RETURN_FALSE; - - return ADE_RETURN_TRUE; -} - ADE_VIRTVAR(Status, l_ShipRegistryEntry, nullptr, "Status of ship", "enumeration", "A SHIP_STATUS_* enumeration, or nil if handle is invalid") { int idx; diff --git a/code/scripting/api/objs/shipclass.cpp b/code/scripting/api/objs/shipclass.cpp index 51dddcba68..bee25cf545 100644 --- a/code/scripting/api/objs/shipclass.cpp +++ b/code/scripting/api/objs/shipclass.cpp @@ -28,6 +28,7 @@ namespace api { //**********HANDLE: default primary ADE_OBJ(l_Default_Primary, int, "default_primary", "weapon index"); +ADE_OBJ_VALIDATOR_RANGE(l_Default_Primary, ship_info_size()); ADE_INDEXER(l_Default_Primary, "number idx", @@ -70,6 +71,7 @@ ADE_FUNC(__len, //**********HANDLE: default secondary ADE_OBJ(l_Default_Secondary, int, "default_secondary", "weapon index"); +ADE_OBJ_VALIDATOR_RANGE(l_Default_Secondary, ship_info_size()); ADE_INDEXER(l_Default_Secondary, "number idx", @@ -112,6 +114,7 @@ ADE_FUNC(__len, //**********HANDLE: Shipclass ADE_OBJ(l_Shipclass, int, "shipclass", "Ship class handle"); +ADE_OBJ_VALIDATOR_RANGE(l_Shipclass, ship_info_size()); ADE_FUNC(__tostring, l_Shipclass, NULL, "Ship class name", "string", "Ship class name, or an empty string if handle is invalid") { @@ -1117,18 +1120,6 @@ ADE_FUNC(hasCustomStrings, return ade_set_args(L, "b", result); } -ADE_FUNC(isValid, l_Shipclass, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - int idx; - if(!ade_get_args(L, "o", l_Shipclass.Get(&idx))) - return ADE_RETURN_NIL; - - if(idx < 0 || idx >= ship_info_size()) - return ADE_RETURN_FALSE; - - return ADE_RETURN_TRUE; -} - ADE_FUNC(isInTechroom, l_Shipclass, NULL, "Gets whether or not the ship class is available in the techroom", "boolean", "Whether ship has been revealed in the techroom, false if handle is invalid") { int idx; diff --git a/code/scripting/api/objs/shiptype.cpp b/code/scripting/api/objs/shiptype.cpp index 4c12f3ca26..4edb142c08 100644 --- a/code/scripting/api/objs/shiptype.cpp +++ b/code/scripting/api/objs/shiptype.cpp @@ -11,6 +11,7 @@ namespace api { //**********HANDLE: Shiptype ADE_OBJ(l_Shiptype, int, "shiptype", "Ship type handle"); +ADE_OBJ_VALIDATOR(l_Shiptype, idx, Ship_types.in_bounds(idx)); ADE_VIRTVAR(Name, l_Shiptype, "string", "Ship type name", "string", "Ship type name, or empty string if handle is invalid") { @@ -34,17 +35,5 @@ ADE_VIRTVAR(Name, l_Shiptype, "string", "Ship type name", "string", "Ship type n return ade_set_args(L, "s", Ship_types[idx].name); } -ADE_FUNC(isValid, l_Shiptype, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - int idx; - if(!ade_get_args(L, "o", l_Shiptype.Get(&idx))) - return ADE_RETURN_NIL; - - if(idx < 0 || idx >= (int)Ship_types.size()) - return ADE_RETURN_FALSE; - - return ADE_RETURN_TRUE; -} - } } diff --git a/code/scripting/api/objs/shipwepselect.cpp b/code/scripting/api/objs/shipwepselect.cpp index 6d3d66684b..04a5c52467 100644 --- a/code/scripting/api/objs/shipwepselect.cpp +++ b/code/scripting/api/objs/shipwepselect.cpp @@ -379,6 +379,7 @@ ADE_FUNC(__len, l_Loadout_Weapon, nullptr, "The number of weapon banks in the sl //**********HANDLE: loadout ship ADE_OBJ_NO_MULTI(l_Loadout_Ship, int, "loadout_ship", "Loadout handle"); +ADE_OBJ_VALIDATOR_RANGE(l_Loadout_Ship, MAX_WSS_SLOTS); ADE_VIRTVAR(ShipClassIndex, l_Loadout_Ship, diff --git a/code/scripting/api/objs/sound.cpp b/code/scripting/api/objs/sound.cpp index fd13f9115a..4936c76f77 100644 --- a/code/scripting/api/objs/sound.cpp +++ b/code/scripting/api/objs/sound.cpp @@ -111,15 +111,6 @@ ADE_FUNC(get3DValues, } } -ADE_FUNC(isValid, l_SoundEntry, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - sound_entry_h *seh; - if(!ade_get_args(L, "o", l_SoundEntry.GetPtr(&seh))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", seh->isValid()); -} - ADE_FUNC(tryLoad, l_SoundEntry, nullptr, "Detects whether handle references a sound that can be loaded", "boolean", "true if a load succeeded, false if not, nil if a syntax/type error occurs") { sound_entry_h *seh; @@ -407,6 +398,11 @@ ADE_FUNC(updatePosition, l_Sound3D, //**********HANDLE: Soundfile soundfile_h::soundfile_h(sound_load_id id) : idx(id) {} +bool soundfile_h::isValid() const +{ + return idx.isValid(); +} + ADE_OBJ(l_Soundfile, soundfile_h, "soundfile", "Handle to a sound file"); ADE_VIRTVAR(Duration, l_Soundfile, "number", "The duration of the sound file, in seconds", "number", "The duration or -1 on error") @@ -491,20 +487,6 @@ ADE_FUNC(unload, l_Soundfile, nullptr, return ade_set_args(L, "b", result != 0); } -ADE_FUNC(isValid, l_Soundfile, NULL, "Checks if the soundfile handle is valid", "boolean", "true if valid, false otherwise") -{ - soundfile_h* handle = nullptr; - - if (!ade_get_args(L, "o", l_Soundfile.GetPtr(&handle))) - return ADE_RETURN_FALSE; - - if (handle == nullptr) { - return ADE_RETURN_FALSE; - } - - return ade_set_args(L, "b", handle->idx.isValid()); -} - } } diff --git a/code/scripting/api/objs/sound.h b/code/scripting/api/objs/sound.h index 1befdc5866..57c96b6402 100644 --- a/code/scripting/api/objs/sound.h +++ b/code/scripting/api/objs/sound.h @@ -53,6 +53,8 @@ struct soundfile_h { sound_load_id idx; explicit soundfile_h(sound_load_id id = sound_load_id::invalid()); + + bool isValid() const; }; DECLARE_ADE_OBJ(l_Soundfile, soundfile_h); diff --git a/code/scripting/api/objs/species.cpp b/code/scripting/api/objs/species.cpp index 24f9814244..18587aec76 100644 --- a/code/scripting/api/objs/species.cpp +++ b/code/scripting/api/objs/species.cpp @@ -11,6 +11,7 @@ namespace api { //**********HANDLE: Species ADE_OBJ(l_Species, int, "species", "Species handle"); +ADE_OBJ_VALIDATOR(l_Species, idx, Species_info.in_bounds(idx)); ADE_VIRTVAR(Name, l_Species, "string", "Species name", "string", "Species name, or empty string if handle is invalid") { @@ -34,18 +35,6 @@ ADE_VIRTVAR(Name, l_Species, "string", "Species name", "string", "Species name, return ade_set_args(L, "s", Species_info[idx].species_name); } -ADE_FUNC(isValid, l_Species, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - int idx; - if(!ade_get_args(L, "o", l_Species.Get(&idx))) - return ADE_RETURN_NIL; - - if(idx < 0 || idx >= (int)Species_info.size()) - return ADE_RETURN_FALSE; - - return ADE_RETURN_TRUE; -} - } } diff --git a/code/scripting/api/objs/streaminganim.cpp b/code/scripting/api/objs/streaminganim.cpp index 2e8365f290..c87fa1e5e3 100644 --- a/code/scripting/api/objs/streaminganim.cpp +++ b/code/scripting/api/objs/streaminganim.cpp @@ -209,15 +209,6 @@ ADE_FUNC(getWidth, l_streaminganim, nullptr, "Get the width of the animation in return ade_set_args(L, "i", sah->ga.width); } -ADE_FUNC(isValid, l_streaminganim, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - streaminganim_h* sah; - if(!ade_get_args(L, "o", l_streaminganim.GetPtr(&sah))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", sah->isValid()); -} - ADE_FUNC(preload, l_streaminganim, NULL, "Load all apng animations into memory, enabling apng frame cache if not already enabled", "boolean", "true if preload was successful, nil if a syntax/type error occurs") { streaminganim_h* sah; diff --git a/code/scripting/api/objs/subsystem.cpp b/code/scripting/api/objs/subsystem.cpp index 8ca424a1bf..0383042f27 100644 --- a/code/scripting/api/objs/subsystem.cpp +++ b/code/scripting/api/objs/subsystem.cpp @@ -1099,15 +1099,6 @@ ADE_FUNC(isInViewFrom, l_Subsystem, "vector from", return ade_set_args(L, "b", in_sight); } -ADE_FUNC(isValid, l_Subsystem, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - ship_subsys_h *sso; - if(!ade_get_args(L, "o", l_Subsystem.GetPtr(&sso))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", sso->isValid()); -} - } } diff --git a/code/scripting/api/objs/support_rearm_pool.cpp b/code/scripting/api/objs/support_rearm_pool.cpp index 15d3e7b241..a4cad78b52 100644 --- a/code/scripting/api/objs/support_rearm_pool.cpp +++ b/code/scripting/api/objs/support_rearm_pool.cpp @@ -11,6 +11,7 @@ namespace scripting::api { //****HANDLE: support_rearm_pool_team ADE_OBJ(l_SupportRearmPoolTeam, int, "support_rearm_pool_team", "Support rearm pool team handle"); +ADE_OBJ_VALIDATOR(l_SupportRearmPoolTeam, idx, idx >= 0 && idx < Num_teams && idx < MAX_TVT_TEAMS); ADE_INDEXER(l_SupportRearmPoolTeam, "number/weaponclass IndexOrClass, number amount", diff --git a/code/scripting/api/objs/team.cpp b/code/scripting/api/objs/team.cpp index cf3dfa3318..3433d7cd19 100644 --- a/code/scripting/api/objs/team.cpp +++ b/code/scripting/api/objs/team.cpp @@ -11,6 +11,7 @@ namespace api { //**********HANDLE: Team ADE_OBJ(l_Team, int, "team", "Team handle"); +ADE_OBJ_VALIDATOR(l_Team, idx, Iff_info.in_bounds(idx)); ADE_FUNC(__eq, l_Team, "team, team", "Checks whether two teams are the same team", "boolean", "true if equal, false otherwise") { @@ -64,18 +65,6 @@ ADE_FUNC(getColor, } } -ADE_FUNC(isValid, l_Team, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - int idx; - if(!ade_get_args(L, "o", l_Team.Get(&idx))) - return ADE_RETURN_NIL; - - if(!SCP_vector_inbounds(Iff_info, idx)) - return ADE_RETURN_FALSE; - - return ADE_RETURN_TRUE; -} - ADE_FUNC(getBreedName, l_Team, nullptr, "Gets the FreeSpace type name", "string", "'Team', or empty string if handle is invalid") { int idx; diff --git a/code/scripting/api/objs/team_colors.cpp b/code/scripting/api/objs/team_colors.cpp index da21ac5022..a3eb6d8d71 100644 --- a/code/scripting/api/objs/team_colors.cpp +++ b/code/scripting/api/objs/team_colors.cpp @@ -9,6 +9,7 @@ namespace scripting::api { //**********HANDLE: TeamColor ADE_OBJ(l_TeamColor, int, "teamcolor", "Team color handle"); +ADE_OBJ_VALIDATOR(l_TeamColor, idx, Team_Names.in_bounds(idx) && Team_Colors.find(Team_Names[idx]) != Team_Colors.end()); ADE_FUNC(__tostring, l_TeamColor, nullptr, "Team color name", "string", "Team color name, or an empty string if handle is invalid") { @@ -112,21 +113,4 @@ ADE_VIRTVAR(StripeColor, l_TeamColor, nullptr, "Team color stripe color", "color return ade_set_args(L, "o", l_Color.Set(cur)); } -ADE_FUNC(isValid, l_TeamColor, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - int idx; - if (!ade_get_args(L, "o", l_TeamColor.Get(&idx))) - return ADE_RETURN_NIL; - - if (!SCP_vector_inbounds(Team_Names, idx)) - return ADE_RETURN_FALSE; - - const auto& it = Team_Colors.find(Team_Names[idx]); - if (it == Team_Colors.end()) { - return ADE_RETURN_FALSE; - } - - return ADE_RETURN_TRUE; -} - } diff --git a/code/scripting/api/objs/techroom.cpp b/code/scripting/api/objs/techroom.cpp index bc74e54c19..696fd847d0 100644 --- a/code/scripting/api/objs/techroom.cpp +++ b/code/scripting/api/objs/techroom.cpp @@ -225,15 +225,5 @@ ADE_FUNC(hasCustomData, l_TechRoomCutscene, nullptr, "Detects whether the cutsce return ade_set_args(L, "b", result); } -ADE_FUNC(isValid, l_TechRoomCutscene, NULL, "Detects whether cutscene is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - cutscene_info_h current; - if (!ade_get_args(L, "o", l_TechRoomCutscene.Get(¤t))) { - return ADE_RETURN_NIL; - } - - return ade_set_args(L, "b", current.isValid()); -} - } // namespace api } // namespace scripting \ No newline at end of file diff --git a/code/scripting/api/objs/texture.cpp b/code/scripting/api/objs/texture.cpp index abbe982f91..43c7228a41 100644 --- a/code/scripting/api/objs/texture.cpp +++ b/code/scripting/api/objs/texture.cpp @@ -101,15 +101,6 @@ ADE_INDEXER(l_Texture, "number", return ade_set_args(L, "o", l_Texture.Set(texture_h(frame, true, first))); } -ADE_FUNC(isValid, l_Texture, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - texture_h* th; - if (!ade_get_args(L, "o", l_Texture.GetPtr(&th))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", th->isValid()); -} - ADE_FUNC(unload, l_Texture, NULL, "Unloads a texture from memory", NULL, NULL) { texture_h* th; diff --git a/code/scripting/api/objs/volumetric.cpp b/code/scripting/api/objs/volumetric.cpp index 844bca4fb8..e12f9d253c 100644 --- a/code/scripting/api/objs/volumetric.cpp +++ b/code/scripting/api/objs/volumetric.cpp @@ -38,21 +38,6 @@ void volumetric_h::deserialize(lua_State* /*L*/, const scripting::ade_table_entr new(data_ptr) volumetric_h(index); } -ADE_FUNC(isValid, - l_Volumetric, - nullptr, - "Determines if this handle is valid", - "boolean", - "true if valid, false otherwise") -{ - volumetric_h* vh = nullptr; - if (!ade_get_args(L, "o", l_Volumetric.GetPtr(&vh))) { - return ADE_RETURN_FALSE; - } - - return ade_set_args(L, "b", vh != nullptr && vh->isValid()); -} - ADE_VIRTVAR(POF, l_Volumetric, nullptr, diff --git a/code/scripting/api/objs/waypoint.cpp b/code/scripting/api/objs/waypoint.cpp index f0b1ed51ed..9357c1dc09 100644 --- a/code/scripting/api/objs/waypoint.cpp +++ b/code/scripting/api/objs/waypoint.cpp @@ -136,14 +136,5 @@ ADE_VIRTVAR(Name, l_WaypointList, "string", "Name of WaypointList", "string", "W return ade_set_args( L, "s", wlh->getList()->get_name()); } -ADE_FUNC(isValid, l_WaypointList, NULL, "Return if this waypointlist handle is valid", "boolean", "true if valid false otherwise") -{ - waypointlist_h* wlh = NULL; - if ( !ade_get_args(L, "o", l_WaypointList.GetPtr(&wlh)) ) { - return ADE_RETURN_FALSE; - } - return ade_set_args(L, "b", wlh != NULL && wlh->isValid()); -} - } } diff --git a/code/scripting/api/objs/weaponclass.cpp b/code/scripting/api/objs/weaponclass.cpp index 6fb8dcdf3f..ecc89ff828 100644 --- a/code/scripting/api/objs/weaponclass.cpp +++ b/code/scripting/api/objs/weaponclass.cpp @@ -17,6 +17,7 @@ namespace api { //**********HANDLE: Weaponclass ADE_OBJ(l_Weaponclass, int, "weaponclass", "Weapon class handle"); +ADE_OBJ_VALIDATOR_RANGE(l_Weaponclass, weapon_info_size()); ADE_FUNC(__tostring, l_Weaponclass, NULL, "Weapon class name", "string", "Weapon class name, or an empty string if handle is invalid") { @@ -1083,18 +1084,6 @@ ADE_VIRTVAR(BeamWarmdown, l_Weaponclass, "number", "The time in seconds that a b return ade_set_args(L, "f", 0.0f); } -ADE_FUNC(isValid, l_Weaponclass, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - int idx; - if(!ade_get_args(L, "o", l_Weaponclass.Get(&idx))) - return ADE_RETURN_NIL; - - if(idx < 0 || idx >= weapon_info_size()) - return ADE_RETURN_FALSE; - - return ADE_RETURN_TRUE; -} - ADE_FUNC(renderTechModel, l_Weaponclass, "number X1, number Y1, number X2, number Y2, [number RotationPercent =0, number PitchPercent =0, number " diff --git a/code/scripting/api/objs/wing.cpp b/code/scripting/api/objs/wing.cpp index 6735467c07..4277b7f278 100644 --- a/code/scripting/api/objs/wing.cpp +++ b/code/scripting/api/objs/wing.cpp @@ -15,6 +15,7 @@ namespace api { //**********HANDLE: Wing ADE_OBJ(l_Wing, int, "wing", "Wing handle"); +ADE_OBJ_VALIDATOR_RANGE(l_Wing, Num_wings); ADE_INDEXER(l_Wing, "number Index", "Array of ships in the wing", "ship", "Ship handle, or invalid ship handle if index is invalid or wing handle is invalid") { @@ -86,18 +87,6 @@ ADE_VIRTVAR(DisplayName, l_Wing, "string", "Wing display name", "string", "The d return ade_set_args(L, "s", wingp->display_name.c_str()); } -ADE_FUNC(isValid, l_Wing, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - int idx; - if(!ade_get_args(L, "o", l_Wing.Get(&idx))) - return ADE_RETURN_NIL; - - if (idx < 0 || idx >= Num_wings) - return ADE_RETURN_FALSE; - - return ADE_RETURN_TRUE; -} - ADE_FUNC(getBreedName, l_Wing, nullptr, "Gets the FreeSpace type name", "string", "'Wing', or empty string if handle is invalid") { int idx; diff --git a/code/scripting/api/objs/wingformation.cpp b/code/scripting/api/objs/wingformation.cpp index f0c4e9a152..c369093730 100644 --- a/code/scripting/api/objs/wingformation.cpp +++ b/code/scripting/api/objs/wingformation.cpp @@ -13,6 +13,7 @@ namespace api { //**********HANDLE: WingFormation ADE_OBJ(l_WingFormation, int, "wingformation", "Wing formation handle"); +ADE_OBJ_VALIDATOR_RANGE(l_WingFormation, sz2i(Wing_formations.size()) + 1); // + 1 admits the default formation ADE_FUNC(__tostring, l_WingFormation, nullptr, "Wing formation name", "string", "Wing formation name, or an empty string if handle is invalid") { @@ -66,17 +67,5 @@ ADE_VIRTVAR(Name, l_WingFormation, "string", "Wing formation name", "string", "W return ade_set_args(L, "s", Wing_formations[formation_id].name); } -ADE_FUNC(isValid, l_WingFormation, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - int formation_id; - if (!ade_get_args(L, "o", l_WingFormation.Get(&formation_id))) - return ADE_RETURN_NIL; - - if (formation_id < 0 || formation_id >= (int)Wing_formations.size() + 1) - return ADE_RETURN_FALSE; - - return ADE_RETURN_TRUE; -} - } } diff --git a/code/scripting/lua/LuaConvert.h b/code/scripting/lua/LuaConvert.h index f7b6cc7efb..47981f004c 100644 --- a/code/scripting/lua/LuaConvert.h +++ b/code/scripting/lua/LuaConvert.h @@ -59,8 +59,8 @@ void pushValue(lua_State* luaState, const bool& value); void pushValue(lua_State* luaState, const lua_CFunction& value); template -void pushValue(lua_State* L, scripting::ade_odata_setter&& value) { - using namespace scripting; +void pushValue(lua_State* L, ::scripting::ade_odata_setter&& value) { + using namespace ::scripting; //WMC - char must be 1 byte, foo. static_assert(sizeof(char) == 1, "char must be 1 byte!"); @@ -105,7 +105,7 @@ bool popValue(lua_State* luaState, bool& target, int stackposition = -1, bool re bool popValue(lua_State* luaState, lua_CFunction& target, int stackposition = -1, bool remove = true); template -bool popValue(lua_State* L, scripting::ade_odata_getter&& od, int stackposition = -1, bool remove = true) +bool popValue(lua_State* L, ::scripting::ade_odata_getter&& od, int stackposition = -1, bool remove = true) { // Use the helper to reduce the amount of code here if (!internal::ade_odata_helper(L, stackposition, od.idx)) { @@ -124,7 +124,7 @@ bool popValue(lua_State* L, scripting::ade_odata_getter&& od, int stackpositi } template -bool popValue(lua_State* L, scripting::ade_odata_ptr_getter&& od, int stackposition = -1, bool remove = true) +bool popValue(lua_State* L, ::scripting::ade_odata_ptr_getter&& od, int stackposition = -1, bool remove = true) { // Use the helper to reduce the amount of code here if (!internal::ade_odata_helper(L, stackposition, od.idx)) { diff --git a/test/src/scripting/api/base.cpp b/test/src/scripting/api/base.cpp index c1b3808c0b..2165b5d8c4 100644 --- a/test/src/scripting/api/base.cpp +++ b/test/src/scripting/api/base.cpp @@ -1,4 +1,9 @@ +#include "mod_table/mod_table.h" +#include "scripting/ade_args.h" +#include "scripting/api/objs/shipclass.h" +#include "scripting/scripting_doc.h" + #include "scripting/ScriptingTestFixture.h" class ScriptingBaseTest : public test::scripting::ScriptingTestFixture { @@ -12,6 +17,81 @@ TEST_F(ScriptingBaseTest, print) { this->EvalTestScript(); } +TEST_F(ScriptingBaseTest, autoIsValid) { + this->EvalTestScript(); +} + +// Verifies that automatically generated isValid() functions and explicitly declared ones coexist correctly in the +// documentation: no class lists isValid more than once, and an explicit declaration replaces the generated one. +TEST_F(ScriptingBaseTest, isValidDocumentation) { + const auto doc = _state->OutputDocumentation([](const SCP_string& error) { + ADD_FAILURE() << "Documentation error: " << error; + }); + + SCP_unordered_map isValidByClass; + + for (const auto& element : doc.elements) { + if (element->type != ::scripting::ElementType::Class) + continue; + + int count = 0; + for (const auto& child : element->children) { + if (child->name == "isValid") { + count++; + isValidByClass[element->name] = child.get(); + } + } + ASSERT_LE(count, 1) << "Class '" << element->name << "' lists isValid more than once"; + } + + // Generated from the isValid() member of the stored type + ASSERT_NE(isValidByClass.end(), isValidByClass.find("object")); + ASSERT_NE(isValidByClass.end(), isValidByClass.find("gamestate")); + ASSERT_NE(isValidByClass.end(), isValidByClass.find("parse_subsystem")); + ASSERT_NE(isValidByClass.end(), isValidByClass.find("soundfile")); + ASSERT_EQ("Detects whether handle is valid", isValidByClass["object"]->description); + + // Generated from a validator registered with ADE_OBJ_VALIDATOR + ASSERT_NE(isValidByClass.end(), isValidByClass.find("shipclass")); + ASSERT_NE(isValidByClass.end(), isValidByClass.find("weaponclass")); + ASSERT_NE(isValidByClass.end(), isValidByClass.find("team")); + ASSERT_NE(isValidByClass.end(), isValidByClass.find("loadout_ship")); + ASSERT_NE(isValidByClass.end(), isValidByClass.find("HudGauge")); + ASSERT_EQ("Detects whether handle is valid", isValidByClass["shipclass"]->description); + + // Derived classes inherit it rather than listing their own + ASSERT_EQ(isValidByClass.end(), isValidByClass.find("ship")); + ASSERT_EQ(isValidByClass.end(), isValidByClass.find("sound3D")); + + // An explicit declaration replaces the generated one + ASSERT_NE(isValidByClass.end(), isValidByClass.find("sound")); + ASSERT_NE(SCP_string::npos, isValidByClass["sound"]->description.find("sound entry")); +} + +// Exercises the generated isValid() of an int-index handle from Lua +TEST_F(ScriptingBaseTest, intValidator) { + this->EvalTestScript(); +} + +// A registered validator must also drive the "return nil instead of an invalid object" option in ade_set_args +TEST_F(ScriptingBaseTest, intValidatorNilReturn) { + auto L = _state->GetLuaSession(); + const bool previous = Lua_API_returns_nil_instead_of_invalid_object; + + // Headless there are no ship classes, so index 0 is invalid + Lua_API_returns_nil_instead_of_invalid_object = false; + ::scripting::ade_set_args(L, "o", ::scripting::api::l_Shipclass.Set(0)); + ASSERT_TRUE(lua_isuserdata(L, -1)); + lua_pop(L, 1); + + Lua_API_returns_nil_instead_of_invalid_object = true; + ::scripting::ade_set_args(L, "o", ::scripting::api::l_Shipclass.Set(0)); + ASSERT_TRUE(lua_isnil(L, -1)); + lua_pop(L, 1); + + Lua_API_returns_nil_instead_of_invalid_object = previous; +} + class ScriptingSerializationTest : public ScriptingBaseTest { public: ScriptingSerializationTest() = default; diff --git a/test/test_data/scripting/base/autoIsValid/data/scripts/test.lua b/test/test_data/scripting/base/autoIsValid/data/scripts/test.lua new file mode 100644 index 0000000000..37a7751342 --- /dev/null +++ b/test/test_data/scripting/base/autoIsValid/data/scripts/test.lua @@ -0,0 +1,16 @@ +-- gamestate and gameevent handles have an isValid() C++ member but never had an explicit +-- ADE_FUNC(isValid, ...), so these exercise the automatically generated function. + +local state = ba.GameStates["GS_STATE_MAIN_MENU"] +assert(type(state.isValid) == "function", "gamestate should expose isValid()") +assert(state:isValid() == true, "a real game state should be valid") + +local badState = ba.GameStates[100000] +assert(badState:isValid() == false, "an out-of-range game state should be invalid") + +local event = ba.GameEvents["GS_EVENT_MAIN_MENU"] +assert(type(event.isValid) == "function", "gameevent should expose isValid()") +assert(event:isValid() == true, "a real game event should be valid") + +local badEvent = ba.GameEvents[100000] +assert(badEvent:isValid() == false, "an out-of-range game event should be invalid") diff --git a/test/test_data/scripting/base/intValidator/data/scripts/test.lua b/test/test_data/scripting/base/intValidator/data/scripts/test.lua new file mode 100644 index 0000000000..ae9a3b74f0 --- /dev/null +++ b/test/test_data/scripting/base/intValidator/data/scripts/test.lua @@ -0,0 +1,7 @@ +-- shipclass is an int-index handle whose validity comes from ADE_OBJ_VALIDATOR. Headless there are no +-- ship classes, so any index yields an invalid handle. + +local sc = tb.ShipClasses[1] +assert(sc ~= nil, "an invalid handle should still be returned when the nil-instead-of-invalid option is off") +assert(type(sc.isValid) == "function", "shipclass should expose isValid()") +assert(sc:isValid() == false, "an out-of-range ship class should be invalid")