31 const nlohmann::json& json) {
33 return absl::InvalidArgumentError(
"Invalid Oracle action model");
36 if (!json.is_object() || json.size() != 3 ||
37 json.at(
"profile") !=
"oracle_actions_v1")
40 behavior.
profile =
"oracle_actions_v1";
41 const auto& hashes = json.at(
"source_sha256");
42 const auto& actions = json.at(
"actions");
43 if (!hashes.is_array() || hashes.size() != 3 || !actions.is_array() ||
44 actions.empty() || actions.size() > 16)
46 for (
int i = 0; i < 3; ++i) {
49 behavior.
source_sha256[i].find_first_not_of(
"0123456789abcdef") !=
53 for (
const auto& value : actions) {
54 if (!value.is_object() || value.size() != 11)
56 auto number = [&](
const char* key,
int low,
int high) {
57 const auto& n = value.at(key);
58 if (!n.is_number_integer() || n < low || n > high)
59 throw std::runtime_error(
"Action field out of range");
63 action.
name = value.at(
"name").get<std::string>();
64 if (action.
name.empty() || action.
name.size() > 80 ||
65 action.
name.find_first_of(
"\r\n\0", 0, 3) != std::string::npos)
67 action.
animation = number(
"animation", 0, 255);
68 action.
block_player = value.at(
"block_player").get<
bool>();
69 action.
message_id = number(
"message_id", -1, 65535);
70 action.
message_next = number(
"message_next", -1, actions.size() - 1);
71 action.
move = value.at(
"move").get<
bool>();
72 action.
x_speed = number(
"x_speed", -128, 127);
73 action.
y_speed = number(
"y_speed", -128, 127);
74 action.
bounce_tiles = value.at(
"bounce_tiles").get<
bool>();
76 action.
timer_next = number(
"timer_next", -1, actions.size() - 1);
82 behavior.
actions.push_back(std::move(action));
85 }
catch (
const std::exception&) {