|
|
@ -319,6 +319,92 @@ struct fn_array_index final : public scripting::function_impl { |
|
|
|
~fn_array_index() final = default; |
|
|
|
}; |
|
|
|
|
|
|
|
struct fn_array_set final : public scripting::function_impl { |
|
|
|
fn_array_set() = default; |
|
|
|
|
|
|
|
std::optional<script_value> apply(UserScript* self, std::vector<argument> n, std::optional<script_error>& error) final { |
|
|
|
if(n.size() != 3) { |
|
|
|
error = script_error{ |
|
|
|
.message = "/array_set takes exactly 3 argument of type (array, integer, value), provided a different amount" |
|
|
|
}; |
|
|
|
return std::nullopt; |
|
|
|
} |
|
|
|
|
|
|
|
auto& arg = n.back(); |
|
|
|
|
|
|
|
if(std::holds_alternative<scripting::script_value>(arg)) { |
|
|
|
error = script_error{ |
|
|
|
.message = "/array_set takes exactly 3 argument of type (array, integer, value), the array needs to be a variable" |
|
|
|
}; |
|
|
|
return std::nullopt; |
|
|
|
} |
|
|
|
|
|
|
|
auto target = self->getValue(std::get<scripting::script_variable>(arg).name); |
|
|
|
|
|
|
|
if(not target) { |
|
|
|
error = script_error{ |
|
|
|
.message = "/array_set takes exactly 3 argument of type (array, integer, value), provided array variable is undefined" |
|
|
|
}; |
|
|
|
return std::nullopt; |
|
|
|
} |
|
|
|
|
|
|
|
if(not std::holds_alternative<array>(target.value().get())) { |
|
|
|
error = script_error{ |
|
|
|
.message = "/array_set takes exactly 1 argument of type array followed by an integer, argument 1 is not an array" |
|
|
|
}; |
|
|
|
return std::nullopt; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
auto& concrete_target = std::get<array>(target.value().get()); |
|
|
|
|
|
|
|
auto& idx_arg = n[1]; |
|
|
|
script_value idx; |
|
|
|
|
|
|
|
if(std::holds_alternative<scripting::script_value>(idx_arg)) { |
|
|
|
idx = std::get<scripting::script_value>(idx_arg); |
|
|
|
} else { |
|
|
|
idx = self->resolve(std::get<scripting::script_variable>(idx_arg).name); |
|
|
|
} |
|
|
|
|
|
|
|
if(not std::holds_alternative<int32_t>(idx)) { |
|
|
|
error = script_error{ |
|
|
|
.message = "/array_set takes exactly 1 argument of type array followed by an integer, argument 2 is not an integer" |
|
|
|
}; |
|
|
|
return std::nullopt; |
|
|
|
} |
|
|
|
|
|
|
|
if(static_cast<int32_t>(concrete_target.value.size()) <= std::get<int32_t>(idx)) { |
|
|
|
error = script_error{ |
|
|
|
.message = "/array_set index must be smaller that the array size, the first element of the array has index 0" |
|
|
|
}; |
|
|
|
return std::nullopt; |
|
|
|
} |
|
|
|
|
|
|
|
if(std::get<int32_t>(idx) < 0) { |
|
|
|
error = script_error{ |
|
|
|
.message = "/array_set index must be 0 or more" |
|
|
|
}; |
|
|
|
return std::nullopt; |
|
|
|
} |
|
|
|
|
|
|
|
auto& value_arg = n.front(); |
|
|
|
script_value value; |
|
|
|
|
|
|
|
if(std::holds_alternative<scripting::script_value>(value_arg)) { |
|
|
|
value = std::get<scripting::script_value>(value_arg); |
|
|
|
} else { |
|
|
|
value = self->resolve(std::get<scripting::script_variable>(value_arg).name); |
|
|
|
} |
|
|
|
|
|
|
|
concrete_target.value.at(std::get<int32_t>(idx)) = value; |
|
|
|
|
|
|
|
return concrete_target.value[std::get<int32_t>(idx)]; |
|
|
|
} |
|
|
|
|
|
|
|
~fn_array_set() final = default; |
|
|
|
}; |
|
|
|
|
|
|
|
namespace scripting { |
|
|
|
|
|
|
|
interpreter register_array_lib(interpreter target, bool recursive_arrays, int32_t size_limit) { |
|
|
@ -329,6 +415,7 @@ namespace scripting { |
|
|
|
target->registerFunction("array_pop", std::make_unique<fn_array_pop>()); |
|
|
|
target->registerFunction("array_size", std::make_unique<fn_array_size>()); |
|
|
|
target->registerFunction("array_index", std::make_unique<fn_array_index>()); |
|
|
|
target->registerFunction("array_set", std::make_unique<fn_array_set>()); |
|
|
|
return std::move(target); |
|
|
|
} |
|
|
|
|