From c4cda66c3bb0761fec322a43fb951de5e19dcbd6 Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Sat, 4 May 2024 18:11:59 -0400 Subject: [PATCH] [Quest API] Add Parcel Sending to Perl/Lua (#4287) --- .../character_parcels_repository.h | 31 ++++++++ zone/embparser_api.cpp | 70 ++++++++++++++++++ zone/lua_general.cpp | 73 +++++++++++++++++++ 3 files changed, 174 insertions(+) diff --git a/common/repositories/character_parcels_repository.h b/common/repositories/character_parcels_repository.h index 97118fa2a..5403d6437 100644 --- a/common/repositories/character_parcels_repository.h +++ b/common/repositories/character_parcels_repository.h @@ -78,6 +78,37 @@ public: return all_entries; } + + static int GetNextFreeParcelSlot(Database& db, const uint32 character_id, const uint32 max_slots) + { + const auto& l = CharacterParcelsRepository::GetWhere( + db, + fmt::format( + "char_id = '{}' ORDER BY slot_id ASC", + character_id + ) + ); + + if (l.empty()) { + return PARCEL_BEGIN_SLOT; + } + + for (uint32 i = PARCEL_BEGIN_SLOT; i <= max_slots; i++) { + auto it = std::find_if( + l.cbegin(), + l.cend(), + [&](const auto &x) { + return x.slot_id == i; + } + ); + + if (it == l.end()) { + return i; + } + } + + return INVALID_INDEX; + } }; #endif //EQEMU_CHARACTER_PARCELS_REPOSITORY_H diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index dc706ac5e..aa87232fd 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -5875,6 +5875,75 @@ std::string Perl__GetZoneShortNameByLongName(std::string zone_long_name) return zone_store.GetZoneShortNameByLongName(zone_long_name); } +bool Perl__send_parcel(perl::reference table_ref) +{ + perl::hash table = table_ref; + if ( + (!table.exists("name") && !table.exists("character_id")) || + !table.exists("item_id") || + !table.exists("quantity") + ) { + return false; + } + + std::string name = table.exists("name") ? table["name"] : ""; + uint32 character_id = table.exists("character_id") ? table["character_id"] : 0; + + if (character_id) { + const std::string& character_name = database.GetCharName(character_id); + if (character_name.empty()) { + return false; + } + + name = character_name; + } else { + auto v = CharacterParcelsRepository::GetParcelCountAndCharacterName(database, name); + if (v.at(0).character_name.empty()) { + return false; + } + + character_id = v.at(0).char_id; + } + + if (!character_id) { + return false; + } + + const int next_parcel_slot = CharacterParcelsRepository::GetNextFreeParcelSlot(database, character_id, RuleI(Parcel, ParcelMaxItems)); + if (next_parcel_slot == INVALID_INDEX) { + return false; + } + + const uint32 item_id = table["item_id"]; + const int16 quantity = table["quantity"]; + const uint32 augment_one = table.exists("augment_one") ? table["augment_one"] : 0; + const uint32 augment_two = table.exists("augment_two") ? table["augment_two"] : 0; + const uint32 augment_three = table.exists("augment_three") ? table["augment_three"] : 0; + const uint32 augment_four = table.exists("augment_four") ? table["augment_four"] : 0; + const uint32 augment_five = table.exists("augment_five") ? table["augment_five"] : 0; + const uint32 augment_six = table.exists("augment_six") ? table["augment_six"] : 0; + const std::string& from_name = table.exists("from_name") ? table["from_name"] : std::string(); + const std::string& note = table.exists("note") ? table["note"] : std::string(); + + auto e = CharacterParcelsRepository::NewEntity(); + + e.char_id = character_id; + e.item_id = item_id; + e.aug_slot_1 = augment_one; + e.aug_slot_2 = augment_two; + e.aug_slot_3 = augment_three; + e.aug_slot_4 = augment_four; + e.aug_slot_5 = augment_five; + e.aug_slot_6 = augment_six; + e.slot_id = next_parcel_slot; + e.quantity = quantity; + e.from_name = from_name; + e.note = note; + e.sent_date = std::time(nullptr); + + return CharacterParcelsRepository::InsertOne(database, e).id; +} + void perl_register_quest() { perl::interpreter perl(PERL_GET_THX); @@ -6704,6 +6773,7 @@ void perl_register_quest() package.add("send_channel_message", (void(*)(uint8, uint32, uint8, uint8, const char*))&Perl__send_channel_message); package.add("send_channel_message", (void(*)(Client*, uint8, uint32, uint8, uint8, const char*))&Perl__send_channel_message); package.add("send_channel_message", (void(*)(Client*, const char*, uint8, uint32, uint8, uint8, const char*))&Perl__send_channel_message); + package.add("send_parcel", &Perl__send_parcel); package.add("setaaexpmodifierbycharid", (void(*)(uint32, uint32, double))&Perl__setaaexpmodifierbycharid); package.add("setaaexpmodifierbycharid", (void(*)(uint32, uint32, double, int16))&Perl__setaaexpmodifierbycharid); package.add("set_data", (void(*)(std::string, std::string))&Perl__set_data); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 5f1d03d34..19c8c280a 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -5504,6 +5504,78 @@ std::string lua_get_zone_short_name_by_long_name(std::string zone_long_name) { return zone_store.GetZoneShortNameByLongName(zone_long_name); } +bool lua_send_parcel(luabind::object lua_table) +{ + if (luabind::type(lua_table) != LUA_TTABLE) { + return false; + } + + if ( + (luabind::type(lua_table["name"]) == LUA_TNIL && luabind::type(lua_table["character_id"]) == LUA_TNIL) || + luabind::type(lua_table["item_id"]) == LUA_TNIL || + luabind::type(lua_table["quantity"]) == LUA_TNIL + ) { + return false; + } + + std::string name = luabind::type(lua_table["name"]) != LUA_TNIL ? luabind::object_cast(lua_table["name"]) : ""; + uint32 character_id = luabind::type(lua_table["character_id"]) != LUA_TNIL ? luabind::object_cast(lua_table["character_id"]) : 0; + + if (character_id) { + const std::string& character_name = database.GetCharName(character_id); + if (character_name.empty()) { + return false; + } + + name = character_name; + } else { + auto v = CharacterParcelsRepository::GetParcelCountAndCharacterName(database, name); + if (v.at(0).character_name.empty()) { + return false; + } + + character_id = v.at(0).char_id; + } + + if (!character_id) { + return false; + } + + const int next_parcel_slot = CharacterParcelsRepository::GetNextFreeParcelSlot(database, character_id, RuleI(Parcel, ParcelMaxItems)); + if (next_parcel_slot == INVALID_INDEX) { + return false; + } + + const uint32 item_id = luabind::object_cast(lua_table["item_id"]); + const int16 quantity = luabind::object_cast(lua_table["quantity"]); + const uint32 augment_one = luabind::type(lua_table["augment_one"]) != LUA_TNIL ? luabind::object_cast(lua_table["augment_one"]) : 0; + const uint32 augment_two = luabind::type(lua_table["augment_two"]) != LUA_TNIL ? luabind::object_cast(lua_table["augment_two"]) : 0; + const uint32 augment_three = luabind::type(lua_table["augment_three"]) != LUA_TNIL ? luabind::object_cast(lua_table["augment_three"]) : 0; + const uint32 augment_four = luabind::type(lua_table["augment_four"]) != LUA_TNIL ? luabind::object_cast(lua_table["augment_four"]) : 0; + const uint32 augment_five = luabind::type(lua_table["augment_five"]) != LUA_TNIL ? luabind::object_cast(lua_table["augment_five"]) : 0; + const uint32 augment_six = luabind::type(lua_table["augment_six"]) != LUA_TNIL ? luabind::object_cast(lua_table["augment_six"]) : 0; + const std::string& from_name = luabind::type(lua_table["from_name"]) != LUA_TNIL ? luabind::object_cast(lua_table["from_name"]) : std::string(); + const std::string& note = luabind::type(lua_table["note"]) != LUA_TNIL ? luabind::object_cast(lua_table["note"]) : std::string(); + + auto e = CharacterParcelsRepository::NewEntity(); + + e.char_id = character_id; + e.item_id = item_id; + e.aug_slot_1 = augment_one; + e.aug_slot_2 = augment_two; + e.aug_slot_3 = augment_three; + e.aug_slot_4 = augment_four; + e.aug_slot_5 = augment_five; + e.aug_slot_6 = augment_six; + e.slot_id = next_parcel_slot; + e.quantity = quantity; + e.from_name = from_name; + e.note = note; + e.sent_date = std::time(nullptr); + + return CharacterParcelsRepository::InsertOne(database, e).id; +} + #define LuaCreateNPCParse(name, c_type, default_value) do { \ cur = table[#name]; \ if(luabind::type(cur) != LUA_TNIL) { \ @@ -6307,6 +6379,7 @@ luabind::scope lua_register_general() { luabind::def("set_auto_login_character_name_by_account_id", &lua_set_auto_login_character_name_by_account_id), luabind::def("get_zone_id_by_long_name", &lua_get_zone_id_by_long_name), luabind::def("get_zone_short_name_by_long_name", &lua_get_zone_short_name_by_long_name), + luabind::def("send_parcel", &lua_send_parcel), /* Cross Zone */