mirror of
https://github.com/open-goal/jak-project
synced 2026-06-16 06:46:07 -04:00
custom levels: support custom regions in jak2/3 (#4300)
This adds support for generating pairs with `DataObjectGenerator` and defining your own regions and `actor-group`s in custom levels.
This commit is contained in:
@@ -61,6 +61,146 @@ int DataObjectGenerator::add_word_float(float f) {
|
||||
return result;
|
||||
}
|
||||
|
||||
void DataObjectGenerator::add_goos_obj(
|
||||
const goos::Object& obj,
|
||||
const bool last_obj,
|
||||
const std::optional<std::map<std::string, size_t>>& entity_slots,
|
||||
const std::optional<std::map<int, size_t>>& actor_group_slots) {
|
||||
// lg::info("add_goos_obj: {}", obj.inspect());
|
||||
size_t cur_slot = 0;
|
||||
size_t next_slot = 0;
|
||||
if (obj.type == goos::ObjectType::INTEGER || obj.type == goos::ObjectType::FLOAT) {
|
||||
cur_slot = add_word(0);
|
||||
next_slot = add_word(0);
|
||||
}
|
||||
switch (obj.type) {
|
||||
case goos::ObjectType::INTEGER: {
|
||||
add_type_tag("binteger");
|
||||
link_word_to_word(cur_slot, add_word(obj.as_int()));
|
||||
} break;
|
||||
case goos::ObjectType::FLOAT: {
|
||||
add_type_tag("bfloat");
|
||||
link_word_to_word(cur_slot, add_word_float(obj.as_float()));
|
||||
} break;
|
||||
case goos::ObjectType::SYMBOL:
|
||||
add_symbol_link(obj.as_symbol().name_ptr);
|
||||
break;
|
||||
case goos::ObjectType::STRING: {
|
||||
std::string str = obj.as_string()->print();
|
||||
std::erase(str, '\"');
|
||||
add_ref_to_string_in_pool(str);
|
||||
} break;
|
||||
case goos::ObjectType::PAIR: {
|
||||
auto pair_slot = add_word(0);
|
||||
if (last_obj) {
|
||||
add_empty_list();
|
||||
} else {
|
||||
next_slot = add_word(0);
|
||||
}
|
||||
link_word_to_byte(pair_slot, add_pair(obj, entity_slots, actor_group_slots));
|
||||
if (!last_obj) {
|
||||
link_word_to_byte(next_slot, current_offset_bytes() + 2);
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
ASSERT_MSG(false, fmt::format("Unsupported object type in pair: {}", obj.inspect()));
|
||||
}
|
||||
if (!obj.is_pair()) {
|
||||
if (last_obj) {
|
||||
if (obj.type == goos::ObjectType::INTEGER || obj.type == goos::ObjectType::FLOAT) {
|
||||
link_word_to_symbol("_empty_", next_slot);
|
||||
} else {
|
||||
add_empty_list();
|
||||
}
|
||||
} else {
|
||||
if (obj.type == goos::ObjectType::INTEGER || obj.type == goos::ObjectType::FLOAT) {
|
||||
link_word_to_byte(next_slot, current_offset_bytes() + 2);
|
||||
} else {
|
||||
link_word_to_byte(add_word(0), current_offset_bytes() + 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int DataObjectGenerator::add_pair(const goos::Object& obj,
|
||||
const std::optional<std::map<std::string, size_t>>& entity_slots,
|
||||
const std::optional<std::map<int, size_t>>& actor_group_slots) {
|
||||
size_t pair_slot = current_offset_bytes() + 2;
|
||||
// lg::info("add_pair: parsing {}", obj.print());
|
||||
|
||||
goos::Object current = obj;
|
||||
while (!current.is_empty_list()) {
|
||||
// lg::info("add_pair: current {}", current.print());
|
||||
auto next = current.as_pair()->car;
|
||||
// special case for entities or actor groups: script pairs can have references to actor groups
|
||||
// or entities from the level data
|
||||
if (next.is_pair() && next.as_pair()->car.is_symbol()) {
|
||||
if (!strcmp(next.as_pair()->car.as_symbol().name_ptr, "entity-actor")) {
|
||||
if (entity_slots.has_value()) {
|
||||
auto pair = next.as_pair();
|
||||
auto type = pair->car;
|
||||
auto val = pair->cdr.as_pair()->car.as_symbol().name_ptr;
|
||||
auto slot = entity_slots->find(val);
|
||||
if (slot != entity_slots->end()) {
|
||||
link_word_to_byte(add_word(0), slot->second);
|
||||
if (current.as_pair()->cdr.is_empty_list()) {
|
||||
add_empty_list();
|
||||
} else {
|
||||
link_word_to_byte(add_word(0), current_offset_bytes() + 2);
|
||||
}
|
||||
} else {
|
||||
ASSERT_MSG(false, fmt::format("error in pair {}: for {}, entity-actor {} not found",
|
||||
obj.print(), pair->print(), val));
|
||||
}
|
||||
}
|
||||
} else if (!strcmp(next.as_pair()->car.as_symbol().name_ptr, "actor-group")) {
|
||||
if (actor_group_slots.has_value()) {
|
||||
auto pair = next.as_pair();
|
||||
auto type = pair->car;
|
||||
auto val = pair->cdr.as_pair()->car.as_int();
|
||||
auto slot = actor_group_slots->find(val);
|
||||
if (slot != actor_group_slots->end()) {
|
||||
link_word_to_byte(add_word(0), slot->second);
|
||||
if (current.as_pair()->cdr.is_empty_list()) {
|
||||
add_empty_list();
|
||||
} else {
|
||||
link_word_to_byte(add_word(0), current_offset_bytes() + 2);
|
||||
}
|
||||
} else {
|
||||
ASSERT_MSG(false, fmt::format("error in pair {}: for {}, got invalid id {}",
|
||||
obj.print(), pair->print(), val));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (current.as_pair()->cdr.is_empty_list()) {
|
||||
// lg::info("add_pair: next (last elem) {}", next.print());
|
||||
add_goos_obj(next, true, entity_slots, actor_group_slots);
|
||||
} else {
|
||||
// lg::info("add_pair: next {}", next.print());
|
||||
add_goos_obj(next, false, entity_slots, actor_group_slots);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (current.as_pair()->cdr.is_empty_list()) {
|
||||
// lg::info("add_pair: next (last elem) {}", next.print());
|
||||
add_goos_obj(next, true, entity_slots, actor_group_slots);
|
||||
} else {
|
||||
// lg::info("add_pair: next {}", next.print());
|
||||
add_goos_obj(next, false, entity_slots, actor_group_slots);
|
||||
}
|
||||
}
|
||||
current = current.as_pair()->cdr;
|
||||
}
|
||||
return pair_slot;
|
||||
}
|
||||
|
||||
int DataObjectGenerator::add_empty_list() {
|
||||
auto result = int(m_words.size());
|
||||
m_words.push_back(0);
|
||||
m_symbol_links["_empty_"].push_back(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void DataObjectGenerator::set_word(u32 word_idx, u32 val) {
|
||||
m_words.at(word_idx) = val;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user