link map objects to constructor args instead of copying them

This commit is contained in:
Martin Michelsen
2024-10-16 21:37:05 -07:00
parent 080a9ebac4
commit 47bc37e806
5 changed files with 53 additions and 54 deletions
+2 -8
View File
@@ -302,13 +302,7 @@ shared_ptr<Map> Lobby::load_maps(
shared_ptr<PSOLFGEncryption> opt_rand_crypt,
shared_ptr<const string> quest_dat_contents_decompressed) {
auto map = make_shared<Map>(version, lobby_id, random_seed, opt_rand_crypt);
map->add_entities_from_quest_data(
episode,
difficulty,
event,
quest_dat_contents_decompressed->data(),
quest_dat_contents_decompressed->size(),
rare_rates);
map->add_entities_from_quest_data(episode, difficulty, event, quest_dat_contents_decompressed, rare_rates);
return map;
}
@@ -396,7 +390,7 @@ shared_ptr<Map> Lobby::load_maps(
if (!floor_object_filename.empty()) {
auto map_data = get_file_data(version, floor_object_filename);
if (map_data) {
map->add_objects_from_map_data(floor, map_data->data(), map_data->size());
map->add_objects_from_map_data(floor, map_data);
if (log) {
log->info("Loaded objects map %s for floor %02zX", floor_object_filename.c_str(), floor);
}
+1 -1
View File
@@ -2401,7 +2401,7 @@ Action a_load_maps_test(
fprintf(stderr, " [%s => ", objects_filename.c_str());
auto map_data = s->load_map_file(v, objects_filename);
if (map_data) {
map->add_objects_from_map_data(floor, map_data->data(), map_data->size());
map->add_objects_from_map_data(floor, map_data);
fprintf(stderr, "%zu objects]", map->objects.size());
} else {
fprintf(stderr, "__MISSING__]");
+31 -24
View File
@@ -704,17 +704,25 @@ string Map::Event::str() const {
}
string Map::Object::str() const {
return phosg::string_printf("[Map::Object source %zX %04hX(%s) @%04hX p1=%g p456=[%08" PRIX32 " %08" PRIX32 " %08" PRIX32 "] floor=%02hhX item_drop_checked=%s]",
this->source_index,
this->base_type,
Map::name_for_object_type(this->base_type),
this->section,
this->param1,
this->param4,
this->param5,
this->param6,
return phosg::string_printf("[Map::Object floor %02hhX source %zX %04hX(%s) @%04hX:(%g %g %g)/(%04" PRIX32 " %04" PRIX32 " %04" PRIX32 ") +%04hX params [%g %g %g %08" PRIX32 " %08" PRIX32 " %08" PRIX32 "]]",
this->floor,
this->item_drop_checked ? "true" : "false");
this->source_index,
this->args->base_type.load(),
Map::name_for_object_type(this->args->base_type),
this->args->section.load(),
this->args->x.load(),
this->args->y.load(),
this->args->z.load(),
this->args->x_angle.load(),
this->args->y_angle.load(),
this->args->z_angle.load(),
this->args->group.load(),
this->args->param1.load(),
this->args->param2.load(),
this->args->param3.load(),
this->args->param4.load(),
this->args->param5.load(),
this->args->param6.load());
}
Map::Map(Version version, uint32_t lobby_id, uint32_t rare_seed, std::shared_ptr<PSOLFGEncryption> opt_rand_crypt)
@@ -729,7 +737,7 @@ void Map::clear() {
this->rare_enemy_indexes.clear();
}
void Map::add_objects_from_map_data(uint8_t floor, const void* data, size_t size) {
void Map::add_objects_from_owned_map_data(uint8_t floor, const void* data, size_t size) {
size_t entry_count = size / sizeof(ObjectEntry);
if (size != entry_count * sizeof(ObjectEntry)) {
throw runtime_error("data size is not a multiple of entry size");
@@ -739,17 +747,10 @@ void Map::add_objects_from_map_data(uint8_t floor, const void* data, size_t size
for (size_t z = 0; z < entry_count; z++) {
uint16_t object_id = this->objects.size();
this->objects.emplace_back(Object{
.args = &objects[z],
.source_index = z,
.floor = floor,
.object_id = object_id,
.base_type = objects[z].base_type,
.section = objects[z].section,
.group = objects[z].group,
.param1 = objects[z].param1,
.param3 = objects[z].param3,
.param4 = objects[z].param4,
.param5 = objects[z].param5,
.param6 = objects[z].param6,
.game_flags = 0,
.set_flags = 0,
.item_drop_checked = false,
@@ -759,6 +760,11 @@ void Map::add_objects_from_map_data(uint8_t floor, const void* data, size_t size
}
}
void Map::add_objects_from_map_data(uint8_t floor, std::shared_ptr<const string> data) {
this->link_owned_data(data);
this->add_objects_from_owned_map_data(floor, data->data(), data->size());
}
bool Map::check_and_log_rare_enemy(bool default_is_rare, uint32_t rare_rate) {
if (default_is_rare) {
return true;
@@ -1597,12 +1603,13 @@ void Map::add_entities_from_quest_data(
Episode episode,
uint8_t difficulty,
uint8_t event,
const void* data,
size_t size,
std::shared_ptr<const string> data,
std::shared_ptr<const RareEnemyRates> rare_rates) {
auto all_floor_sections = this->collect_quest_map_data_sections(data, size);
this->link_owned_data(data);
phosg::StringReader r(data, size);
auto all_floor_sections = this->collect_quest_map_data_sections(data->data(), data->size());
phosg::StringReader r(*data);
shared_ptr<DATParserRandomState> random_state;
for (size_t floor = 0; floor < all_floor_sections.size(); floor++) {
const auto& floor_sections = all_floor_sections[floor];
@@ -1612,7 +1619,7 @@ void Map::add_entities_from_quest_data(
if (header.data_size % sizeof(ObjectEntry)) {
throw runtime_error("quest layout object section size is not a multiple of object entry size");
}
this->add_objects_from_map_data(floor, r.pgetv(floor_sections.objects + sizeof(header), header.data_size), header.data_size);
this->add_objects_from_owned_map_data(floor, r.pgetv(floor_sections.objects + sizeof(header), header.data_size), header.data_size);
}
if ((floor_sections.wave_events != 0xFFFFFFFF) &&
+11 -13
View File
@@ -51,9 +51,9 @@ struct Map {
/* 1C */ le_uint32_t x_angle;
/* 20 */ le_uint32_t y_angle;
/* 24 */ le_uint32_t z_angle;
/* 28 */ le_float param1; // If <= 0, this is a specialized box, and the specialization is in param4/5/6
/* 28 */ le_float param1; // Boxes: if <= 0, this is a specialized box, and the specialization is in param4/5/6
/* 2C */ le_float param2;
/* 30 */ le_float param3;
/* 30 */ le_float param3; // Boxes: if == 0, the item should be varied by difficulty and area
/* 34 */ le_uint32_t param4;
/* 38 */ le_uint32_t param5;
/* 3C */ le_uint32_t param6;
@@ -211,17 +211,10 @@ struct Map {
struct Object {
// TODO: Add more fields in here if we ever care about them. Currently we
// only care about boxes with fixed item drops.
const ObjectEntry* args;
size_t source_index;
uint8_t floor;
uint16_t object_id;
uint16_t base_type;
uint16_t section;
uint16_t group;
float param1; // If <= 0, this is a specialized box, and the specialization is in param4/5/6
float param3; // If == 0, the item should be varied by difficulty and area
uint32_t param4;
uint32_t param5;
uint32_t param6;
uint16_t game_flags;
// Technically set_flags shouldn't be part of the Object struct, but all
// object entries always generate exactly one object, so we store it here.
@@ -305,7 +298,12 @@ struct Map {
void clear();
void add_objects_from_map_data(uint8_t floor, const void* data, size_t size);
inline void link_owned_data(std::shared_ptr<const std::string> data) {
this->linked_data.emplace(data);
}
void add_objects_from_owned_map_data(uint8_t floor, const void* data, size_t size);
void add_objects_from_map_data(uint8_t floor, std::shared_ptr<const std::string> data);
bool check_and_log_rare_enemy(bool default_is_rare, uint32_t rare_rate);
void add_enemy(
@@ -359,8 +357,7 @@ struct Map {
Episode episode,
uint8_t difficulty,
uint8_t event,
const void* data,
size_t size,
std::shared_ptr<const std::string> data,
std::shared_ptr<const RareEnemyRates> rare_rates = Map::DEFAULT_RARE_ENEMIES);
const Enemy& find_enemy(uint16_t enemy_id) const;
@@ -380,6 +377,7 @@ struct Map {
phosg::PrefixedLogger log;
Version version;
uint32_t rare_seed;
std::unordered_set<std::shared_ptr<const std::string>> linked_data;
std::shared_ptr<PSOLFGEncryption> opt_rand_crypt;
std::vector<Object> objects;
std::vector<Enemy> enemies;
+8 -8
View File
@@ -2579,26 +2579,26 @@ DropReconcileResult reconcile_drop_request_with_map(
if (map) {
map_object = &map->objects.at(cmd.entity_id);
log.info("Drop check for K-%hX %c %s",
map_object->object_id, res.ignore_def ? 'G' : 'S', Map::name_for_object_type(map_object->base_type));
map_object->object_id, res.ignore_def ? 'G' : 'S', Map::name_for_object_type(map_object->args->base_type));
if (cmd.floor != map_object->floor) {
log.warning("Floor %02hhX from command does not match object\'s expected floor %02hhX", cmd.floor, map_object->floor);
}
if (is_v1_or_v2(version) && (version != Version::GC_NTE)) {
// V1 and V2 don't have 6xA2, so we can't get ignore_def or the object
// parameters from the client on those versions
cmd.param3 = map_object->param3;
cmd.param4 = map_object->param4;
cmd.param5 = map_object->param5;
cmd.param6 = map_object->param6;
cmd.param3 = map_object->args->param3;
cmd.param4 = map_object->args->param4;
cmd.param5 = map_object->args->param5;
cmd.param6 = map_object->args->param6;
}
bool object_ignore_def = (map_object->param1 > 0.0);
bool object_ignore_def = (map_object->args->param1 > 0.0);
if (res.ignore_def != object_ignore_def) {
log.warning("ignore_def value %s from command does not match object\'s expected ignore_def %s (from p1=%g)",
res.ignore_def ? "true" : "false", object_ignore_def ? "true" : "false", map_object->param1);
res.ignore_def ? "true" : "false", object_ignore_def ? "true" : "false", map_object->args->param1.load());
}
if (config.check_flag(Client::Flag::DEBUG_ENABLED)) {
send_text_message_printf(client_channel, "$C5K-%hX %c %s",
map_object->object_id, res.ignore_def ? 'G' : 'S', Map::name_for_object_type(map_object->base_type));
map_object->object_id, res.ignore_def ? 'G' : 'S', Map::name_for_object_type(map_object->args->base_type));
}
}