/** * EQEmulator: Everquest Server Emulator * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY except by those people which sell it, which * are required to give you total support for your newly bought product; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "expedition_database.h" #include "expedition.h" #include "zonedb.h" #include "../common/database.h" #include "../common/expedition_lockout_timer.h" #include "../common/strings.h" #include uint32_t ExpeditionDatabase::InsertExpedition(uint32_t dz_id) { LogExpeditionsDetail("Inserting new expedition dz [{}]", dz_id); std::string query = fmt::format(SQL( INSERT INTO expeditions (dynamic_zone_id) VALUES ({}); ), dz_id); auto results = database.QueryDatabase(query); if (!results.Success()) { LogExpeditions("Failed to obtain an expedition id for dz [{}]", dz_id); return 0; } return results.LastInsertedID(); } std::vector ExpeditionDatabase::LoadCharacterLockouts(uint32_t character_id) { LogExpeditionsDetail("Loading character [{}] lockouts", character_id); std::vector lockouts; auto query = fmt::format(SQL( SELECT from_expedition_uuid, expedition_name, event_name, UNIX_TIMESTAMP(expire_time), duration FROM character_expedition_lockouts WHERE character_id = {} AND expire_time > NOW(); ), character_id); auto results = database.QueryDatabase(query); if (results.Success()) { for (auto row = results.begin(); row != results.end(); ++row) { lockouts.emplace_back( row[0], // expedition_uuid row[1], // expedition_name row[2], // event_name strtoull(row[3], nullptr, 10), // expire_time static_cast(strtoul(row[4], nullptr, 10)) // duration ); } } return lockouts; } std::vector ExpeditionDatabase::LoadCharacterLockouts( uint32_t character_id, const std::string& expedition_name) { LogExpeditionsDetail("Loading character [{}] lockouts for [{}]", character_id, expedition_name); std::vector lockouts; auto query = fmt::format(SQL( SELECT from_expedition_uuid, event_name, UNIX_TIMESTAMP(expire_time), duration FROM character_expedition_lockouts WHERE character_id = {} AND expire_time > NOW() AND expedition_name = '{}'; ), character_id, Strings::Escape(expedition_name)); auto results = database.QueryDatabase(query); if (results.Success()) { for (auto row = results.begin(); row != results.end(); ++row) { lockouts.emplace_back( row[0], // expedition_uuid expedition_name, row[1], // event_name strtoull(row[2], nullptr, 10), // expire_time static_cast(strtoul(row[3], nullptr, 10)) // duration ); } } return lockouts; } void ExpeditionDatabase::DeleteAllCharacterLockouts(uint32_t character_id) { LogExpeditionsDetail("Deleting all character [{}] lockouts", character_id); if (character_id != 0) { std::string query = fmt::format(SQL( DELETE FROM character_expedition_lockouts WHERE character_id = {}; ), character_id); database.QueryDatabase(query); } } void ExpeditionDatabase::DeleteAllCharacterLockouts( uint32_t character_id, const std::string& expedition_name) { LogExpeditionsDetail("Deleting all character [{}] lockouts for [{}]", character_id, expedition_name); if (character_id != 0 && !expedition_name.empty()) { std::string query = fmt::format(SQL( DELETE FROM character_expedition_lockouts WHERE character_id = {} AND expedition_name = '{}'; ), character_id, Strings::Escape(expedition_name)); database.QueryDatabase(query); } } void ExpeditionDatabase::DeleteCharacterLockout( uint32_t character_id, const std::string& expedition_name, const std::string& event_name) { LogExpeditionsDetail( "Deleting character [{}] lockout: [{}]:[{}]", character_id, expedition_name, event_name ); auto query = fmt::format(SQL( DELETE FROM character_expedition_lockouts WHERE character_id = {} AND expedition_name = '{}' AND event_name = '{}'; ), character_id, Strings::Escape(expedition_name), Strings::Escape(event_name)); database.QueryDatabase(query); } void ExpeditionDatabase::DeleteMembersLockout( const std::vector& members, const std::string& expedition_name, const std::string& event_name) { LogExpeditionsDetail("Deleting members lockout: [{}]:[{}]", expedition_name, event_name); std::string query_character_ids; for (const auto& member : members) { fmt::format_to(std::back_inserter(query_character_ids), "{},", member.id); } if (!query_character_ids.empty()) { query_character_ids.pop_back(); // trailing comma auto query = fmt::format(SQL( DELETE FROM character_expedition_lockouts WHERE character_id IN ({}) AND expedition_name = '{}' AND event_name = '{}'; ), query_character_ids, Strings::Escape(expedition_name), Strings::Escape(event_name)); database.QueryDatabase(query); } } void ExpeditionDatabase::DeleteLockout(uint32_t expedition_id, const std::string& event_name) { LogExpeditionsDetail("Deleting expedition [{}] lockout event [{}]", expedition_id, event_name); auto query = fmt::format(SQL( DELETE FROM expedition_lockouts WHERE expedition_id = {} AND event_name = '{}'; ), expedition_id, Strings::Escape(event_name)); database.QueryDatabase(query); } void ExpeditionDatabase::InsertCharacterLockouts(uint32_t character_id, const std::vector& lockouts) { LogExpeditionsDetail("Inserting [{}] lockouts for character [{}]", lockouts.size(), character_id); std::string insert_values; for (const auto& lockout : lockouts) { fmt::format_to(std::back_inserter(insert_values), "({}, FROM_UNIXTIME({}), {}, '{}', '{}', '{}'),", character_id, lockout.GetExpireTime(), lockout.GetDuration(), lockout.GetExpeditionUUID(), Strings::Escape(lockout.GetExpeditionName()), Strings::Escape(lockout.GetEventName()) ); } if (!insert_values.empty()) { insert_values.pop_back(); // trailing comma auto query = fmt::format(SQL( INSERT INTO character_expedition_lockouts (character_id, expire_time, duration, from_expedition_uuid, expedition_name, event_name) VALUES {} ON DUPLICATE KEY UPDATE from_expedition_uuid = VALUES(from_expedition_uuid), expire_time = VALUES(expire_time), duration = VALUES(duration); ), insert_values); database.QueryDatabase(query); } } void ExpeditionDatabase::InsertMembersLockout( const std::vector& members, const ExpeditionLockoutTimer& lockout) { LogExpeditionsDetail( "Inserting members lockout [{}]:[{}] with expire time [{}]", lockout.GetExpeditionName(), lockout.GetEventName(), lockout.GetExpireTime() ); std::string insert_values; for (const auto& member : members) { fmt::format_to(std::back_inserter(insert_values), "({}, FROM_UNIXTIME({}), {}, '{}', '{}', '{}'),", member.id, lockout.GetExpireTime(), lockout.GetDuration(), lockout.GetExpeditionUUID(), Strings::Escape(lockout.GetExpeditionName()), Strings::Escape(lockout.GetEventName()) ); } if (!insert_values.empty()) { insert_values.pop_back(); // trailing comma auto query = fmt::format(SQL( INSERT INTO character_expedition_lockouts (character_id, expire_time, duration, from_expedition_uuid, expedition_name, event_name) VALUES {} ON DUPLICATE KEY UPDATE from_expedition_uuid = VALUES(from_expedition_uuid), expire_time = VALUES(expire_time), duration = VALUES(duration); ), insert_values); database.QueryDatabase(query); } } void ExpeditionDatabase::InsertLockout( uint32_t expedition_id, const ExpeditionLockoutTimer& lockout) { LogExpeditionsDetail( "Inserting expedition [{}] lockout: [{}]:[{}] expire time: [{}]", expedition_id, lockout.GetExpeditionName(), lockout.GetEventName(), lockout.GetExpireTime() ); auto query = fmt::format(SQL( INSERT INTO expedition_lockouts (expedition_id, from_expedition_uuid, event_name, expire_time, duration) VALUES ({}, '{}', '{}', FROM_UNIXTIME({}), {}) ON DUPLICATE KEY UPDATE from_expedition_uuid = VALUES(from_expedition_uuid), expire_time = VALUES(expire_time), duration = VALUES(duration); ), expedition_id, lockout.GetExpeditionUUID(), Strings::Escape(lockout.GetEventName()), lockout.GetExpireTime(), lockout.GetDuration() ); database.QueryDatabase(query); } void ExpeditionDatabase::InsertLockouts( uint32_t expedition_id, const std::unordered_map& lockouts) { LogExpeditionsDetail("Inserting expedition [{}] lockouts", expedition_id); std::string insert_values; for (const auto& lockout : lockouts) { fmt::format_to(std::back_inserter(insert_values), "({}, '{}', '{}', FROM_UNIXTIME({}), {}),", expedition_id, lockout.second.GetExpeditionUUID(), Strings::Escape(lockout.second.GetEventName()), lockout.second.GetExpireTime(), lockout.second.GetDuration() ); } if (!insert_values.empty()) { insert_values.pop_back(); // trailing comma auto query = fmt::format(SQL( INSERT INTO expedition_lockouts (expedition_id, from_expedition_uuid, event_name, expire_time, duration) VALUES {} ON DUPLICATE KEY UPDATE from_expedition_uuid = VALUES(from_expedition_uuid), expire_time = VALUES(expire_time), duration = VALUES(duration); ), insert_values); database.QueryDatabase(query); } } void ExpeditionDatabase::UpdateLockState(uint32_t expedition_id, bool is_locked) { LogExpeditionsDetail("Updating lock state [{}] for expedition [{}]", is_locked, expedition_id); auto query = fmt::format(SQL( UPDATE expeditions SET is_locked = {} WHERE id = {}; ), is_locked, expedition_id); database.QueryDatabase(query); } void ExpeditionDatabase::UpdateReplayLockoutOnJoin(uint32_t expedition_id, bool add_on_join) { LogExpeditionsDetail("Updating replay lockout on join [{}] for expedition [{}]", add_on_join, expedition_id); auto query = fmt::format(SQL( UPDATE expeditions SET add_replay_on_join = {} WHERE id = {}; ), add_on_join, expedition_id); database.QueryDatabase(query); } void ExpeditionDatabase::AddLockoutDuration(const std::vector& members, const ExpeditionLockoutTimer& lockout, int seconds) { LogExpeditionsDetail( "Adding duration [{}] seconds to members lockouts [{}]:[{}]", seconds, lockout.GetExpeditionName(), lockout.GetEventName()); std::string insert_values; for (const auto& member : members) { fmt::format_to(std::back_inserter(insert_values), "({}, FROM_UNIXTIME({}), {}, '{}', '{}', '{}'),", member.id, lockout.GetExpireTime(), lockout.GetDuration(), lockout.GetExpeditionUUID(), Strings::Escape(lockout.GetExpeditionName()), Strings::Escape(lockout.GetEventName()) ); } if (!insert_values.empty()) { insert_values.pop_back(); // trailing comma auto query = fmt::format(SQL( INSERT INTO character_expedition_lockouts (character_id, expire_time, duration, from_expedition_uuid, expedition_name, event_name) VALUES {} ON DUPLICATE KEY UPDATE from_expedition_uuid = VALUES(from_expedition_uuid), expire_time = DATE_ADD(expire_time, INTERVAL {} SECOND), duration = GREATEST(0, CAST(duration AS SIGNED) + {}); ), insert_values, seconds, seconds); database.QueryDatabase(query); } }