From eb104e40dee509545bd1b59064af5e5f97712e71 Mon Sep 17 00:00:00 2001 From: JJ Date: Fri, 28 Feb 2020 21:39:46 -0500 Subject: [PATCH 01/42] Update link [skip ci] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5e4f919fe..f3b829732 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ |:---:|:---:|:---:| |**Install Count**|![Windows Install Count](http://analytics.akkadius.com/?install_count&windows_count)|![Linux Install Count](http://analytics.akkadius.com/?install_count&linux_count)| ### > Windows -* [Install](https://github.com/EQEmu/Server/wiki/Windows-Server) +* [Install](https://eqemu.gitbook.io/server/categories/how-to-guides/installation/server-installation-windows) ### > Debian/Ubuntu/CentOS/Fedora * You can use curl or wget to kick off the installer (whichever your OS has) From a3eb74b855b02cb6ade8c8b3b4dc455f73f98795 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 5 Mar 2020 14:37:43 -0500 Subject: [PATCH 02/42] Fix /split while in a raid This still doesn't add support for /autosplit in a raid, how should that work? This changes the Raid::SplitMoney to take a group ID and fails when provided with RAID_GROUPLESS. This does change behavior, but I'm not sure if it was ever used so ... --- zone/client_packet.cpp | 24 ++++++++++++++++-------- zone/lua_raid.cpp | 12 ++++++------ zone/lua_raid.h | 4 ++-- zone/perl_raids.cpp | 15 ++++++++------- zone/raids.cpp | 17 +++++++++++------ zone/raids.h | 2 +- 6 files changed, 44 insertions(+), 30 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 7173dd342..1848a926c 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -13327,13 +13327,17 @@ void Client::Handle_OP_Split(const EQApplicationPacket *app) Split_Struct *split = (Split_Struct *)app->pBuffer; //Per the note above, Im not exactly sure what to do on error //to notify the client of the error... - if (!isgrouped) { - Message(Chat::Red, "You can not split money if you're not in a group."); - return; - } - Group *cgroup = GetGroup(); - if (cgroup == nullptr) { - //invalid group, not sure if we should say more... + + Group *group = nullptr; + Raid *raid = nullptr; + + if (IsRaidGrouped()) + raid = GetRaid(); + else if (IsGrouped()) + group = GetGroup(); + + // is there an actual error message for this? + if (raid == nullptr && group == nullptr) { Message(Chat::Red, "You can not split money if you're not in a group."); return; } @@ -13345,7 +13349,11 @@ void Client::Handle_OP_Split(const EQApplicationPacket *app) Message(Chat::Red, "You do not have enough money to do that split."); return; } - cgroup->SplitMoney(split->copper, split->silver, split->gold, split->platinum); + + if (raid) + raid->SplitMoney(raid->GetGroup(this), split->copper, split->silver, split->gold, split->platinum); + else if (group) + group->SplitMoney(split->copper, split->silver, split->gold, split->platinum); return; diff --git a/zone/lua_raid.cpp b/zone/lua_raid.cpp index 93c1f4c28..c181b8bd2 100644 --- a/zone/lua_raid.cpp +++ b/zone/lua_raid.cpp @@ -52,14 +52,14 @@ uint32 Lua_Raid::GetTotalRaidDamage(Lua_Mob other) { return self->GetTotalRaidDamage(other); } -void Lua_Raid::SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum) { +void Lua_Raid::SplitMoney(uint32 gid, uint32 copper, uint32 silver, uint32 gold, uint32 platinum) { Lua_Safe_Call_Void(); - self->SplitMoney(copper, silver, gold, platinum); + self->SplitMoney(gid, copper, silver, gold, platinum); } -void Lua_Raid::SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Lua_Client splitter) { +void Lua_Raid::SplitMoney(uint32 gid, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Lua_Client splitter) { Lua_Safe_Call_Void(); - self->SplitMoney(copper, silver, gold, platinum, splitter); + self->SplitMoney(gid, copper, silver, gold, platinum, splitter); } void Lua_Raid::BalanceHP(int penalty, uint32 group_id) { @@ -146,8 +146,8 @@ luabind::scope lua_register_raid() { .def("GetGroup", (int(Lua_Raid::*)(Lua_Client))&Lua_Raid::GetGroup) .def("SplitExp", (void(Lua_Raid::*)(uint32,Lua_Mob))&Lua_Raid::SplitExp) .def("GetTotalRaidDamage", (uint32(Lua_Raid::*)(Lua_Mob))&Lua_Raid::GetTotalRaidDamage) - .def("SplitMoney", (void(Lua_Raid::*)(uint32,uint32,uint32,uint32))&Lua_Raid::SplitMoney) - .def("SplitMoney", (void(Lua_Raid::*)(uint32,uint32,uint32,uint32,Lua_Client))&Lua_Raid::SplitMoney) + .def("SplitMoney", (void(Lua_Raid::*)(uint32,uint32,uint32,uint32,uint32))&Lua_Raid::SplitMoney) + .def("SplitMoney", (void(Lua_Raid::*)(uint32,uint32,uint32,uint32,uint32,Lua_Client))&Lua_Raid::SplitMoney) .def("BalanceHP", (void(Lua_Raid::*)(int,uint32))&Lua_Raid::BalanceHP) .def("IsLeader", (bool(Lua_Raid::*)(const char*))&Lua_Raid::IsLeader) .def("IsGroupLeader", (bool(Lua_Raid::*)(const char*))&Lua_Raid::IsGroupLeader) diff --git a/zone/lua_raid.h b/zone/lua_raid.h index 626b98bb2..bc10a729c 100644 --- a/zone/lua_raid.h +++ b/zone/lua_raid.h @@ -34,8 +34,8 @@ public: int GetGroup(Lua_Client c); void SplitExp(uint32 exp, Lua_Mob other); uint32 GetTotalRaidDamage(Lua_Mob other); - void SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum); - void SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Lua_Client splitter); + void SplitMoney(uint32 gid, uint32 copper, uint32 silver, uint32 gold, uint32 platinum); + void SplitMoney(uint32 gid, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Lua_Client splitter); void BalanceHP(int penalty, uint32 group_id); bool IsLeader(const char *c); bool IsLeader(Lua_Client c); diff --git a/zone/perl_raids.cpp b/zone/perl_raids.cpp index 72672de4e..670d445e5 100644 --- a/zone/perl_raids.cpp +++ b/zone/perl_raids.cpp @@ -247,13 +247,14 @@ XS(XS_Raid_SplitMoney); /* prototype to pass -Wmissing-prototypes */ XS(XS_Raid_SplitMoney) { dXSARGS; if (items != 5) - Perl_croak(aTHX_ "Usage: Raid::SplitMoney(THIS, uint32 copper, uint32 silver, uint32 gold, uint32 platinum)"); + Perl_croak(aTHX_ "Usage: Raid::SplitMoney(THIS, uint32 gid, uint32 copper, uint32 silver, uint32 gold, uint32 platinum)"); { Raid *THIS; - uint32 copper = (uint32) SvUV(ST(1)); - uint32 silver = (uint32) SvUV(ST(2)); - uint32 gold = (uint32) SvUV(ST(3)); - uint32 platinum = (uint32) SvUV(ST(4)); + uint32 gid = (uint32) SvUV(ST(1)); + uint32 copper = (uint32) SvUV(ST(2)); + uint32 silver = (uint32) SvUV(ST(3)); + uint32 gold = (uint32) SvUV(ST(4)); + uint32 platinum = (uint32) SvUV(ST(5)); if (sv_derived_from(ST(0), "Raid")) { IV tmp = SvIV((SV *) SvRV(ST(0))); @@ -263,7 +264,7 @@ XS(XS_Raid_SplitMoney) { if (THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - THIS->SplitMoney(copper, silver, gold, platinum); + THIS->SplitMoney(gid, copper, silver, gold, platinum); } XSRETURN_EMPTY; } @@ -569,7 +570,7 @@ XS(boot_Raid) { newXSproto(strcpy(buf, "GetGroup"), XS_Raid_GetGroup, file, "$$"); newXSproto(strcpy(buf, "SplitExp"), XS_Raid_SplitExp, file, "$$$"); newXSproto(strcpy(buf, "GetTotalRaidDamage"), XS_Raid_GetTotalRaidDamage, file, "$$"); - newXSproto(strcpy(buf, "SplitMoney"), XS_Raid_SplitMoney, file, "$$$$$"); + newXSproto(strcpy(buf, "SplitMoney"), XS_Raid_SplitMoney, file, "$$$$$$"); newXSproto(strcpy(buf, "BalanceHP"), XS_Raid_BalanceHP, file, "$$$"); newXSproto(strcpy(buf, "IsLeader"), XS_Raid_IsLeader, file, "$$"); newXSproto(strcpy(buf, "IsGroupLeader"), XS_Raid_IsGroupLeader, file, "$$"); diff --git a/zone/raids.cpp b/zone/raids.cpp index 7a153864d..a4e1535d3 100644 --- a/zone/raids.cpp +++ b/zone/raids.cpp @@ -728,15 +728,20 @@ void Raid::BalanceMana(int32 penalty, uint32 gid, float range, Mob* caster, int3 } //basically the same as Group's version just with more people like a lot of non group specific raid stuff -void Raid::SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter){ +//this only functions if the member has a group in the raid. This does not support /autosplit? +void Raid::SplitMoney(uint32 gid, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter) +{ //avoid unneeded work + if (gid == RAID_GROUPLESS) + return; + if(copper == 0 && silver == 0 && gold == 0 && platinum == 0) return; uint32 i; uint8 membercount = 0; for (i = 0; i < MAX_RAID_MEMBERS; i++) { - if (members[i].member != nullptr) { + if (members[i].member != nullptr && members[i].GroupNumber == gid) { membercount++; } } @@ -809,11 +814,11 @@ void Raid::SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum msg += " as your split"; for (i = 0; i < MAX_RAID_MEMBERS; i++) { - if (members[i].member != nullptr) { // If Group Member is Client - //I could not get MoneyOnCorpse to work, so we use this - members[i].member->AddMoneyToPP(cpsplit, spsplit, gpsplit, ppsplit, true); + if (members[i].member != nullptr && members[i].GroupNumber == gid) { // If Group Member is Client + //I could not get MoneyOnCorpse to work, so we use this + members[i].member->AddMoneyToPP(cpsplit, spsplit, gpsplit, ppsplit, true); - members[i].member->Message(Chat::Green, msg.c_str()); + members[i].member->Message(Chat::Green, msg.c_str()); } } } diff --git a/zone/raids.h b/zone/raids.h index 260ae6c71..26ba90a02 100644 --- a/zone/raids.h +++ b/zone/raids.h @@ -159,7 +159,7 @@ public: void BalanceHP(int32 penalty, uint32 gid, float range = 0, Mob* caster = nullptr, int32 limit = 0); void BalanceMana(int32 penalty, uint32 gid, float range = 0, Mob* caster = nullptr, int32 limit = 0); void HealGroup(uint32 heal_amt, Mob* caster, uint32 gid, float range = 0); - void SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter = nullptr); + void SplitMoney(uint32 gid, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter = nullptr); void GroupBardPulse(Mob* caster, uint16 spellid, uint32 gid); void TeleportGroup(Mob* sender, uint32 zoneID, uint16 instance_id, float x, float y, float z, float heading, uint32 gid); From 4915e86abaee2a35b38a035a350b2a8833f2c538 Mon Sep 17 00:00:00 2001 From: JJ Date: Thu, 5 Mar 2020 22:31:54 -0500 Subject: [PATCH 03/42] Slight tweak (field name) to #983 "Override LEVEL and INT aggro blocking". If you already ran the previous SQL, use this instead: ALTER TABLE `npc_types` CHANGE `always_aggros_foes` `always_aggro` TINYINT(1) NOT NULL DEFAULT '0'; --- utils/sql/db_update_manifest.txt | 2 +- utils/sql/git/required/2020_03_05_npc_always_aggro.sql | 2 +- zone/aggro.cpp | 10 +++++----- zone/corpse.cpp | 2 +- zone/mob.cpp | 4 ++-- zone/mob.h | 4 ++-- zone/npc.cpp | 2 +- zone/zonedb.cpp | 4 ++-- zone/zonedump.h | 2 +- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index ca7a29f25..9be222856 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -404,7 +404,7 @@ 9148|2020_01_28_corpse_guild_consent_id.sql|SHOW COLUMNS FROM `character_corpses` LIKE 'guild_consent_id'|empty| 9149|2020_02_06_globalloot.sql|SHOW COLUMNS FROM `global_loot` LIKE 'hot_zone'|empty| 9150|2020_02_06_aa_reset_on_death.sql|SHOW COLUMNS FROM `aa_ability` LIKE 'reset_on_death'|empty| -9151|2020_03_05_npc_always_aggro.sql|SHOW COLUMNS FROM `npc_types` LIKE 'always_aggros_foes'|empty| +9151|2020_03_05_npc_always_aggro.sql|SHOW COLUMNS FROM `npc_types` LIKE 'always_aggro'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2020_03_05_npc_always_aggro.sql b/utils/sql/git/required/2020_03_05_npc_always_aggro.sql index d9e6351a3..83641998c 100644 --- a/utils/sql/git/required/2020_03_05_npc_always_aggro.sql +++ b/utils/sql/git/required/2020_03_05_npc_always_aggro.sql @@ -1 +1 @@ -ALTER TABLE `npc_types` ADD COLUMN `always_aggros_foes` tinyint(4) NOT NULL DEFAULT 0; +ALTER TABLE `npc_types` ADD COLUMN `always_aggro` tinyint(1) NOT NULL DEFAULT 0; diff --git a/zone/aggro.cpp b/zone/aggro.cpp index fac15457e..87b98d599 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -139,7 +139,7 @@ void NPC::DescribeAggro(Client *towho, Mob *mob, bool verbose) { if (RuleB(Aggro, UseLevelAggro)) { - if (GetLevel() < RuleI(Aggro, MinAggroLevel) && mob->GetLevelCon(GetLevel()) == CON_GRAY && GetBodyType() != 3 && !AlwaysAggrosFoes()) + if (GetLevel() < RuleI(Aggro, MinAggroLevel) && mob->GetLevelCon(GetLevel()) == CON_GRAY && GetBodyType() != 3 && !AlwaysAggro()) { towho->Message(Chat::White, "...%s is red to me (basically)", mob->GetName(), dist2, iAggroRange2); return; @@ -147,7 +147,7 @@ void NPC::DescribeAggro(Client *towho, Mob *mob, bool verbose) { } else { - if(GetINT() > RuleI(Aggro, IntAggroThreshold) && mob->GetLevelCon(GetLevel()) == CON_GRAY && !AlwaysAggrosFoes()) { + if(GetINT() > RuleI(Aggro, IntAggroThreshold) && mob->GetLevelCon(GetLevel()) == CON_GRAY && !AlwaysAggro()) { towho->Message(Chat::White, "...%s is red to me (basically)", mob->GetName(), dist2, iAggroRange2); return; @@ -318,7 +318,7 @@ bool Mob::CheckWillAggro(Mob *mob) { //old InZone check taken care of above by !mob->CastToClient()->Connected() ( ( GetLevel() >= RuleI(Aggro, MinAggroLevel)) - ||(GetBodyType() == 3) || AlwaysAggrosFoes() + ||(GetBodyType() == 3) || AlwaysAggro() ||( mob->IsClient() && mob->CastToClient()->IsSitting() ) ||( mob->GetLevelCon(GetLevel()) != CON_GRAY) @@ -352,7 +352,7 @@ bool Mob::CheckWillAggro(Mob *mob) { //old InZone check taken care of above by !mob->CastToClient()->Connected() ( ( GetINT() <= RuleI(Aggro, IntAggroThreshold) ) - || AlwaysAggrosFoes() + || AlwaysAggro() ||( mob->IsClient() && mob->CastToClient()->IsSitting() ) ||( mob->GetLevelCon(GetLevel()) != CON_GRAY) @@ -384,7 +384,7 @@ bool Mob::CheckWillAggro(Mob *mob) { LogAggro("Dist^2: [{}]\n", dist2); LogAggro("Range^2: [{}]\n", iAggroRange2); LogAggro("Faction: [{}]\n", fv); - LogAggro("AlwaysAggroFlag: [{}]\n", AlwaysAggrosFoes()); + LogAggro("AlwaysAggroFlag: [{}]\n", AlwaysAggro()); LogAggro("Int: [{}]\n", GetINT()); LogAggro("Con: [{}]\n", GetLevelCon(mob->GetLevel())); diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 5858d5acc..fd4174868 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -262,7 +262,7 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( 0, // uint8 in_legtexture, 0, // uint8 in_feettexture, 0, // uint8 in_usemodel, - 0 // bool in_always_aggros_foes + 0 // bool in_always_aggro ), corpse_decay_timer(RuleI(Character, CorpseDecayTimeMS)), corpse_rez_timer(RuleI(Character, CorpseResTimeMS)), diff --git a/zone/mob.cpp b/zone/mob.cpp index 2e3d3d290..5d25c42f0 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -94,7 +94,7 @@ Mob::Mob( uint8 in_legtexture, uint8 in_feettexture, uint16 in_usemodel, - bool in_always_aggros_foes + bool in_always_aggro ) : attack_timer(2000), attack_dw_timer(2000), @@ -276,7 +276,7 @@ Mob::Mob( qglobal = 0; spawned = false; rare_spawn = false; - always_aggros_foes = in_always_aggros_foes; + always_aggro = in_always_aggro; InitializeBuffSlots(); diff --git a/zone/mob.h b/zone/mob.h index 2a89ba384..f1c128080 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -579,7 +579,7 @@ public: inline const GravityBehavior GetFlyMode() const { return flymode; } bool IsBoat() const; bool IsControllableBoat() const; - inline const bool AlwaysAggrosFoes() const { return always_aggros_foes; } + inline const bool AlwaysAggro() const { return always_aggro; } //Group virtual bool HasRaid() = 0; @@ -1391,7 +1391,7 @@ protected: Timer ranged_timer; float attack_speed; //% increase/decrease in attack speed (not haste) int attack_delay; //delay between attacks in 10ths of seconds - bool always_aggros_foes; + bool always_aggro; int16 slow_mitigation; // Allows for a slow mitigation (100 = 100%, 50% = 50%) Timer tic_timer; Timer mana_timer; diff --git a/zone/npc.cpp b/zone/npc.cpp index 307e7a926..6df237d5d 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -114,7 +114,7 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi npc_type_data->legtexture, npc_type_data->feettexture, npc_type_data->use_model, - npc_type_data->always_aggros_foes + npc_type_data->always_aggro ), attacked_timer(CombatEventTimer_expire), swarm_timer(100), diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 3b03d2563..cad4e1df8 100755 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2507,7 +2507,7 @@ const NPCType *ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load "npc_types.stuck_behavior, " "npc_types.model, " "npc_types.flymode, " - "npc_types.always_aggros_foes " + "npc_types.always_aggro " "FROM npc_types %s", where_condition.c_str() ); @@ -2709,7 +2709,7 @@ const NPCType *ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load temp_npctype_data->stuck_behavior = atoi(row[109]); temp_npctype_data->use_model = atoi(row[110]); temp_npctype_data->flymode = atoi(row[111]); - temp_npctype_data->always_aggros_foes = atoi(row[112]); + temp_npctype_data->always_aggro = atoi(row[112]); temp_npctype_data->skip_auto_scale = false; // hardcoded here for now diff --git a/zone/zonedump.h b/zone/zonedump.h index 80508f233..0a1bcd07d 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -147,7 +147,7 @@ struct NPCType int8 stuck_behavior; uint16 use_model; int8 flymode; - bool always_aggros_foes; + bool always_aggro; }; namespace player_lootitem { From 581d5b1289962960946a62caae4759325ac85d8e Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 7 Mar 2020 18:58:12 -0500 Subject: [PATCH 04/42] Deleted characters will no longer show in the guild window. --- common/guild_base.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/common/guild_base.cpp b/common/guild_base.cpp index 642db7cbc..b7ac8515c 100644 --- a/common/guild_base.cpp +++ b/common/guild_base.cpp @@ -912,7 +912,7 @@ bool BaseGuildManager::GetEntireGuild(uint32 guild_id, std::vectorQueryDatabase(query); if (!results.Success()) { return false; @@ -941,7 +941,7 @@ bool BaseGuildManager::GetCharInfo(const char *char_name, CharGuildInfo &into) { m_db->DoEscapeString(esc, char_name, nl); //load up the rank info for each guild. - std::string query = StringFormat(GuildMemberBaseQuery " WHERE c.name='%s'", esc); + std::string query = StringFormat(GuildMemberBaseQuery " WHERE c.name='%s' AND c.deleted_at IS NULL", esc); safe_delete_array(esc); auto results = m_db->QueryDatabase(query); if (!results.Success()) { @@ -969,9 +969,9 @@ bool BaseGuildManager::GetCharInfo(uint32 char_id, CharGuildInfo &into) { //load up the rank info for each guild. std::string query; #ifdef BOTS - query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.mob_type = 'C'", char_id); + query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.mob_type = 'C' AND c.deleted_at IS NULL", char_id); #else - query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d", char_id); + query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.deleted_at IS NULL", char_id); #endif auto results = m_db->QueryDatabase(query); if (!results.Success()) { From 1b15ee141d77efc91725a0c5fe7a68a8734aba29 Mon Sep 17 00:00:00 2001 From: regneq Date: Sat, 7 Mar 2020 18:38:38 -0800 Subject: [PATCH 05/42] Faction always conned indifferent in no combat zone such as PoK, Nexus, etc regardless of faction level as evident with Planar Traveler's Manual (faction modifier) and restocking high quality ore (faction reward) in Bazaar and PoK. --- zone/client.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zone/client.cpp b/zone/client.cpp index 8b60b391a..8c4b42957 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -7797,6 +7797,8 @@ FACTION_VALUE Client::GetFactionLevel(uint32 char_id, uint32 npc_id, uint32 p_ra // few optimizations if (GetFeigned()) return FACTION_INDIFFERENT; + if(!zone->CanDoCombat()) + return FACTION_INDIFFERENT; if (invisible_undead && tnpc && !tnpc->SeeInvisibleUndead()) return FACTION_INDIFFERENT; if (IsInvisible(tnpc)) From 2a9248697ef1eeefcc7b1647d2c51612e1fa7a8d Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 8 Mar 2020 10:38:28 -0400 Subject: [PATCH 06/42] Add GetGroupIDByCharID and GetGuildIDByCharID to Perl/Lua. --- common/database.cpp | 22 ++++++++++++++++++++++ common/database.h | 1 + zone/embparser_api.cpp | 37 +++++++++++++++++++++++++++++++++++++ zone/lua_general.cpp | 10 ++++++++++ zone/questmgr.cpp | 14 ++++++++++++++ zone/questmgr.h | 2 ++ 6 files changed, 86 insertions(+) diff --git a/common/database.cpp b/common/database.cpp index 352ecbbc1..9c846b260 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2158,6 +2158,28 @@ uint32 Database::GetGuildIDByCharID(uint32 character_id) return atoi(row[0]); } +uint32 Database::GetGroupIDByCharID(uint32 character_id) +{ + std::string query = fmt::format( + SQL( + SELECT groupid + FROM group_id + WHERE charid = '{}' + ), + character_id + ); + auto results = QueryDatabase(query); + + if (!results.Success()) + return 0; + + if (results.RowCount() == 0) + return 0; + + auto row = results.begin(); + return atoi(row[0]); +} + /** * @param log_settings */ diff --git a/common/database.h b/common/database.h index f569da20b..4b9391d31 100644 --- a/common/database.h +++ b/common/database.h @@ -133,6 +133,7 @@ public: uint32 GetCharacterID(const char *name); uint32 GetCharacterInfo(const char* iName, uint32* oAccID = 0, uint32* oZoneID = 0, uint32* oInstanceID = 0, float* oX = 0, float* oY = 0, float* oZ = 0); uint32 GetGuildIDByCharID(uint32 char_id); + uint32 GetGroupIDByCharID(uint32 char_id); void GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID = 0); void GetCharName(uint32 char_id, char* name); diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 871cc0ced..8a68b0fe3 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -3169,6 +3169,41 @@ XS(XS__getguildnamebyid) { XSRETURN(1); } +XS(XS__getguildidbycharid); +XS(XS__getguildidbycharid) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: quest::getguildidbycharid(uint32 char_id)"); + dXSTARG; + + int RETVAL; + uint32 char_id = (int) SvUV(ST(0)); + + RETVAL = quest_manager.getguildidbycharid(char_id); + + XSprePUSH; + PUSHi((IV)RETVAL); + + XSRETURN(1); +} + +XS(XS__getgroupidbycharid); +XS(XS__getgroupidbycharid) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: quest::getgroupidbycharid(uint32 char_id)"); + dXSTARG; + + int RETVAL; + uint32 char_id = (int) SvUV(ST(0)); + + RETVAL = quest_manager.getgroupidbycharid(char_id); + XSprePUSH; + PUSHi((IV)RETVAL); + + XSRETURN(1); +} + XS(XS__SetRunning); XS(XS__SetRunning) { dXSARGS; @@ -3942,6 +3977,8 @@ EXTERN_C XS(boot_quest) { newXS(strcpy(buf, "getItemName"), XS_qc_getItemName, file); newXS(strcpy(buf, "get_spawn_condition"), XS__get_spawn_condition, file); newXS(strcpy(buf, "getguildnamebyid"), XS__getguildnamebyid, file); + newXS(strcpy(buf, "getguildidbycharid"), XS__getguildidbycharid, file); + newXS(strcpy(buf, "getgroupidbycharid"), XS__getgroupidbycharid, file); newXS(strcpy(buf, "getlevel"), XS__getlevel, file); newXS(strcpy(buf, "getplayerburiedcorpsecount"), XS__getplayerburiedcorpsecount, file); newXS(strcpy(buf, "getplayercorpsecount"), XS__getplayercorpsecount, file); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 0d1086ad1..cc60664b5 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -858,6 +858,14 @@ const char *lua_get_guild_name_by_id(uint32 guild_id) { return quest_manager.getguildnamebyid(guild_id); } +int lua_get_guild_id_by_char_id(uint32 char_id) { + return database.GetGuildIDByCharID(char_id); +} + +int lua_get_group_id_by_char_id(uint32 char_id) { + return database.GetGroupIDByCharID(char_id); +} + uint32 lua_create_instance(const char *zone, uint32 version, uint32 duration) { return quest_manager.CreateInstance(zone, version, duration); } @@ -1728,6 +1736,8 @@ luabind::scope lua_register_general() { luabind::def("set_data", (void(*)(std::string, std::string, std::string))&lua_set_data), luabind::def("delete_data", (bool(*)(std::string))&lua_delete_data), luabind::def("get_guild_name_by_id", &lua_get_guild_name_by_id), + luabind::def("get_guild_id_by_char_id", &lua_get_guild_id_by_char_id), + luabind::def("get_group_id_by_char_id", &lua_get_group_id_by_char_id), luabind::def("create_instance", &lua_create_instance), luabind::def("destroy_instance", &lua_destroy_instance), luabind::def("update_instance_timer", &lua_update_instance_timer), diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index bea136e28..4b2eb432f 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2876,6 +2876,20 @@ const char* QuestManager::getguildnamebyid(int guild_id) { return(""); } +int QuestManager::getguildidbycharid(uint32 char_id) { + if (char_id > 0) { + return database.GetGuildIDByCharID(char_id); + } + return 0; +} + +int QuestManager::getgroupidbycharid(uint32 char_id) { + if (char_id > 0) { + return database.GetGroupIDByCharID(char_id); + } + return 0; +} + void QuestManager::SetRunning(bool val) { QuestManagerCurrentQuestVars(); diff --git a/zone/questmgr.h b/zone/questmgr.h index 5ad551c43..53b425bd0 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -251,6 +251,8 @@ public: const char* varlink(char* perltext, int item_id); std::string saylink(char *saylink_text, bool silent, const char *link_name); const char* getguildnamebyid(int guild_id); + int getguildidbycharid(uint32 char_id); + int getgroupidbycharid(uint32 char_id); void SetRunning(bool val); bool IsRunning(); void FlyMode(GravityBehavior flymode); From cede38f5624a8409f4382af8027b8f34b179f1c4 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 8 Mar 2020 21:11:56 -0400 Subject: [PATCH 07/42] Add GetRaidIDByCharID to Perl/Lua. --- common/database.cpp | 16 ++++++++++++++++ common/database.h | 1 + zone/embparser_api.cpp | 18 ++++++++++++++++++ zone/lua_general.cpp | 5 +++++ zone/questmgr.cpp | 7 +++++++ zone/questmgr.h | 1 + 6 files changed, 48 insertions(+) diff --git a/common/database.cpp b/common/database.cpp index 9c846b260..3f64a21f9 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2180,6 +2180,22 @@ uint32 Database::GetGroupIDByCharID(uint32 character_id) return atoi(row[0]); } +uint32 Database::GetRaidIDByCharID(uint32 character_id) { + std::string query = fmt::format( + SQL( + SELECT raidid + FROM raid_members + WHERE charid = '{}' + ), + character_id + ); + auto results = QueryDatabase(query); + for (auto row = results.begin(); row != results.end(); ++row) { + return atoi(row[0]); + } + return 0; +} + /** * @param log_settings */ diff --git a/common/database.h b/common/database.h index 4b9391d31..95458c1c1 100644 --- a/common/database.h +++ b/common/database.h @@ -134,6 +134,7 @@ public: uint32 GetCharacterInfo(const char* iName, uint32* oAccID = 0, uint32* oZoneID = 0, uint32* oInstanceID = 0, float* oX = 0, float* oY = 0, float* oZ = 0); uint32 GetGuildIDByCharID(uint32 char_id); uint32 GetGroupIDByCharID(uint32 char_id); + uint32 GetRaidIDByCharID(uint32 char_id); void GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID = 0); void GetCharName(uint32 char_id, char* name); diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 8a68b0fe3..efdc09803 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -3204,6 +3204,23 @@ XS(XS__getgroupidbycharid) { XSRETURN(1); } +XS(XS__getraididbycharid); +XS(XS__getraididbycharid) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: quest::getraididbycharid(uint32 char_id)"); + dXSTARG; + + int RETVAL; + uint32 char_id = (int) SvUV(ST(0)); + + RETVAL = quest_manager.getraididbycharid(char_id); + XSprePUSH; + PUSHi((IV)RETVAL); + + XSRETURN(1); +} + XS(XS__SetRunning); XS(XS__SetRunning) { dXSARGS; @@ -3979,6 +3996,7 @@ EXTERN_C XS(boot_quest) { newXS(strcpy(buf, "getguildnamebyid"), XS__getguildnamebyid, file); newXS(strcpy(buf, "getguildidbycharid"), XS__getguildidbycharid, file); newXS(strcpy(buf, "getgroupidbycharid"), XS__getgroupidbycharid, file); + newXS(strcpy(buf, "getraididbycharid"), XS__getraididbycharid, file); newXS(strcpy(buf, "getlevel"), XS__getlevel, file); newXS(strcpy(buf, "getplayerburiedcorpsecount"), XS__getplayerburiedcorpsecount, file); newXS(strcpy(buf, "getplayercorpsecount"), XS__getplayercorpsecount, file); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index cc60664b5..69e262199 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -866,6 +866,10 @@ int lua_get_group_id_by_char_id(uint32 char_id) { return database.GetGroupIDByCharID(char_id); } +int lua_get_raid_id_by_char_id(uint32 char_id) { + return database.GetRaidIDByCharID(char_id); +} + uint32 lua_create_instance(const char *zone, uint32 version, uint32 duration) { return quest_manager.CreateInstance(zone, version, duration); } @@ -1738,6 +1742,7 @@ luabind::scope lua_register_general() { luabind::def("get_guild_name_by_id", &lua_get_guild_name_by_id), luabind::def("get_guild_id_by_char_id", &lua_get_guild_id_by_char_id), luabind::def("get_group_id_by_char_id", &lua_get_group_id_by_char_id), + luabind::def("get_raid_id_by_char_id", &lua_get_raid_id_by_char_id), luabind::def("create_instance", &lua_create_instance), luabind::def("destroy_instance", &lua_destroy_instance), luabind::def("update_instance_timer", &lua_update_instance_timer), diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 4b2eb432f..033b42f1a 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2890,6 +2890,13 @@ int QuestManager::getgroupidbycharid(uint32 char_id) { return 0; } +int QuestManager::getraididbycharid(uint32 char_id) { + if (char_id > 0) { + return database.GetRaidIDByCharID(char_id); + } + return 0; +} + void QuestManager::SetRunning(bool val) { QuestManagerCurrentQuestVars(); diff --git a/zone/questmgr.h b/zone/questmgr.h index 53b425bd0..2aa1df109 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -253,6 +253,7 @@ public: const char* getguildnamebyid(int guild_id); int getguildidbycharid(uint32 char_id); int getgroupidbycharid(uint32 char_id); + int getraididbycharid(uint32 char_id); void SetRunning(bool val); bool IsRunning(); void FlyMode(GravityBehavior flymode); From 8d252dfd9aac41699177b776e7f1636ec43b867f Mon Sep 17 00:00:00 2001 From: Chris Miles Date: Mon, 9 Mar 2020 03:00:07 -0500 Subject: [PATCH 08/42] Implement database dump service --- common/CMakeLists.txt | 4 + common/cli/eqemu_command_handler.cpp | 2 +- common/database/database_dump_service.h | 77 ++++++++++++++++ common/file_util.cpp | 67 ++++++++++++++ common/file_util.h | 32 +++++++ utils/sql/character_table_list.txt | 57 ------------ utils/sql/data_tables.txt | 6 -- utils/sql/system_tables.txt | 113 ------------------------ utils/sql/user_tables.txt | 94 -------------------- world/world_server_command_handler.cpp | 62 ++++++++++++- world/world_server_command_handler.h | 1 + 11 files changed, 243 insertions(+), 272 deletions(-) create mode 100644 common/database/database_dump_service.h create mode 100644 common/file_util.cpp create mode 100644 common/file_util.h delete mode 100644 utils/sql/character_table_list.txt delete mode 100644 utils/sql/data_tables.txt delete mode 100644 utils/sql/system_tables.txt delete mode 100644 utils/sql/user_tables.txt diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index a959d9093..e312c202d 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -9,6 +9,7 @@ SET(common_sources crash.cpp crc16.cpp crc32.cpp + database/database_dump_service.cpp database.cpp database_conversions.cpp database_instances.cpp @@ -31,6 +32,7 @@ SET(common_sources event_sub.cpp extprofile.cpp faction.cpp + file_util.cpp guild_base.cpp guilds.cpp inventory_profile.cpp @@ -120,6 +122,7 @@ SET(common_headers cli/argh.h cli/eqemu_command_handler.h cli/terminal_color.hpp + database/database_dump_service.h data_verification.h database.h database_schema.h @@ -150,6 +153,7 @@ SET(common_headers event_sub.h extprofile.h faction.h + file_util.h features.h fixed_memory_hash_set.h fixed_memory_variable_hash_set.h diff --git a/common/cli/eqemu_command_handler.cpp b/common/cli/eqemu_command_handler.cpp index bbcdb4612..96ed5a155 100644 --- a/common/cli/eqemu_command_handler.cpp +++ b/common/cli/eqemu_command_handler.cpp @@ -96,7 +96,7 @@ namespace EQEmuCommand { "\nCommand" << termcolor::reset << "\n\n" << termcolor::green << argv[1] << arguments_string << termcolor::reset << "\n" << - termcolor::yellow << (!options_string.empty() ? "\nOptions\n" : "") << + termcolor::yellow << (!options_string.empty() ? "\nOptions\n\n" : "") << termcolor::reset << termcolor::cyan << options_string << termcolor::reset; std::cout << command_string.str() << std::endl; diff --git a/common/database/database_dump_service.h b/common/database/database_dump_service.h new file mode 100644 index 000000000..096d4c5d3 --- /dev/null +++ b/common/database/database_dump_service.h @@ -0,0 +1,77 @@ +/** + * 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 + * +*/ + +#ifndef EQEMU_DATABASE_DUMP_SERVICE_H +#define EQEMU_DATABASE_DUMP_SERVICE_H + + +class DatabaseDumpService { +public: + void Dump(); + bool IsDumpAllTables() const; + void SetDumpAllTables(bool dump_all_tables); + bool IsDumpWithNoData() const; + void SetDumpWithNoData(bool dump_with_no_data); + bool IsDumpSystemTables() const; + void SetDumpSystemTables(bool dump_system_tables); + bool IsDumpContentTables() const; + void SetDumpContentTables(bool dump_content_tables); + bool IsDumpPlayerTables() const; + void SetDumpPlayerTables(bool dump_player_tables); + bool IsDumpLoginServerTables() const; + void SetDumpLoginServerTables(bool dump_login_server_tables); + bool IsDumpNoTableLock() const; + void SetDumpNoTableLock(bool dump_no_table_lock); + bool IsDumpWithCompression() const; + void SetDumpWithCompression(bool dump_with_compression); + const std::string &GetDumpPath() const; + void SetDumpPath(const std::string &dump_path); + const std::string &GetDumpFileName() const; + void SetDumpFileName(const std::string &dump_file_name); + +private: + bool dump_all_tables; + bool dump_system_tables; + bool dump_content_tables; + bool dump_player_tables; + bool dump_login_server_tables; + bool dump_with_no_data; + bool dump_no_table_lock; + bool dump_with_compression; + std::string dump_path; + std::string dump_file_name; + + std::string execute(const std::string &cmd, bool return_result); + bool IsMySQLInstalled(); + std::string GetMySQLVersion(); + std::string GetBaseMySQLDumpCommand(); + std::string GetPlayerTablesList(); + std::string GetSystemTablesList(); + std::string GetContentTablesList(); + std::string GetLoginTableList(); + bool IsTarAvailable(); + bool IsRarAvailable(); + bool HasCompressionBinary(); + std::string GetDumpFileNameWithPath(); + std::string GetSetDumpPath(); +}; + + +#endif //EQEMU_DATABASE_DUMP_SERVICE_H diff --git a/common/file_util.cpp b/common/file_util.cpp new file mode 100644 index 000000000..8c9aca9a4 --- /dev/null +++ b/common/file_util.cpp @@ -0,0 +1,67 @@ +/** + * 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 +#include "file_util.h" + +#ifdef _WINDOWS +#include +#include +#include +#include +#include +#include +#else + +#include +#include + +#endif + +/** + * @param name + * @return + */ +bool FileUtil::exists(const std::string &name) +{ + std::ifstream f(name.c_str()); + + return f.good(); +} + +/** + * @param directory_name + */ +void FileUtil::mkdir(const std::string& directory_name) +{ + +#ifdef _WINDOWS + struct _stat st; + if (_stat(directory_name.c_str(), &st) == 0) // exists + return; + _mkdir(directory_name.c_str()); +#else + struct stat st{}; + if (stat(directory_name.c_str(), &st) == 0) { // exists + return; + } + ::mkdir(directory_name.c_str(), 0755); +#endif +} \ No newline at end of file diff --git a/common/file_util.h b/common/file_util.h new file mode 100644 index 000000000..05869d303 --- /dev/null +++ b/common/file_util.h @@ -0,0 +1,32 @@ +/** + * 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 + * +*/ + +#ifndef EQEMU_FILE_UTIL_H +#define EQEMU_FILE_UTIL_H + + +class FileUtil { +public: + static bool exists(const std::string &name); + static void mkdir(const std::string& directory_name); +}; + + +#endif //EQEMU_FILE_UTIL_H diff --git a/utils/sql/character_table_list.txt b/utils/sql/character_table_list.txt deleted file mode 100644 index ab6610dab..000000000 --- a/utils/sql/character_table_list.txt +++ /dev/null @@ -1,57 +0,0 @@ -account -account_ip -account_flags -account_rewards -adventure_details -adventure_stats -buyer -char_recipe_list -character_activities -character_alt_currency -character_alternate_abilities -character_auras -character_bandolier -character_bind -character_buffs -character_corpse_items -character_corpses -character_currency -character_data -character_disciplines -character_enabledtasks -character_inspect_messages -character_item_recast -character_languages -character_leadership_abilities -character_material -character_memmed_spells -character_pet_buffs -character_pet_info -character_pet_inventory -character_potionbelt -character_skills -character_spells -character_tasks -character_tribute -completed_tasks -data_buckets -faction_values -friends -guild_bank -guild_members -guild_ranks -guild_relations -guilds -instance_list_player -inventory -inventory_snapshots -keyring -mail -player_titlesets -quest_globals -sharedbank -timers -titles -trader -trader_audit -zone_flags" \ No newline at end of file diff --git a/utils/sql/data_tables.txt b/utils/sql/data_tables.txt deleted file mode 100644 index 8738c716b..000000000 --- a/utils/sql/data_tables.txt +++ /dev/null @@ -1,6 +0,0 @@ -command_settings -inventory_versions -launcher -rule_sets -rule_values -variables \ No newline at end of file diff --git a/utils/sql/system_tables.txt b/utils/sql/system_tables.txt deleted file mode 100644 index a33605130..000000000 --- a/utils/sql/system_tables.txt +++ /dev/null @@ -1,113 +0,0 @@ -aa_ability -aa_actions -aa_effects -aa_rank_effects -aa_rank_prereqs -aa_ranks -aa_required_level_cost -adventure_template -adventure_template_entry -adventure_template_entry_flavor -altadv_vars -alternate_currency -auras -base_data -blocked_spells -books -bug_reports -char_create_combinations -char_create_point_allocations -class_skill -damageshieldtypes -data_buckets -db_str -doors -eqtime -faction_base_data -faction_list -faction_list_mod -fear_hints -fishing -forage -global_loot -goallists -graveyard -grid -grid_entries -ground_spawns -horses -instance_list -items -ip_exemptions -ldon_trap_entries -ldon_trap_templates -level_exp_mods -logsys_categories -lootdrop -lootdrop_entries -loottable -loottable_entries -merc_armorinfo -merc_buffs -merc_inventory -merc_merchant_entries -merc_merchant_template_entries -merc_merchant_templates -merc_name_types -merc_npc_types -merc_spell_list_entries -merc_spell_lists -merc_stance_entries -merc_stats -merc_subtypes -merc_templates -merc_types -merc_weaponinfo -merchantlist -mercs -name_filter -npc_emotes -npc_faction -npc_faction_entries -npc_scale_global_base -npc_spells -npc_spells_effects -npc_spells_effects_entries -npc_spells_entries -npc_types -npc_types_metadata -npc_types_tint -object -perl_event_export_settings -pets -pets_equipmentset -pets_equipmentset_entries -profanity_list -proximities -races -saylink -skill_caps -spawn2 -spawn_condition_values -spawn_conditions -spawn_events -spawnentry -spawngroup -spells_new -start_zones -starting_items -task_activities -tasks -tasksets -titles -tradeskill_recipe -tradeskill_recipe_entries -traps -tribute_levels -tributes -veteran_reward_templates -zone -zone_points -zone_server -zone_state_dump -zoneserver_auth diff --git a/utils/sql/user_tables.txt b/utils/sql/user_tables.txt deleted file mode 100644 index ee19fe472..000000000 --- a/utils/sql/user_tables.txt +++ /dev/null @@ -1,94 +0,0 @@ -aa_timers -account -account_flags -account_ip -account_rewards -adventure_details -adventure_members -adventure_stats -banned_ips -bugs -buyer -char_recipe_list -character_activities -character_alt_currency -character_alternate_abilities -character_auras -character_bandolier -character_bind -character_buffs -character_corpse_items -character_corpses -character_currency -character_data -character_disciplines -character_enabledtasks -character_inspect_messages -character_item_recast -character_languages -character_leadership_abilities -character_material -character_memmed_spells -character_pet_buffs -character_pet_info -character_pet_inventory -character_potionbelt -character_skills -character_spells -character_tasks -character_tribute -chatchannels -completed_tasks -discovered_items -eventlog -faction_values -friends -gm_ips -group_id -group_leaders -guild_bank -guild_members -guild_ranks -guild_relations -guilds -hackers -instance_list_player -inventory -inventory_snapshots -item_tick -keyring -launcher_zones -lfguild -mail -merchantlist_temp -object_contents -petitions -player_titlesets -qs_merchant_transaction_record -qs_merchant_transaction_record_entries -qs_player_aa_rate_hourly -qs_player_delete_record -qs_player_delete_record_entries -qs_player_events -qs_player_handin_record -qs_player_handin_record_entries -qs_player_move_record -qs_player_move_record_entries -qs_player_npc_kill_record -qs_player_npc_kill_record_entries -qs_player_speech -qs_player_trade_record -qs_player_trade_record_entries -quest_globals -raid_details -raid_leaders -raid_members -reports -respawn_times -sharedbank -spell_buckets -spell_globals -timers -trader -trader_audit -zone_flags diff --git a/world/world_server_command_handler.cpp b/world/world_server_command_handler.cpp index 3a929d89f..565277f97 100644 --- a/world/world_server_command_handler.cpp +++ b/world/world_server_command_handler.cpp @@ -24,6 +24,7 @@ #include "../common/version.h" #include "worlddb.h" #include "../common/database_schema.h" +#include "../common/database/database_dump_service.h" namespace WorldserverCommandHandler { @@ -51,6 +52,7 @@ namespace WorldserverCommandHandler { function_map["database:version"] = &WorldserverCommandHandler::DatabaseVersion; function_map["database:set-account-status"] = &WorldserverCommandHandler::DatabaseSetAccountStatus; function_map["database:schema"] = &WorldserverCommandHandler::DatabaseGetSchema; + function_map["database:dump"] = &WorldserverCommandHandler::DatabaseDump; EQEmuCommand::HandleMenu(function_map, cmd, argc, argv); } @@ -145,7 +147,7 @@ namespace WorldserverCommandHandler { */ void DatabaseGetSchema(int argc, char **argv, argh::parser &cmd, std::string &description) { - description = "Displays server database schema"; + description = "Displays server database schema"; if (cmd[{"-h", "--help"}]) { return; @@ -202,4 +204,62 @@ namespace WorldserverCommandHandler { std::cout << payload.str() << std::endl; } + /** + * @param argc + * @param argv + * @param cmd + * @param description + */ + void DatabaseDump(int argc, char **argv, argh::parser &cmd, std::string &description) + { + description = "Dumps server database tables"; + + if (cmd[{"-h", "--help"}]) { + return; + } + + std::vector arguments = {}; + std::vector options = { + "--all", + "--content-tables", + "--login-tables", + "--player-tables", + "--system-tables", + "--table-structure-only", + "--no-table-lock", + "--dump-path=", + "--compress" + }; + + + if (argc < 3) { + EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv); + return; + } + + auto database_dump_service = new DatabaseDumpService(); + bool dump_all = cmd[{"-a", "--all"}]; + + if (!cmd("--dump-path").str().empty()) { + database_dump_service->SetDumpPath(cmd("--dump-path").str()); + } + + /** + * Set Option + */ + database_dump_service->SetDumpContentTables(cmd[{"-c", "--content-tables"}] || dump_all); + database_dump_service->SetDumpLoginServerTables(cmd[{"-c", "--login-tables"}] || dump_all); + database_dump_service->SetDumpPlayerTables(cmd[{"-c", "--player-tables"}] || dump_all); + database_dump_service->SetDumpSystemTables(cmd[{"-c", "--system-tables"}] || dump_all); + database_dump_service->SetDumpWithNoData(cmd[{"-c", "--table-structure-only"}]); + database_dump_service->SetDumpAllTables(dump_all); + database_dump_service->SetDumpNoTableLock(cmd[{"--no-table-lock"}]); + database_dump_service->SetDumpWithCompression(cmd[{"--compress"}]); + + /** + * Dump + */ + database_dump_service->Dump(); + } + } \ No newline at end of file diff --git a/world/world_server_command_handler.h b/world/world_server_command_handler.h index f3d4317f2..a32a78f0f 100644 --- a/world/world_server_command_handler.h +++ b/world/world_server_command_handler.h @@ -30,6 +30,7 @@ namespace WorldserverCommandHandler { void DatabaseVersion(int argc, char **argv, argh::parser &cmd, std::string &description); void DatabaseSetAccountStatus(int argc, char **argv, argh::parser &cmd, std::string &description); void DatabaseGetSchema(int argc, char **argv, argh::parser &cmd, std::string &description); + void DatabaseDump(int argc, char **argv, argh::parser &cmd, std::string &description); }; From d4a1ea82dce70d3006c7c25c41d3001ffb0a263c Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 9 Mar 2020 03:01:59 -0500 Subject: [PATCH 09/42] Create database_dump_service.cpp --- common/database/database_dump_service.cpp | 434 ++++++++++++++++++++++ 1 file changed, 434 insertions(+) create mode 100644 common/database/database_dump_service.cpp diff --git a/common/database/database_dump_service.cpp b/common/database/database_dump_service.cpp new file mode 100644 index 000000000..68608bd67 --- /dev/null +++ b/common/database/database_dump_service.cpp @@ -0,0 +1,434 @@ +/** + * 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 +#include +#include +#include "database_dump_service.h" +#include "../eqemu_logsys.h" +#include "../string_util.h" +#include "../eqemu_config.h" +#include "../database_schema.h" +#include "../file_util.h" + +#define DATABASE_DUMP_PATH "backups/" + +/** + * @param cmd + * @param return_result + * @return + */ +std::string DatabaseDumpService::execute(const std::string &cmd, bool return_result = true) +{ + const char *file_name = "db-exec-result.txt"; + + if (return_result) { + std::system((cmd + " > " + file_name).c_str()); + } + else { + std::system((cmd).c_str()); + } + + std::string result; + + if (return_result) { + std::ifstream file(file_name); + result = {std::istreambuf_iterator(file), std::istreambuf_iterator()}; + std::remove(file_name); + + } + + return result; +} + +/** + * @return bool + */ +bool DatabaseDumpService::IsMySQLInstalled() +{ + std::string version_output = GetMySQLVersion(); + + return version_output.find("mysql") != std::string::npos && version_output.find("Ver") != std::string::npos; +} + +/** + * Linux + * @return bool + */ +bool DatabaseDumpService::IsTarAvailable() +{ + std::string version_output = execute("tar --version"); + + return version_output.find("GNU tar") != std::string::npos; +} + +/** + * Windows TODO + * @return bool + */ +bool DatabaseDumpService::IsRarAvailable() +{ + std::string version_output = execute("winrar --version"); + + return version_output.find("todo") != std::string::npos; +} + +/** + * @return + */ +bool DatabaseDumpService::HasCompressionBinary() +{ + return IsTarAvailable() || IsRarAvailable(); +} + +/** + * @return + */ +std::string DatabaseDumpService::GetMySQLVersion() +{ + std::string version_output = execute("mysql --version"); + + return trim(version_output); +} + +/** + * @return + */ +std::string DatabaseDumpService::GetBaseMySQLDumpCommand() +{ + auto config = EQEmuConfig::get(); + + return fmt::format( + "mysqldump -u {} -p{} -h {} {}", + config->DatabaseUsername, + config->DatabasePassword, + config->DatabaseHost, + config->DatabaseDB + ); +} + +/** + * @return + */ +std::string DatabaseDumpService::GetPlayerTablesList() +{ + std::string tables_list; + std::vector tables = DatabaseSchema::GetPlayerTables(); + for (const auto &table : tables) { + tables_list += table + " "; + } + + return trim(tables_list); +} + +/** + * @return + */ +std::string DatabaseDumpService::GetLoginTableList() +{ + std::string tables_list; + std::vector tables = DatabaseSchema::GetLoginTables(); + for (const auto &table : tables) { + tables_list += table + " "; + } + + return trim(tables_list); +} + +/** + * @return + */ +std::string DatabaseDumpService::GetSystemTablesList() +{ + std::string tables_list; + + std::vector tables = DatabaseSchema::GetServerTables(); + for (const auto &table : tables) { + tables_list += table + " "; + } + + tables = DatabaseSchema::GetStateTables(); + for (const auto &table : tables) { + tables_list += table + " "; + } + + tables = DatabaseSchema::GetVersionTables(); + for (const auto &table : tables) { + tables_list += table + " "; + } + + return trim(tables_list); +} + +/** + * @return + */ +std::string DatabaseDumpService::GetContentTablesList() +{ + std::string tables_list; + + std::vector tables = DatabaseSchema::GetContentTables(); + for (const auto &table : tables) { + tables_list += table + " "; + } + + return trim(tables_list); +} + +/** + * @return + */ +std::string GetDumpDate() +{ + + time_t now = time(nullptr); + struct tm time_struct{}; + char buf[80]; + time_struct = *localtime(&now); + strftime(buf, sizeof(buf), "%Y-%m-%d", &time_struct); + + std::string time = buf; + + return time; +} + +/** + * @return + */ +std::string DatabaseDumpService::GetSetDumpPath() +{ + return !GetDumpPath().empty() ? GetDumpPath() : DATABASE_DUMP_PATH; +} +/** + * @return + */ +std::string DatabaseDumpService::GetDumpFileNameWithPath() +{ + return GetSetDumpPath() + GetDumpFileName(); +} + +void DatabaseDumpService::Dump() +{ + if (!IsMySQLInstalled()) { + LogError("MySQL is not installed; Please check your PATH for a valid MySQL installation"); + return; + } + + LogInfo("MySQL installed [{}]", GetMySQLVersion()); + + SetDumpFileName(EQEmuConfig::get()->DatabaseDB + '-' + GetDumpDate()); + + auto config = EQEmuConfig::get(); + + LogInfo( + "Database [{}] Host [{}] Username [{}]", + config->DatabaseDB, + config->DatabaseHost, + config->DatabaseUsername + ); + + std::string options = "--compact --allow-keywords --extended-insert"; + + if (IsDumpWithNoData()) { + options += " --no-data"; + } + + if (IsDumpNoTableLock()) { + options += " --skip-lock-tables"; + } + + std::string tables_to_dump; + std::string dump_descriptor; + + if (!IsDumpAllTables()) { + if (IsDumpPlayerTables()) { + tables_to_dump += GetPlayerTablesList(); + dump_descriptor += "-player"; + } + + if (IsDumpSystemTables()) { + tables_to_dump += GetSystemTablesList(); + dump_descriptor += "-system"; + } + + if (IsDumpContentTables()) { + tables_to_dump += GetContentTablesList(); + dump_descriptor += "-content"; + } + + if (IsDumpLoginServerTables()) { + tables_to_dump += GetLoginTableList(); + dump_descriptor += "-login"; + } + } + + if (!dump_descriptor.empty()) { + SetDumpFileName(GetDumpFileName() + dump_descriptor); + } + + std::string execute_command = fmt::format( + "{} {} {} > {}.sql", + GetBaseMySQLDumpCommand(), + options, + tables_to_dump, + GetDumpFileNameWithPath() + ); + + if (!FileUtil::exists(GetSetDumpPath())) { + FileUtil::mkdir(GetSetDumpPath()); + } + + execute(execute_command, false); + + if (!tables_to_dump.empty()) { + LogInfo("Dumping Tables [{}]", tables_to_dump); + } + + LogInfo("Database dump created at [{}.sql]", GetDumpFileNameWithPath()); + + if (IsDumpWithCompression()) { + if (HasCompressionBinary()) { + LogInfo("Compression requested... Compressing dump [{}.sql]", GetDumpFileNameWithPath()); + + if (IsTarAvailable()) { + execute( + fmt::format( + "tar -zcvf {}.tar.gz -C {} {}.sql", + GetDumpFileNameWithPath(), + GetSetDumpPath(), + GetDumpFileName() + ) + ); + LogInfo("Compressed dump created at [{}.tar.gz]", GetDumpFileNameWithPath()); + } + } + else { + LogWarning("Compression requested but binary not found... Skipping..."); + } + } + +// LogDebug("[{}] dump-path", GetSetDumpPath()); +// LogDebug("[{}] compression", (IsDumpWithCompression() ? "true" : "false")); +// LogDebug("[{}] has-compression-binary", (HasCompressionBinary() ? "true" : "false")); +// LogDebug("[{}] content", (IsDumpContentTables() ? "true" : "false")); +// LogDebug("[{}] no-data", (IsDumpWithNoData() ? "true" : "false")); +// LogDebug("[{}] login", (IsDumpLoginServerTables() ? "true" : "false")); +// LogDebug("[{}] player", (IsDumpPlayerTables() ? "true" : "false")); +// LogDebug("[{}] system", (IsDumpSystemTables() ? "true" : "false")); +} + +bool DatabaseDumpService::IsDumpSystemTables() const +{ + return dump_system_tables; +} + +void DatabaseDumpService::SetDumpSystemTables(bool dump_system_tables) +{ + DatabaseDumpService::dump_system_tables = dump_system_tables; +} + +bool DatabaseDumpService::IsDumpContentTables() const +{ + return dump_content_tables; +} + +void DatabaseDumpService::SetDumpContentTables(bool dump_content_tables) +{ + DatabaseDumpService::dump_content_tables = dump_content_tables; +} + +bool DatabaseDumpService::IsDumpPlayerTables() const +{ + return dump_player_tables; +} + +void DatabaseDumpService::SetDumpPlayerTables(bool dump_player_tables) +{ + DatabaseDumpService::dump_player_tables = dump_player_tables; +} + +bool DatabaseDumpService::IsDumpLoginServerTables() const +{ + return dump_login_server_tables; +} + +void DatabaseDumpService::SetDumpLoginServerTables(bool dump_login_server_tables) +{ + DatabaseDumpService::dump_login_server_tables = dump_login_server_tables; +} + +bool DatabaseDumpService::IsDumpWithNoData() const +{ + return dump_with_no_data; +} + +void DatabaseDumpService::SetDumpWithNoData(bool dump_with_no_data) +{ + DatabaseDumpService::dump_with_no_data = dump_with_no_data; +} + +bool DatabaseDumpService::IsDumpAllTables() const +{ + return dump_all_tables; +} + +void DatabaseDumpService::SetDumpAllTables(bool dump_all_tables) +{ + DatabaseDumpService::dump_all_tables = dump_all_tables; +} +bool DatabaseDumpService::IsDumpNoTableLock() const +{ + return dump_no_table_lock; +} + +void DatabaseDumpService::SetDumpNoTableLock(bool dump_no_table_lock) +{ + DatabaseDumpService::dump_no_table_lock = dump_no_table_lock; +} + +bool DatabaseDumpService::IsDumpWithCompression() const +{ + return dump_with_compression; +} + +void DatabaseDumpService::SetDumpWithCompression(bool dump_with_compression) +{ + DatabaseDumpService::dump_with_compression = dump_with_compression; +} + +const std::string &DatabaseDumpService::GetDumpPath() const +{ + return dump_path; +} + +void DatabaseDumpService::SetDumpPath(const std::string &dump_path) +{ + DatabaseDumpService::dump_path = dump_path; +} + +void DatabaseDumpService::SetDumpFileName(const std::string &dump_file_name) +{ + DatabaseDumpService::dump_file_name = dump_file_name; +} + +const std::string &DatabaseDumpService::GetDumpFileName() const +{ + return dump_file_name; +} From dd1470892dc3eb6448852803b06bb2b6b50a1902 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 9 Mar 2020 03:20:43 -0500 Subject: [PATCH 10/42] Update database_dump_service.cpp --- common/database/database_dump_service.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/common/database/database_dump_service.cpp b/common/database/database_dump_service.cpp index 68608bd67..4d0273bf6 100644 --- a/common/database/database_dump_service.cpp +++ b/common/database/database_dump_service.cpp @@ -28,6 +28,13 @@ #include "../database_schema.h" #include "../file_util.h" +#include +#if _WIN32 +#include +#else +#include +#endif + #define DATABASE_DUMP_PATH "backups/" /** From bfecd6ad14a8991e30292fe4a837242e1be341cf Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 9 Mar 2020 14:08:17 -0500 Subject: [PATCH 11/42] Add query-serv table dump option, add option to dump directly to console, add initializers for dump settings --- common/database/database_dump_service.cpp | 77 ++++++++++++++++++++--- common/database/database_dump_service.h | 23 ++++--- common/database_schema.h | 27 +++++++- world/world_server_command_handler.cpp | 4 ++ 4 files changed, 113 insertions(+), 18 deletions(-) diff --git a/common/database/database_dump_service.cpp b/common/database/database_dump_service.cpp index 4d0273bf6..f7a339c84 100644 --- a/common/database/database_dump_service.cpp +++ b/common/database/database_dump_service.cpp @@ -29,10 +29,13 @@ #include "../file_util.h" #include + #if _WIN32 #include #else + #include + #endif #define DATABASE_DUMP_PATH "backups/" @@ -159,6 +162,20 @@ std::string DatabaseDumpService::GetLoginTableList() return trim(tables_list); } +/** + * @return + */ +std::string DatabaseDumpService::GetQueryServTables() +{ + std::string tables_list; + std::vector tables = DatabaseSchema::GetQueryServerTables(); + for (const auto &table : tables) { + tables_list += table + " "; + } + + return trim(tables_list); +} + /** * @return */ @@ -238,6 +255,10 @@ void DatabaseDumpService::Dump() return; } + if (IsDumpOutputToConsole()) { + LogSys.SilenceConsoleLogging(); + } + LogInfo("MySQL installed [{}]", GetMySQLVersion()); SetDumpFileName(EQEmuConfig::get()->DatabaseDB + '-' + GetDumpDate()); @@ -266,43 +287,59 @@ void DatabaseDumpService::Dump() if (!IsDumpAllTables()) { if (IsDumpPlayerTables()) { - tables_to_dump += GetPlayerTablesList(); + tables_to_dump += GetPlayerTablesList() + " "; dump_descriptor += "-player"; } if (IsDumpSystemTables()) { - tables_to_dump += GetSystemTablesList(); + tables_to_dump += GetSystemTablesList() + " "; dump_descriptor += "-system"; } if (IsDumpContentTables()) { - tables_to_dump += GetContentTablesList(); + tables_to_dump += GetContentTablesList() + " "; dump_descriptor += "-content"; } if (IsDumpLoginServerTables()) { - tables_to_dump += GetLoginTableList(); + tables_to_dump += GetLoginTableList() + " "; dump_descriptor += "-login"; } + + if (IsDumpQueryServerTables()) { + tables_to_dump += GetQueryServTables(); + dump_descriptor += "-queryserv"; + } } if (!dump_descriptor.empty()) { SetDumpFileName(GetDumpFileName() + dump_descriptor); } + /** + * If we are dumping to stdout then we don't generate a file + */ + std::string pipe_file; + if (!IsDumpOutputToConsole()) { + pipe_file = fmt::format(" > {}.sql", GetDumpFileNameWithPath()); + } + std::string execute_command = fmt::format( - "{} {} {} > {}.sql", + "{} {} {} {}", GetBaseMySQLDumpCommand(), options, tables_to_dump, - GetDumpFileNameWithPath() + pipe_file ); - if (!FileUtil::exists(GetSetDumpPath())) { + if (!FileUtil::exists(GetSetDumpPath()) && !IsDumpOutputToConsole()) { FileUtil::mkdir(GetSetDumpPath()); } - execute(execute_command, false); + std::string execution_result = execute(execute_command, IsDumpOutputToConsole()); + if (!execution_result.empty()) { + std::cout << execution_result; + } if (!tables_to_dump.empty()) { LogInfo("Dumping Tables [{}]", tables_to_dump); @@ -310,7 +347,7 @@ void DatabaseDumpService::Dump() LogInfo("Database dump created at [{}.sql]", GetDumpFileNameWithPath()); - if (IsDumpWithCompression()) { + if (IsDumpWithCompression() && !IsDumpOutputToConsole()) { if (HasCompressionBinary()) { LogInfo("Compression requested... Compressing dump [{}.sql]", GetDumpFileNameWithPath()); @@ -331,8 +368,10 @@ void DatabaseDumpService::Dump() } } +// LogDebug("[{}] dump-to-console", IsDumpOutputToConsole()); // LogDebug("[{}] dump-path", GetSetDumpPath()); // LogDebug("[{}] compression", (IsDumpWithCompression() ? "true" : "false")); +// LogDebug("[{}] query-serv", (IsDumpQueryServerTables() ? "true" : "false")); // LogDebug("[{}] has-compression-binary", (HasCompressionBinary() ? "true" : "false")); // LogDebug("[{}] content", (IsDumpContentTables() ? "true" : "false")); // LogDebug("[{}] no-data", (IsDumpWithNoData() ? "true" : "false")); @@ -439,3 +478,23 @@ const std::string &DatabaseDumpService::GetDumpFileName() const { return dump_file_name; } + +bool DatabaseDumpService::IsDumpQueryServerTables() const +{ + return dump_query_server_tables; +} + +void DatabaseDumpService::SetDumpQueryServerTables(bool dump_query_server_tables) +{ + DatabaseDumpService::dump_query_server_tables = dump_query_server_tables; +} + +bool DatabaseDumpService::IsDumpOutputToConsole() const +{ + return dump_output_to_console; +} + +void DatabaseDumpService::SetDumpOutputToConsole(bool dump_output_to_console) +{ + DatabaseDumpService::dump_output_to_console = dump_output_to_console; +} \ No newline at end of file diff --git a/common/database/database_dump_service.h b/common/database/database_dump_service.h index 096d4c5d3..eb87520da 100644 --- a/common/database/database_dump_service.h +++ b/common/database/database_dump_service.h @@ -45,16 +45,22 @@ public: void SetDumpPath(const std::string &dump_path); const std::string &GetDumpFileName() const; void SetDumpFileName(const std::string &dump_file_name); + bool IsDumpQueryServerTables() const; + void SetDumpQueryServerTables(bool dump_query_server_tables); + bool IsDumpOutputToConsole() const; + void SetDumpOutputToConsole(bool dump_output_to_console); private: - bool dump_all_tables; - bool dump_system_tables; - bool dump_content_tables; - bool dump_player_tables; - bool dump_login_server_tables; - bool dump_with_no_data; - bool dump_no_table_lock; - bool dump_with_compression; + bool dump_all_tables = false; + bool dump_system_tables = false; + bool dump_content_tables = false; + bool dump_player_tables = false; + bool dump_query_server_tables = false; + bool dump_login_server_tables = false; + bool dump_with_no_data = false; + bool dump_no_table_lock = false; + bool dump_with_compression = false; + bool dump_output_to_console = false; std::string dump_path; std::string dump_file_name; @@ -71,6 +77,7 @@ private: bool HasCompressionBinary(); std::string GetDumpFileNameWithPath(); std::string GetSetDumpPath(); + std::string GetQueryServTables(); }; diff --git a/common/database_schema.h b/common/database_schema.h index b497ad474..5502441d0 100644 --- a/common/database_schema.h +++ b/common/database_schema.h @@ -233,7 +233,6 @@ namespace DatabaseSchema { "task_activities", "tasks", "tasksets", - "titles", "tradeskill_recipe", "tradeskill_recipe_entries", "traps", @@ -282,6 +281,32 @@ namespace DatabaseSchema { }; } + /** + * Gets QueryServer tables + * + * @return + */ + static std::vector GetQueryServerTables() + { + return { + "qs_merchant_transaction_record", + "qs_merchant_transaction_record_entries", + "qs_player_aa_rate_hourly", + "qs_player_delete_record", + "qs_player_delete_record_entries", + "qs_player_events", + "qs_player_handin_record", + "qs_player_handin_record_entries", + "qs_player_move_record", + "qs_player_move_record_entries", + "qs_player_npc_kill_record", + "qs_player_npc_kill_record_entries", + "qs_player_speech", + "qs_player_trade_record", + "qs_player_trade_record_entries", + }; + } + /** * Gets state tables * Tables that keep track of server state diff --git a/world/world_server_command_handler.cpp b/world/world_server_command_handler.cpp index 565277f97..32e794800 100644 --- a/world/world_server_command_handler.cpp +++ b/world/world_server_command_handler.cpp @@ -225,9 +225,11 @@ namespace WorldserverCommandHandler { "--login-tables", "--player-tables", "--system-tables", + "--query-serv-tables", "--table-structure-only", "--no-table-lock", "--dump-path=", + "--dump-output-to-console", "--compress" }; @@ -252,9 +254,11 @@ namespace WorldserverCommandHandler { database_dump_service->SetDumpPlayerTables(cmd[{"-c", "--player-tables"}] || dump_all); database_dump_service->SetDumpSystemTables(cmd[{"-c", "--system-tables"}] || dump_all); database_dump_service->SetDumpWithNoData(cmd[{"-c", "--table-structure-only"}]); + database_dump_service->SetDumpQueryServerTables(cmd[{"--query-serv-tables"}]); database_dump_service->SetDumpAllTables(dump_all); database_dump_service->SetDumpNoTableLock(cmd[{"--no-table-lock"}]); database_dump_service->SetDumpWithCompression(cmd[{"--compress"}]); + database_dump_service->SetDumpOutputToConsole(cmd[{"--dump-output-to-console"}]); /** * Dump From 53be04c39c54ea3aa481dceaa63d410e208e5a61 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 9 Mar 2020 15:51:11 -0500 Subject: [PATCH 12/42] Don't lock tables by default; move tables around in schema; add peq-dump.sh script --- common/database/database_dump_service.cpp | 46 +++++++++++++++++----- common/database/database_dump_service.h | 27 +++++++------ common/database_schema.h | 17 ++++---- utils/sql/peq-dump/peq-dump.sh | 47 +++++++++++++++++++++++ world/world_server_command_handler.cpp | 6 ++- 5 files changed, 112 insertions(+), 31 deletions(-) create mode 100755 utils/sql/peq-dump/peq-dump.sh diff --git a/common/database/database_dump_service.cpp b/common/database/database_dump_service.cpp index f7a339c84..7610f3759 100644 --- a/common/database/database_dump_service.cpp +++ b/common/database/database_dump_service.cpp @@ -255,6 +255,10 @@ void DatabaseDumpService::Dump() return; } + if (IsDumpDropTableSyntaxOnly()) { + SetDumpOutputToConsole(true); + } + if (IsDumpOutputToConsole()) { LogSys.SilenceConsoleLogging(); } @@ -278,7 +282,7 @@ void DatabaseDumpService::Dump() options += " --no-data"; } - if (IsDumpNoTableLock()) { + if (!IsDumpTableLock()) { options += " --skip-lock-tables"; } @@ -336,9 +340,22 @@ void DatabaseDumpService::Dump() FileUtil::mkdir(GetSetDumpPath()); } - std::string execution_result = execute(execute_command, IsDumpOutputToConsole()); - if (!execution_result.empty()) { - std::cout << execution_result; + if (IsDumpDropTableSyntaxOnly()) { + std::vector tables = SplitString(tables_to_dump, ' '); + + for (auto &table : tables) { + std::cout << "DROP TABLE `" << table << "`;" << std::endl; + } + + if (tables_to_dump.empty()) { + std::cerr << "No tables were specified" << std::endl; + } + } + else { + std::string execution_result = execute(execute_command, IsDumpOutputToConsole()); + if (!execution_result.empty()) { + std::cout << execution_result; + } } if (!tables_to_dump.empty()) { @@ -439,14 +456,15 @@ void DatabaseDumpService::SetDumpAllTables(bool dump_all_tables) { DatabaseDumpService::dump_all_tables = dump_all_tables; } -bool DatabaseDumpService::IsDumpNoTableLock() const + +bool DatabaseDumpService::IsDumpTableLock() const { - return dump_no_table_lock; + return dump_table_lock; } -void DatabaseDumpService::SetDumpNoTableLock(bool dump_no_table_lock) +void DatabaseDumpService::SetDumpTableLock(bool dump_table_lock) { - DatabaseDumpService::dump_no_table_lock = dump_no_table_lock; + DatabaseDumpService::dump_table_lock = dump_table_lock; } bool DatabaseDumpService::IsDumpWithCompression() const @@ -497,4 +515,14 @@ bool DatabaseDumpService::IsDumpOutputToConsole() const void DatabaseDumpService::SetDumpOutputToConsole(bool dump_output_to_console) { DatabaseDumpService::dump_output_to_console = dump_output_to_console; -} \ No newline at end of file +} + +bool DatabaseDumpService::IsDumpDropTableSyntaxOnly() const +{ + return dump_drop_table_syntax_only; +} + +void DatabaseDumpService::SetDumpDropTableSyntaxOnly(bool dump_drop_table_syntax_only) +{ + DatabaseDumpService::dump_drop_table_syntax_only = dump_drop_table_syntax_only; +} diff --git a/common/database/database_dump_service.h b/common/database/database_dump_service.h index eb87520da..20f57e85c 100644 --- a/common/database/database_dump_service.h +++ b/common/database/database_dump_service.h @@ -37,8 +37,8 @@ public: void SetDumpPlayerTables(bool dump_player_tables); bool IsDumpLoginServerTables() const; void SetDumpLoginServerTables(bool dump_login_server_tables); - bool IsDumpNoTableLock() const; - void SetDumpNoTableLock(bool dump_no_table_lock); + bool IsDumpTableLock() const; + void SetDumpTableLock(bool dump_table_lock); bool IsDumpWithCompression() const; void SetDumpWithCompression(bool dump_with_compression); const std::string &GetDumpPath() const; @@ -49,18 +49,21 @@ public: void SetDumpQueryServerTables(bool dump_query_server_tables); bool IsDumpOutputToConsole() const; void SetDumpOutputToConsole(bool dump_output_to_console); + bool IsDumpDropTableSyntaxOnly() const; + void SetDumpDropTableSyntaxOnly(bool dump_drop_table_syntax_only); private: - bool dump_all_tables = false; - bool dump_system_tables = false; - bool dump_content_tables = false; - bool dump_player_tables = false; - bool dump_query_server_tables = false; - bool dump_login_server_tables = false; - bool dump_with_no_data = false; - bool dump_no_table_lock = false; - bool dump_with_compression = false; - bool dump_output_to_console = false; + bool dump_all_tables = false; + bool dump_system_tables = false; + bool dump_content_tables = false; + bool dump_player_tables = false; + bool dump_query_server_tables = false; + bool dump_login_server_tables = false; + bool dump_with_no_data = false; + bool dump_table_lock = false; + bool dump_with_compression = false; + bool dump_output_to_console = false; + bool dump_drop_table_syntax_only = false; std::string dump_path; std::string dump_file_name; diff --git a/common/database_schema.h b/common/database_schema.h index 5502441d0..40c9c39f1 100644 --- a/common/database_schema.h +++ b/common/database_schema.h @@ -85,7 +85,8 @@ namespace DatabaseSchema { } /** - * Gets all player and meta-data tables + * @description Gets all player and meta-data tables + * @note These tables have no content in the PEQ daily dump * * @return */ @@ -98,6 +99,8 @@ namespace DatabaseSchema { "account_rewards", "adventure_details", "adventure_stats", + "bugs", + "bug_reports", "buyer", "char_recipe_list", "character_activities", @@ -129,6 +132,8 @@ namespace DatabaseSchema { "character_tribute", "completed_tasks", "data_buckets", + "discovered_items", + "eventlog", "faction_values", "friends", "guild_bank", @@ -141,9 +146,12 @@ namespace DatabaseSchema { "inventory_snapshots", "keyring", "mail", + "petitions", "player_titlesets", "quest_globals", + "saylink", "sharedbank", + "reports", "timers", "titles", "trader", @@ -255,13 +263,9 @@ namespace DatabaseSchema { { return { "banned_ips", - "bugs", - "bug_reports", "command_settings", "db_str", - "discovered_items", "eqtime", - "eventlog", "gm_ips", "hackers", "ip_exemptions", @@ -271,12 +275,9 @@ namespace DatabaseSchema { "logsys_categories", "name_filter", "perl_event_export_settings", - "petitions", "profanity_list", - "reports", "rule_sets", "rule_values", - "saylink", "variables", }; } diff --git a/utils/sql/peq-dump/peq-dump.sh b/utils/sql/peq-dump/peq-dump.sh new file mode 100755 index 000000000..afcb63212 --- /dev/null +++ b/utils/sql/peq-dump/peq-dump.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +world_path="" + +if [ -d "bin" ] +then + world_path="bin/" +fi + +world_bin="${world_path}world" + +echo "World path is [$world_path] bin is [$world_bin]" + +# Run from the context of server directory +# +# --content-tables +# --login-tables +# --player-tables +# --system-tables +# --query-serv-tables + +############################################# +# dump +############################################# + +dump_path=/tmp/peq-dump/ + +mkdir -p ${dump_path} + +############################################# +# generate "drop_" table files +############################################# +bash -c "${world_bin} database:dump --content-tables --drop-table-syntax-only --dump-output-to-console > ${dump_path}drop_tables_content.sql" +bash -c "${world_bin} database:dump --login-tables --drop-table-syntax-only --dump-output-to-console > ${dump_path}drop_tables_login.sql" +bash -c "${world_bin} database:dump --player-tables --drop-table-syntax-only --dump-output-to-console > ${dump_path}drop_tables_player.sql" +bash -c "${world_bin} database:dump --system-tables --drop-table-syntax-only --dump-output-to-console > ${dump_path}drop_tables_system.sql" +bash -c "${world_bin} database:dump --query-serv-tables --drop-table-syntax-only --dump-output-to-console > ${dump_path}drop_tables_queryserv.sql" + +############################################# +# generate "create_" table files +############################################# +bash -c "${world_bin} database:dump --content-tables --dump-output-to-console > ${dump_path}create_tables_content.sql" +bash -c "${world_bin} database:dump --login-tables --table-structure-only --dump-output-to-console > ${dump_path}create_tables_login.sql" +bash -c "${world_bin} database:dump --player-tables --table-structure-only --dump-output-to-console > ${dump_path}create_tables_player.sql" +bash -c "${world_bin} database:dump --system-tables --dump-output-to-console > ${dump_path}create_tables_system.sql" +bash -c "${world_bin} database:dump --query-serv-tables --table-structure-only --dump-output-to-console > ${dump_path}create_tables_queryserv.sql" + diff --git a/world/world_server_command_handler.cpp b/world/world_server_command_handler.cpp index 32e794800..5ccbf167c 100644 --- a/world/world_server_command_handler.cpp +++ b/world/world_server_command_handler.cpp @@ -227,9 +227,10 @@ namespace WorldserverCommandHandler { "--system-tables", "--query-serv-tables", "--table-structure-only", - "--no-table-lock", + "--table-lock", "--dump-path=", "--dump-output-to-console", + "--drop-table-syntax-only", "--compress" }; @@ -256,9 +257,10 @@ namespace WorldserverCommandHandler { database_dump_service->SetDumpWithNoData(cmd[{"-c", "--table-structure-only"}]); database_dump_service->SetDumpQueryServerTables(cmd[{"--query-serv-tables"}]); database_dump_service->SetDumpAllTables(dump_all); - database_dump_service->SetDumpNoTableLock(cmd[{"--no-table-lock"}]); + database_dump_service->SetDumpTableLock(cmd[{"--table-lock"}]); database_dump_service->SetDumpWithCompression(cmd[{"--compress"}]); database_dump_service->SetDumpOutputToConsole(cmd[{"--dump-output-to-console"}]); + database_dump_service->SetDumpDropTableSyntaxOnly(cmd[{"--drop-table-syntax-only"}]); /** * Dump From 899e2d339793dad50107c30e695728cbd874cace Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 9 Mar 2020 16:31:30 -0500 Subject: [PATCH 13/42] Add innodb conversion script; will hook up in manifest later --- .../2020_03_09_convert_myisam_to_innodb.sql | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 utils/sql/git/required/2020_03_09_convert_myisam_to_innodb.sql diff --git a/utils/sql/git/required/2020_03_09_convert_myisam_to_innodb.sql b/utils/sql/git/required/2020_03_09_convert_myisam_to_innodb.sql new file mode 100644 index 000000000..ec9f6607b --- /dev/null +++ b/utils/sql/git/required/2020_03_09_convert_myisam_to_innodb.sql @@ -0,0 +1,99 @@ +ALTER TABLE `aa_actions` ENGINE=InnoDB; +ALTER TABLE `aa_effects` ENGINE=InnoDB; +ALTER TABLE `aa_required_level_cost` ENGINE=InnoDB; +ALTER TABLE `aa_timers` ENGINE=InnoDB; +ALTER TABLE `account_flags` ENGINE=InnoDB; +ALTER TABLE `account_ip` ENGINE=InnoDB; +ALTER TABLE `account` ENGINE=InnoDB; +ALTER TABLE `adventure_template_entry_flavor` ENGINE=InnoDB; +ALTER TABLE `adventure_template_entry` ENGINE=InnoDB; +ALTER TABLE `altadv_vars` ENGINE=InnoDB; +ALTER TABLE `alternate_currency` ENGINE=InnoDB; +ALTER TABLE `banned_ips` ENGINE=InnoDB; +ALTER TABLE `base_data` ENGINE=InnoDB; +ALTER TABLE `blocked_spells` ENGINE=InnoDB; +ALTER TABLE `buyer` ENGINE=InnoDB; +ALTER TABLE `char_create_combinations` ENGINE=InnoDB; +ALTER TABLE `char_create_point_allocations` ENGINE=InnoDB; +ALTER TABLE `character_activities` ENGINE=InnoDB; +ALTER TABLE `character_enabledtasks` ENGINE=InnoDB; +ALTER TABLE `character_tasks` ENGINE=InnoDB; +ALTER TABLE `chatchannels` ENGINE=InnoDB; +ALTER TABLE `completed_tasks` ENGINE=InnoDB; +ALTER TABLE `damageshieldtypes` ENGINE=InnoDB; +ALTER TABLE `discovered_items` ENGINE=InnoDB; +ALTER TABLE `eqtime` ENGINE=InnoDB; +ALTER TABLE `eventlog` ENGINE=InnoDB; +ALTER TABLE `faction_list_mod` ENGINE=InnoDB; +ALTER TABLE `faction_list` ENGINE=InnoDB; +ALTER TABLE `faction_values` ENGINE=InnoDB; +ALTER TABLE `friends` ENGINE=InnoDB; +ALTER TABLE `goallists` ENGINE=InnoDB; +ALTER TABLE `guild_bank` ENGINE=InnoDB; +ALTER TABLE `guild_members` ENGINE=InnoDB; +ALTER TABLE `guild_ranks` ENGINE=InnoDB; +ALTER TABLE `guild_relations` ENGINE=InnoDB; +ALTER TABLE `guilds` ENGINE=InnoDB; +ALTER TABLE `hackers` ENGINE=InnoDB; +ALTER TABLE `horses` ENGINE=InnoDB; +ALTER TABLE `inventory_versions` ENGINE=InnoDB; +ALTER TABLE `item_tick` ENGINE=InnoDB; +ALTER TABLE `items` ENGINE=InnoDB; +ALTER TABLE `keyring` ENGINE=InnoDB; +ALTER TABLE `launcher_zones` ENGINE=InnoDB; +ALTER TABLE `launcher` ENGINE=InnoDB; +ALTER TABLE `ldon_trap_entries` ENGINE=InnoDB; +ALTER TABLE `ldon_trap_templates` ENGINE=InnoDB; +ALTER TABLE `lfguild` ENGINE=InnoDB; +ALTER TABLE `lootdrop_entries` ENGINE=InnoDB; +ALTER TABLE `lootdrop` ENGINE=InnoDB; +ALTER TABLE `loottable_entries` ENGINE=InnoDB; +ALTER TABLE `loottable` ENGINE=InnoDB; +ALTER TABLE `mail` ENGINE=InnoDB; +ALTER TABLE `merc_armorinfo` ENGINE=InnoDB; +ALTER TABLE `merc_buffs` ENGINE=InnoDB; +ALTER TABLE `merc_inventory` ENGINE=InnoDB; +ALTER TABLE `merc_merchant_entries` ENGINE=InnoDB; +ALTER TABLE `merc_merchant_template_entries` ENGINE=InnoDB; +ALTER TABLE `merc_merchant_templates` ENGINE=InnoDB; +ALTER TABLE `merc_name_types` ENGINE=InnoDB; +ALTER TABLE `merc_npc_types` ENGINE=InnoDB; +ALTER TABLE `merc_spell_list_entries` ENGINE=InnoDB; +ALTER TABLE `merc_spell_lists` ENGINE=InnoDB; +ALTER TABLE `merc_stance_entries` ENGINE=InnoDB; +ALTER TABLE `merc_stats` ENGINE=InnoDB; +ALTER TABLE `merc_subtypes` ENGINE=InnoDB; +ALTER TABLE `merc_templates` ENGINE=InnoDB; +ALTER TABLE `merc_types` ENGINE=InnoDB; +ALTER TABLE `merc_weaponinfo` ENGINE=InnoDB; +ALTER TABLE `mercs` ENGINE=InnoDB; +ALTER TABLE `name_filter` ENGINE=InnoDB; +ALTER TABLE `npc_types` ENGINE=InnoDB; +ALTER TABLE `object_contents` ENGINE=InnoDB; +ALTER TABLE `petitions` ENGINE=InnoDB; +ALTER TABLE `pets_equipmentset_entries` ENGINE=InnoDB; +ALTER TABLE `pets_equipmentset` ENGINE=InnoDB; +ALTER TABLE `player_titlesets` ENGINE=InnoDB; +ALTER TABLE `proximities` ENGINE=InnoDB; +ALTER TABLE `races` ENGINE=InnoDB; +ALTER TABLE `raid_details` ENGINE=InnoDB; +ALTER TABLE `raid_leaders` ENGINE=InnoDB; +ALTER TABLE `raid_members` ENGINE=InnoDB; +ALTER TABLE `rule_sets` ENGINE=InnoDB; +ALTER TABLE `rule_values` ENGINE=InnoDB; +ALTER TABLE `saylink` ENGINE=InnoDB; +ALTER TABLE `sharedbank` ENGINE=InnoDB; +ALTER TABLE `skill_caps` ENGINE=InnoDB; +ALTER TABLE `spell_globals` ENGINE=InnoDB; +ALTER TABLE `spells_new` ENGINE=InnoDB; +ALTER TABLE `task_activities` ENGINE=InnoDB; +ALTER TABLE `tasks` ENGINE=InnoDB; +ALTER TABLE `tasksets` ENGINE=InnoDB; +ALTER TABLE `timers` ENGINE=InnoDB; +ALTER TABLE `titles` ENGINE=InnoDB; +ALTER TABLE `trader_audit` ENGINE=InnoDB; +ALTER TABLE `trader` ENGINE=InnoDB; +ALTER TABLE `tradeskill_recipe_entries` ENGINE=InnoDB; +ALTER TABLE `tradeskill_recipe` ENGINE=InnoDB; +ALTER TABLE `variables` ENGINE=InnoDB; +ALTER TABLE `veteran_reward_templates` ENGINE=InnoDB; \ No newline at end of file From 6438a37fb5869c362d08d4404da3b1f8dd2d983a Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 9 Mar 2020 16:31:43 -0500 Subject: [PATCH 14/42] Split up state table dump --- common/database/database_dump_service.cpp | 28 +++++++++++++++++++++-- common/database/database_dump_service.h | 26 ++++++++++++--------- common/database_schema.h | 17 +++++++------- utils/sql/peq-dump/peq-dump.sh | 12 ++++++---- world/world_server_command_handler.cpp | 15 +++++++----- 5 files changed, 66 insertions(+), 32 deletions(-) diff --git a/common/database/database_dump_service.cpp b/common/database/database_dump_service.cpp index 7610f3759..5d6da79e9 100644 --- a/common/database/database_dump_service.cpp +++ b/common/database/database_dump_service.cpp @@ -188,12 +188,21 @@ std::string DatabaseDumpService::GetSystemTablesList() tables_list += table + " "; } - tables = DatabaseSchema::GetStateTables(); + tables = DatabaseSchema::GetVersionTables(); for (const auto &table : tables) { tables_list += table + " "; } - tables = DatabaseSchema::GetVersionTables(); + return trim(tables_list); +} +/** + * @return + */ +std::string DatabaseDumpService::GetStateTablesList() +{ + std::string tables_list; + + std::vector tables = DatabaseSchema::GetStateTables(); for (const auto &table : tables) { tables_list += table + " "; } @@ -300,6 +309,11 @@ void DatabaseDumpService::Dump() dump_descriptor += "-system"; } + if (IsDumpStateTables()) { + tables_to_dump += GetStateTablesList() + " "; + dump_descriptor += "-state"; + } + if (IsDumpContentTables()) { tables_to_dump += GetContentTablesList() + " "; dump_descriptor += "-content"; @@ -526,3 +540,13 @@ void DatabaseDumpService::SetDumpDropTableSyntaxOnly(bool dump_drop_table_syntax { DatabaseDumpService::dump_drop_table_syntax_only = dump_drop_table_syntax_only; } + +bool DatabaseDumpService::IsDumpStateTables() const +{ + return dump_state_tables; +} + +void DatabaseDumpService::SetDumpStateTables(bool dump_state_tables) +{ + DatabaseDumpService::dump_state_tables = dump_state_tables; +} diff --git a/common/database/database_dump_service.h b/common/database/database_dump_service.h index 20f57e85c..439a380ba 100644 --- a/common/database/database_dump_service.h +++ b/common/database/database_dump_service.h @@ -51,19 +51,22 @@ public: void SetDumpOutputToConsole(bool dump_output_to_console); bool IsDumpDropTableSyntaxOnly() const; void SetDumpDropTableSyntaxOnly(bool dump_drop_table_syntax_only); + bool IsDumpStateTables() const; + void SetDumpStateTables(bool dump_state_tables); private: - bool dump_all_tables = false; - bool dump_system_tables = false; - bool dump_content_tables = false; - bool dump_player_tables = false; - bool dump_query_server_tables = false; - bool dump_login_server_tables = false; - bool dump_with_no_data = false; - bool dump_table_lock = false; - bool dump_with_compression = false; - bool dump_output_to_console = false; - bool dump_drop_table_syntax_only = false; + bool dump_all_tables = false; + bool dump_state_tables = false; + bool dump_system_tables = false; + bool dump_content_tables = false; + bool dump_player_tables = false; + bool dump_query_server_tables = false; + bool dump_login_server_tables = false; + bool dump_with_no_data = false; + bool dump_table_lock = false; + bool dump_with_compression = false; + bool dump_output_to_console = false; + bool dump_drop_table_syntax_only = false; std::string dump_path; std::string dump_file_name; @@ -73,6 +76,7 @@ private: std::string GetBaseMySQLDumpCommand(); std::string GetPlayerTablesList(); std::string GetSystemTablesList(); + std::string GetStateTablesList(); std::string GetContentTablesList(); std::string GetLoginTableList(); bool IsTarAvailable(); diff --git a/common/database_schema.h b/common/database_schema.h index 40c9c39f1..75856eb9f 100644 --- a/common/database_schema.h +++ b/common/database_schema.h @@ -99,8 +99,6 @@ namespace DatabaseSchema { "account_rewards", "adventure_details", "adventure_stats", - "bugs", - "bug_reports", "buyer", "char_recipe_list", "character_activities", @@ -133,7 +131,6 @@ namespace DatabaseSchema { "completed_tasks", "data_buckets", "discovered_items", - "eventlog", "faction_values", "friends", "guild_bank", @@ -149,9 +146,9 @@ namespace DatabaseSchema { "petitions", "player_titlesets", "quest_globals", - "saylink", "sharedbank", - "reports", + "spell_buckets", + "spell_globals", "timers", "titles", "trader", @@ -263,6 +260,7 @@ namespace DatabaseSchema { { return { "banned_ips", + "chatchannels", "command_settings", "db_str", "eqtime", @@ -318,7 +316,9 @@ namespace DatabaseSchema { { return { "adventure_members", - "chatchannels", + "bugs", + "bug_reports", + "eventlog", "group_id", "group_leaders", "item_tick", @@ -329,8 +329,9 @@ namespace DatabaseSchema { "raid_leaders", "raid_members", "respawn_times", - "spell_buckets", - "spell_globals", + "reports", + "saylink", + }; } diff --git a/utils/sql/peq-dump/peq-dump.sh b/utils/sql/peq-dump/peq-dump.sh index afcb63212..06300fbd7 100755 --- a/utils/sql/peq-dump/peq-dump.sh +++ b/utils/sql/peq-dump/peq-dump.sh @@ -34,14 +34,16 @@ bash -c "${world_bin} database:dump --content-tables --drop-table-syntax-only -- bash -c "${world_bin} database:dump --login-tables --drop-table-syntax-only --dump-output-to-console > ${dump_path}drop_tables_login.sql" bash -c "${world_bin} database:dump --player-tables --drop-table-syntax-only --dump-output-to-console > ${dump_path}drop_tables_player.sql" bash -c "${world_bin} database:dump --system-tables --drop-table-syntax-only --dump-output-to-console > ${dump_path}drop_tables_system.sql" +bash -c "${world_bin} database:dump --state-tables --drop-table-syntax-only --dump-output-to-console > ${dump_path}drop_tables_state.sql" bash -c "${world_bin} database:dump --query-serv-tables --drop-table-syntax-only --dump-output-to-console > ${dump_path}drop_tables_queryserv.sql" ############################################# # generate "create_" table files ############################################# -bash -c "${world_bin} database:dump --content-tables --dump-output-to-console > ${dump_path}create_tables_content.sql" -bash -c "${world_bin} database:dump --login-tables --table-structure-only --dump-output-to-console > ${dump_path}create_tables_login.sql" -bash -c "${world_bin} database:dump --player-tables --table-structure-only --dump-output-to-console > ${dump_path}create_tables_player.sql" -bash -c "${world_bin} database:dump --system-tables --dump-output-to-console > ${dump_path}create_tables_system.sql" -bash -c "${world_bin} database:dump --query-serv-tables --table-structure-only --dump-output-to-console > ${dump_path}create_tables_queryserv.sql" +bash -c "${world_bin} database:dump --login-tables --table-structure-only --dump-output-to-console | sed 's/ AUTO_INCREMENT=[0-9]*\b//g' > ${dump_path}create_tables_login.sql" +bash -c "${world_bin} database:dump --player-tables --table-structure-only --dump-output-to-console | sed 's/ AUTO_INCREMENT=[0-9]*\b//g' > ${dump_path}create_tables_player.sql" +bash -c "${world_bin} database:dump --state-tables --table-structure-only --dump-output-to-console | sed 's/ AUTO_INCREMENT=[0-9]*\b//g' > ${dump_path}create_tables_state.sql" +bash -c "${world_bin} database:dump --query-serv-tables --table-structure-only --dump-output-to-console | sed 's/ AUTO_INCREMENT=[0-9]*\b//g' > ${dump_path}create_tables_queryserv.sql" +bash -c "${world_bin} database:dump --content-tables --dump-output-to-console > ${dump_path}create_tables_content.sql" +bash -c "${world_bin} database:dump --system-tables --dump-output-to-console > ${dump_path}create_tables_system.sql" \ No newline at end of file diff --git a/world/world_server_command_handler.cpp b/world/world_server_command_handler.cpp index 5ccbf167c..9bad28541 100644 --- a/world/world_server_command_handler.cpp +++ b/world/world_server_command_handler.cpp @@ -224,6 +224,7 @@ namespace WorldserverCommandHandler { "--content-tables", "--login-tables", "--player-tables", + "--state-tables", "--system-tables", "--query-serv-tables", "--table-structure-only", @@ -250,13 +251,15 @@ namespace WorldserverCommandHandler { /** * Set Option */ - database_dump_service->SetDumpContentTables(cmd[{"-c", "--content-tables"}] || dump_all); - database_dump_service->SetDumpLoginServerTables(cmd[{"-c", "--login-tables"}] || dump_all); - database_dump_service->SetDumpPlayerTables(cmd[{"-c", "--player-tables"}] || dump_all); - database_dump_service->SetDumpSystemTables(cmd[{"-c", "--system-tables"}] || dump_all); - database_dump_service->SetDumpWithNoData(cmd[{"-c", "--table-structure-only"}]); - database_dump_service->SetDumpQueryServerTables(cmd[{"--query-serv-tables"}]); + database_dump_service->SetDumpContentTables(cmd[{"--content-tables"}] || dump_all); + database_dump_service->SetDumpLoginServerTables(cmd[{"--login-tables"}] || dump_all); + database_dump_service->SetDumpPlayerTables(cmd[{"--player-tables"}] || dump_all); + database_dump_service->SetDumpStateTables(cmd[{"--state-tables"}] || dump_all); + database_dump_service->SetDumpSystemTables(cmd[{"--system-tables"}] || dump_all); + database_dump_service->SetDumpQueryServerTables(cmd[{"--query-serv-tables"}] || dump_all); database_dump_service->SetDumpAllTables(dump_all); + + database_dump_service->SetDumpWithNoData(cmd[{"--table-structure-only"}]); database_dump_service->SetDumpTableLock(cmd[{"--table-lock"}]); database_dump_service->SetDumpWithCompression(cmd[{"--compress"}]); database_dump_service->SetDumpOutputToConsole(cmd[{"--dump-output-to-console"}]); From e7fab67d8ab0ab69a9be45a10e0000e341633ecb Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 9 Mar 2020 22:57:27 -0500 Subject: [PATCH 15/42] Finalize peq-dump.sh script [skip ci] --- utils/sql/peq-dump/peq-dump.sh | 36 +++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/utils/sql/peq-dump/peq-dump.sh b/utils/sql/peq-dump/peq-dump.sh index 06300fbd7..f60ed02d0 100755 --- a/utils/sql/peq-dump/peq-dump.sh +++ b/utils/sql/peq-dump/peq-dump.sh @@ -1,7 +1,11 @@ #!/usr/bin/env bash +# Run from the context of server directory world_path="" +############################################# +# world path +############################################# if [ -d "bin" ] then world_path="bin/" @@ -11,25 +15,18 @@ world_bin="${world_path}world" echo "World path is [$world_path] bin is [$world_bin]" -# Run from the context of server directory -# -# --content-tables -# --login-tables -# --player-tables -# --system-tables -# --query-serv-tables - ############################################# # dump ############################################# dump_path=/tmp/peq-dump/ - -mkdir -p ${dump_path} +echo "Generating dump path [${dump_path}]" +rm -rf ${dump_path} && mkdir -p ${dump_path} ############################################# # generate "drop_" table files ############################################# +echo "Generating [drop_*] table exports..." bash -c "${world_bin} database:dump --content-tables --drop-table-syntax-only --dump-output-to-console > ${dump_path}drop_tables_content.sql" bash -c "${world_bin} database:dump --login-tables --drop-table-syntax-only --dump-output-to-console > ${dump_path}drop_tables_login.sql" bash -c "${world_bin} database:dump --player-tables --drop-table-syntax-only --dump-output-to-console > ${dump_path}drop_tables_player.sql" @@ -40,10 +37,27 @@ bash -c "${world_bin} database:dump --query-serv-tables --drop-table-syntax-only ############################################# # generate "create_" table files ############################################# +echo "Generating [create_*] table exports..." + +# structure only bash -c "${world_bin} database:dump --login-tables --table-structure-only --dump-output-to-console | sed 's/ AUTO_INCREMENT=[0-9]*\b//g' > ${dump_path}create_tables_login.sql" bash -c "${world_bin} database:dump --player-tables --table-structure-only --dump-output-to-console | sed 's/ AUTO_INCREMENT=[0-9]*\b//g' > ${dump_path}create_tables_player.sql" bash -c "${world_bin} database:dump --state-tables --table-structure-only --dump-output-to-console | sed 's/ AUTO_INCREMENT=[0-9]*\b//g' > ${dump_path}create_tables_state.sql" bash -c "${world_bin} database:dump --query-serv-tables --table-structure-only --dump-output-to-console | sed 's/ AUTO_INCREMENT=[0-9]*\b//g' > ${dump_path}create_tables_queryserv.sql" +# with content bash -c "${world_bin} database:dump --content-tables --dump-output-to-console > ${dump_path}create_tables_content.sql" -bash -c "${world_bin} database:dump --system-tables --dump-output-to-console > ${dump_path}create_tables_system.sql" \ No newline at end of file +bash -c "${world_bin} database:dump --system-tables --dump-output-to-console > ${dump_path}create_tables_system.sql" + +############################################# +# zip +############################################# +human_date=$(date +"%B-%d-%Y" | tr '[:upper:]' '[:lower:]') + +echo "Compressing..." +bash -c "cd ${dump_path} && zip peq-latest.zip * && mv ${dump_path}peq-latest.zip /tmp/peq-latest.zip" + +echo "Cleaning up..." +rm -rf ${dump_path} + +echo "Dump located [/tmp/peq-latest.zip]" \ No newline at end of file From fa12b146a3e13fdbe11d09b7717bd57f57fc9156 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 9 Mar 2020 23:05:01 -0500 Subject: [PATCH 16/42] Add "all" .sql files [skip ci] --- utils/sql/peq-dump/peq-dump.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/utils/sql/peq-dump/peq-dump.sh b/utils/sql/peq-dump/peq-dump.sh index f60ed02d0..7fd9bf278 100755 --- a/utils/sql/peq-dump/peq-dump.sh +++ b/utils/sql/peq-dump/peq-dump.sh @@ -49,6 +49,13 @@ bash -c "${world_bin} database:dump --query-serv-tables --table-structure-only - bash -c "${world_bin} database:dump --content-tables --dump-output-to-console > ${dump_path}create_tables_content.sql" bash -c "${world_bin} database:dump --system-tables --dump-output-to-console > ${dump_path}create_tables_system.sql" +############################################# +# "all" exports +############################################# + +bash -c "cd ${dump_path} && ls * | grep create | sed 's/.*/source &;/' > create_all_tables.sql" +bash -c "cd ${dump_path} && ls * | grep drop | sed 's/.*/source &;/' > drop_all_tables.sql" + ############################################# # zip ############################################# From c42d6dcd1b0833fb8cf6fb57f6facb5b583b2dc7 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 10 Mar 2020 00:14:28 -0500 Subject: [PATCH 17/42] Add 7zip compression; tweak dump settings --- common/database/database_dump_service.cpp | 26 +++++++++++++++++------ common/database/database_dump_service.h | 2 +- utils/sql/peq-dump/peq-dump.sh | 3 +-- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/common/database/database_dump_service.cpp b/common/database/database_dump_service.cpp index 5d6da79e9..e98a8d830 100644 --- a/common/database/database_dump_service.cpp +++ b/common/database/database_dump_service.cpp @@ -90,14 +90,14 @@ bool DatabaseDumpService::IsTarAvailable() } /** - * Windows TODO + * Windows * @return bool */ -bool DatabaseDumpService::IsRarAvailable() +bool DatabaseDumpService::Is7ZipAvailable() { std::string version_output = execute("winrar --version"); - return version_output.find("todo") != std::string::npos; + return version_output.find("7-Zip") != std::string::npos; } /** @@ -105,7 +105,7 @@ bool DatabaseDumpService::IsRarAvailable() */ bool DatabaseDumpService::HasCompressionBinary() { - return IsTarAvailable() || IsRarAvailable(); + return IsTarAvailable() || Is7ZipAvailable(); } /** @@ -285,7 +285,7 @@ void DatabaseDumpService::Dump() config->DatabaseUsername ); - std::string options = "--compact --allow-keywords --extended-insert"; + std::string options = "--allow-keywords --extended-insert"; if (IsDumpWithNoData()) { options += " --no-data"; @@ -358,7 +358,7 @@ void DatabaseDumpService::Dump() std::vector tables = SplitString(tables_to_dump, ' '); for (auto &table : tables) { - std::cout << "DROP TABLE `" << table << "`;" << std::endl; + std::cout << "DROP TABLE IF EXISTS `" << table << "`;" << std::endl; } if (tables_to_dump.empty()) { @@ -393,6 +393,20 @@ void DatabaseDumpService::Dump() ); LogInfo("Compressed dump created at [{}.tar.gz]", GetDumpFileNameWithPath()); } + else if (Is7ZipAvailable()) { + execute( + fmt::format( + "7z a -t7z {}.zip -C {} {}.sql", + GetDumpFileNameWithPath(), + GetSetDumpPath(), + GetDumpFileNameWithPath() + ) + ); + LogInfo("Compressed dump created at [{}.zip]", GetDumpFileNameWithPath()); + } + else { + LogInfo("Compression requested, but no available compression binary was found"); + } } else { LogWarning("Compression requested but binary not found... Skipping..."); diff --git a/common/database/database_dump_service.h b/common/database/database_dump_service.h index 439a380ba..f0614e85b 100644 --- a/common/database/database_dump_service.h +++ b/common/database/database_dump_service.h @@ -80,7 +80,7 @@ private: std::string GetContentTablesList(); std::string GetLoginTableList(); bool IsTarAvailable(); - bool IsRarAvailable(); + bool Is7ZipAvailable(); bool HasCompressionBinary(); std::string GetDumpFileNameWithPath(); std::string GetSetDumpPath(); diff --git a/utils/sql/peq-dump/peq-dump.sh b/utils/sql/peq-dump/peq-dump.sh index 7fd9bf278..911439c8f 100755 --- a/utils/sql/peq-dump/peq-dump.sh +++ b/utils/sql/peq-dump/peq-dump.sh @@ -52,7 +52,6 @@ bash -c "${world_bin} database:dump --system-tables --dump-output-to-console > $ ############################################# # "all" exports ############################################# - bash -c "cd ${dump_path} && ls * | grep create | sed 's/.*/source &;/' > create_all_tables.sql" bash -c "cd ${dump_path} && ls * | grep drop | sed 's/.*/source &;/' > drop_all_tables.sql" @@ -62,7 +61,7 @@ bash -c "cd ${dump_path} && ls * | grep drop | sed 's/.*/source &;/' > drop_all_ human_date=$(date +"%B-%d-%Y" | tr '[:upper:]' '[:lower:]') echo "Compressing..." -bash -c "cd ${dump_path} && zip peq-latest.zip * && mv ${dump_path}peq-latest.zip /tmp/peq-latest.zip" +bash -c "cd /tmp/ && rm peq-latest.zip && zip peq-latest.zip peq-dump/* && mv ${dump_path}peq-latest.zip /tmp/peq-latest.zip" echo "Cleaning up..." rm -rf ${dump_path} From 431a325414dc4702bc1d8c5eec0e97f60ebfce6d Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 10 Mar 2020 00:22:39 -0500 Subject: [PATCH 18/42] Update manifest [skip ci] --- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/common/version.h b/common/version.h index 359c27576..99261fe83 100644 --- a/common/version.h +++ b/common/version.h @@ -34,7 +34,7 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9151 +#define CURRENT_BINARY_DATABASE_VERSION 9152 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9026 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 9be222856..4113a838a 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -405,6 +405,7 @@ 9149|2020_02_06_globalloot.sql|SHOW COLUMNS FROM `global_loot` LIKE 'hot_zone'|empty| 9150|2020_02_06_aa_reset_on_death.sql|SHOW COLUMNS FROM `aa_ability` LIKE 'reset_on_death'|empty| 9151|2020_03_05_npc_always_aggro.sql|SHOW COLUMNS FROM `npc_types` LIKE 'always_aggro'|empty| +9152|2020_03_09_convert_myisam_to_innodb.sql|SELECT * FROM db_version WHERE version >= 9151|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not From f3d82710669896e5360deb5216fb7c6c2b958db7 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 10 Mar 2020 13:41:53 -0500 Subject: [PATCH 19/42] Slightly adjust manifest criteria [skip ci] --- utils/sql/db_update_manifest.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 4113a838a..28b22028e 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -405,7 +405,7 @@ 9149|2020_02_06_globalloot.sql|SHOW COLUMNS FROM `global_loot` LIKE 'hot_zone'|empty| 9150|2020_02_06_aa_reset_on_death.sql|SHOW COLUMNS FROM `aa_ability` LIKE 'reset_on_death'|empty| 9151|2020_03_05_npc_always_aggro.sql|SHOW COLUMNS FROM `npc_types` LIKE 'always_aggro'|empty| -9152|2020_03_09_convert_myisam_to_innodb.sql|SELECT * FROM db_version WHERE version >= 9151|empty| +9152|2020_03_09_convert_myisam_to_innodb.sql|SELECT * FROM db_version WHERE version >= 9152|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not From 08414bda55ce234a1888f6571b91fa59cbf511b2 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 10 Mar 2020 19:18:18 -0500 Subject: [PATCH 20/42] Fix 7zip availability check [skip ci] --- common/database/database_dump_service.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/database/database_dump_service.cpp b/common/database/database_dump_service.cpp index e98a8d830..c4aa971d6 100644 --- a/common/database/database_dump_service.cpp +++ b/common/database/database_dump_service.cpp @@ -95,7 +95,7 @@ bool DatabaseDumpService::IsTarAvailable() */ bool DatabaseDumpService::Is7ZipAvailable() { - std::string version_output = execute("winrar --version"); + std::string version_output = execute("7z -help"); return version_output.find("7-Zip") != std::string::npos; } From e451dad94e9db50c23395ebf5162fce0fde46e13 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 10 Mar 2020 19:42:52 -0500 Subject: [PATCH 21/42] Dump tweaks [skip ci] --- utils/sql/peq-dump/peq-dump.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/utils/sql/peq-dump/peq-dump.sh b/utils/sql/peq-dump/peq-dump.sh index 911439c8f..ccb7b8949 100755 --- a/utils/sql/peq-dump/peq-dump.sh +++ b/utils/sql/peq-dump/peq-dump.sh @@ -21,7 +21,8 @@ echo "World path is [$world_path] bin is [$world_bin]" dump_path=/tmp/peq-dump/ echo "Generating dump path [${dump_path}]" -rm -rf ${dump_path} && mkdir -p ${dump_path} +rm -rf ${dump_path} +mkdir -p ${dump_path} ############################################# # generate "drop_" table files @@ -61,7 +62,7 @@ bash -c "cd ${dump_path} && ls * | grep drop | sed 's/.*/source &;/' > drop_all_ human_date=$(date +"%B-%d-%Y" | tr '[:upper:]' '[:lower:]') echo "Compressing..." -bash -c "cd /tmp/ && rm peq-latest.zip && zip peq-latest.zip peq-dump/* && mv ${dump_path}peq-latest.zip /tmp/peq-latest.zip" +bash -c "cd /tmp/ && rm -rf peq-latest.zip && zip peq-latest.zip peq-dump/* && mv ${dump_path}peq-latest.zip /tmp/peq-latest.zip" echo "Cleaning up..." rm -rf ${dump_path} From 785804a9365f34a4a03ac734fdb9d52d1b6cd0ff Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 10 Mar 2020 19:54:26 -0500 Subject: [PATCH 22/42] Move tables around in schema [skip ci] --- common/database_schema.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/common/database_schema.h b/common/database_schema.h index 75856eb9f..7f883aa9f 100644 --- a/common/database_schema.h +++ b/common/database_schema.h @@ -259,14 +259,10 @@ namespace DatabaseSchema { static std::vector GetServerTables() { return { - "banned_ips", "chatchannels", "command_settings", "db_str", "eqtime", - "gm_ips", - "hackers", - "ip_exemptions", "launcher", "launcher_zones", "level_exp_mods", @@ -316,11 +312,15 @@ namespace DatabaseSchema { { return { "adventure_members", - "bugs", + "banned_ips", "bug_reports", + "bugs", "eventlog", + "gm_ips", "group_id", "group_leaders", + "hackers", + "ip_exemptions", "item_tick", "lfguild", "merchantlist_temp", @@ -328,8 +328,8 @@ namespace DatabaseSchema { "raid_details", "raid_leaders", "raid_members", - "respawn_times", "reports", + "respawn_times", "saylink", }; From 240d5c2a66b7f4d482ec7164192f177624789b85 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 11 Mar 2020 01:39:08 -0500 Subject: [PATCH 23/42] Add LOS check with NPC::AICheckCloseBeneficialSpells [skip ci] --- zone/npc.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/zone/npc.cpp b/zone/npc.cpp index 6df237d5d..0cc2580fe 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -3093,6 +3093,14 @@ bool NPC::AICheckCloseBeneficialSpells( continue; } + if (!mob->CheckLosFN(caster)) { + continue; + } + + if (mob->GetReverseFactionCon(caster) >= FACTION_KINDLY) { + continue; + } + LogAICastBeneficialClose( "NPC [{}] Distance [{}] Cast Range [{}] Caster [{}]", mob->GetCleanName(), @@ -3101,10 +3109,6 @@ bool NPC::AICheckCloseBeneficialSpells( caster->GetCleanName() ); - if (mob->GetReverseFactionCon(caster) >= FACTION_KINDLY) { - continue; - } - if ((spell_types & SpellType_Buff) && !RuleB(NPC, BuffFriends)) { if (mob != caster) { spell_types = SpellType_Heal; From 7f25f8a235bf6b040592e3f3c37774d7e2783869 Mon Sep 17 00:00:00 2001 From: Ali Date: Wed, 11 Mar 2020 17:28:56 +0300 Subject: [PATCH 24/42] Modified eqemu_server.pl to pull latest PEQ * Also added an escape to skip pulling Maps (tighter feedback loop if developing) --- utils/scripts/eqemu_server.pl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index a5ae9e7b8..3c8663273 100755 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -52,6 +52,10 @@ if (-e "eqemu_server_skip_update.txt") { $skip_self_update_check = 1; } +if (-e "eqemu_server_skip_maps_update.txt") { + $skip_self_maps_update_check = 1; +} + #::: Check for script self update check_xml_to_json_conversion() if $ARGV[0] eq "convert_xml"; do_self_update_check_routine() if !$skip_self_update_check; @@ -460,7 +464,7 @@ sub do_installer_routines { get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1); } - map_files_fetch_bulk(); + map_files_fetch_bulk() if !$skip_self_maps_update_check; opcodes_fetch(); plugins_fetch(); quest_files_fetch(); @@ -1705,26 +1709,22 @@ sub fetch_server_dlls { sub fetch_peq_db_full { print "[Install] Downloading latest PEQ Database... Please wait...\n"; - get_remote_file("http://edit.projecteq.net/weekly/peq_beta.zip", "updates_staged/peq_beta.zip", 1); + get_remote_file("http://db.projecteq.net/api/v1/dump/latest", "updates_staged/peq-latest.zip", 1); print "[Install] Downloaded latest PEQ Database... Extracting...\n"; - unzip('updates_staged/peq_beta.zip', 'updates_staged/peq_db/'); - my $start_dir = "updates_staged/peq_db"; + unzip('updates_staged/peq-latest.zip', 'updates_staged/peq_db/'); + my $start_dir = "updates_staged/peq_db/peq-dump"; find( sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { $destination_file = $file; - $destination_file =~ s/updates_staged\/peq_db\///g; - if ($file =~ /peqbeta|player_tables/i) { + $destination_file =~ s/updates_staged\/peq_db\/peq-dump\///g; + if ($file =~ /create_tables_content|create_tables_login|create_tables_player|create_tables_queryserv|create_tables_state|create_tables_system/i) { print "[Install] DB :: Installing :: " . $destination_file . "\n"; get_mysql_result_from_file($file); } } - - #::: PEQ DB baseline version - print get_mysql_result("DELETE FROM db_version"); - print get_mysql_result("INSERT INTO `db_version` (`version`) VALUES (9130);"); } sub map_files_fetch_bulk { From dac7541d891757950d3722bbb5aae497f332bfd2 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 11 Mar 2020 20:43:53 -0700 Subject: [PATCH 25/42] Update README.md Change the badges to the updated builds we have for appveyor. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f3b829732..31f88be38 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # EQEmulator Core Server -|Travis CI (Linux)|Appveyor w/ Bots (Windows) |Appveyor w/o Bots (Windows) | +|Travis CI (Linux)|Appveyor (Windows x86) |Appveyor (Windows x64) | |:---:|:---:|:---:| -|[![Linux CI](https://travis-ci.org/EQEmu/Server.svg?branch=master)](https://travis-ci.org/EQEmu/Server) |[![Build status](https://ci.appveyor.com/api/projects/status/scr25kmntx36c1ub/branch/master?svg=true)](https://ci.appveyor.com/project/KimLS/server-87crp/branch/master) |[![Build status](https://ci.appveyor.com/api/projects/status/mdwbr4o9l6mxqofj/branch/master?svg=true)](https://ci.appveyor.com/project/KimLS/server-w0pq2/branch/master) | +|[![Linux CI](https://travis-ci.org/EQEmu/Server.svg?branch=master)](https://travis-ci.org/EQEmu/Server) |[![Build status](https://ci.appveyor.com/api/projects/status/v3utuu0dttm2cqd0?svg=true)](https://ci.appveyor.com/project/KimLS/server) |[![Build status](https://ci.appveyor.com/api/projects/status/scr25kmntx36c1ub?svg=true)](https://ci.appveyor.com/project/KimLS/server-87crp) | *** From 6a61fd5df9aa2d1b975ea9c532e57d32fe0baa38 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 12 Mar 2020 23:12:44 -0400 Subject: [PATCH 26/42] Tweaked compression arguments for 7-Zip cli command invocation --- common/database/database_dump_service.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/common/database/database_dump_service.cpp b/common/database/database_dump_service.cpp index c4aa971d6..d505a1a24 100644 --- a/common/database/database_dump_service.cpp +++ b/common/database/database_dump_service.cpp @@ -50,7 +50,11 @@ std::string DatabaseDumpService::execute(const std::string &cmd, bool return_res const char *file_name = "db-exec-result.txt"; if (return_result) { +#ifdef _WINDOWS + std::system((cmd + " > " + file_name + " 2>&1").c_str()); +#else std::system((cmd + " > " + file_name).c_str()); +#endif } else { std::system((cmd).c_str()); @@ -95,7 +99,7 @@ bool DatabaseDumpService::IsTarAvailable() */ bool DatabaseDumpService::Is7ZipAvailable() { - std::string version_output = execute("7z -help"); + std::string version_output = execute("7z --help"); return version_output.find("7-Zip") != std::string::npos; } @@ -396,9 +400,8 @@ void DatabaseDumpService::Dump() else if (Is7ZipAvailable()) { execute( fmt::format( - "7z a -t7z {}.zip -C {} {}.sql", + "7z a -t7z {}.zip {}.sql", GetDumpFileNameWithPath(), - GetSetDumpPath(), GetDumpFileNameWithPath() ) ); From e384cf6149eeaf7d2c1df5c5cf5a0fc50cc8af98 Mon Sep 17 00:00:00 2001 From: KimLS Date: Wed, 18 Mar 2020 20:42:27 -0700 Subject: [PATCH 27/42] Replace hard coded 12 with EFFECT_COUNT in the two spots I see it used. --- zone/npc.cpp | 2 +- zone/zonedb.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/npc.cpp b/zone/npc.cpp index 0cc2580fe..b7dc3272a 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -962,7 +962,7 @@ void NPC::Depop(bool StartSpawnTimer) { } bool NPC::DatabaseCastAccepted(int spell_id) { - for (int i=0; i < 12; i++) { + for (int i=0; i < EFFECT_COUNT; i++) { switch(spells[spell_id].effectid[i]) { case SE_Stamina: { if(IsEngaged() && GetHPRatio() < 100) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index cad4e1df8..1dfbeb4a2 100755 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -3703,7 +3703,7 @@ void ZoneDatabase::LoadBuffs(Client *client) if (!IsValidSpell(buffs[index].spellid)) continue; - for (int effectIndex = 0; effectIndex < 12; ++effectIndex) { + for (int effectIndex = 0; effectIndex < EFFECT_COUNT; ++effectIndex) { if (spells[buffs[index].spellid].effectid[effectIndex] == SE_Charm) { buffs[index].spellid = SPELL_UNKNOWN; From 0ab729162594d03841a4b5ea6c3d2e6fc8b2dc10 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 19 Mar 2020 16:43:16 -0400 Subject: [PATCH 28/42] Add countitem(item_id) to Perl/Lua. --- zone/embparser_api.cpp | 14 ++++++++++++++ zone/lua_general.cpp | 5 +++++ zone/questmgr.cpp | 26 ++++++++++++++++++++++++++ zone/questmgr.h | 1 + 4 files changed, 46 insertions(+) diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index efdc09803..cf55925b8 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -2797,6 +2797,19 @@ XS(XS__collectitems) { XSRETURN_IV(quantity); } +XS(XS__countitem); +XS(XS__countitem) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: quest::countitem(int item_id)"); + + uint32 item_id = (int) SvIV(ST(0)); + + int quantity = quest_manager.countitem(item_id); + + XSRETURN_IV(quantity); +} + XS(XS__UpdateSpawnTimer); XS(XS__UpdateSpawnTimer) { dXSARGS; @@ -3951,6 +3964,7 @@ EXTERN_C XS(boot_quest) { newXS(strcpy(buf, "clearspawntimers"), XS__clearspawntimers, file); newXS(strcpy(buf, "collectitems"), XS__collectitems, file); newXS(strcpy(buf, "completedtasksinset"), XS__completedtasksinset, file); + newXS(strcpy(buf, "countitem"), XS__countitem, file); newXS(strcpy(buf, "createdoor"), XS__CreateDoor, file); newXS(strcpy(buf, "creategroundobject"), XS__CreateGroundObject, file); newXS(strcpy(buf, "creategroundobjectfrommodel"), XS__CreateGroundObjectFromModel, file); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 69e262199..9367cef21 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -781,6 +781,10 @@ int lua_collect_items(uint32 item_id, bool remove) { return quest_manager.collectitems(item_id, remove); } +int lua_count_item(uint32 item_id) { + return quest_manager.countitem(item_id); +} + void lua_update_spawn_timer(uint32 id, uint32 new_time) { quest_manager.UpdateSpawnTimer(id, new_time); } @@ -1724,6 +1728,7 @@ luabind::scope lua_register_general() { luabind::def("create_door", &lua_create_door), luabind::def("modify_npc_stat", &lua_modify_npc_stat), luabind::def("collect_items", &lua_collect_items), + luabind::def("count_item", &lua_count_item), luabind::def("update_spawn_timer", &lua_update_spawn_timer), luabind::def("merchant_set_item", (void(*)(uint32,uint32))&lua_merchant_set_item), luabind::def("merchant_set_item", (void(*)(uint32,uint32,uint32))&lua_merchant_set_item), diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 033b42f1a..0c36b876a 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2580,6 +2580,32 @@ int QuestManager::collectitems(uint32 item_id, bool remove) return quantity; } +int QuestManager::countitem(uint32 item_id) { + QuestManagerCurrentQuestVars(); + int quantity = 0; + EQEmu::ItemInstance *item = nullptr; + static const int16 slots[][2] = { + { EQEmu::invslot::POSSESSIONS_BEGIN, EQEmu::invslot::POSSESSIONS_END }, + { EQEmu::invbag::GENERAL_BAGS_BEGIN, EQEmu::invbag::GENERAL_BAGS_END }, + { EQEmu::invbag::CURSOR_BAG_BEGIN, EQEmu::invbag::CURSOR_BAG_END}, + { EQEmu::invslot::BANK_BEGIN, EQEmu::invslot::BANK_END }, + { EQEmu::invbag::BANK_BAGS_BEGIN, EQEmu::invbag::BANK_BAGS_END }, + { EQEmu::invslot::SHARED_BANK_BEGIN, EQEmu::invslot::SHARED_BANK_END }, + { EQEmu::invbag::SHARED_BANK_BAGS_BEGIN, EQEmu::invbag::SHARED_BANK_BAGS_END }, + }; + const size_t size = sizeof(slots) / sizeof(slots[0]); + for (int slot_index = 0; slot_index < size; ++slot_index) { + for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) { + item = initiator->GetInv().GetItem(slot_id); + if (item && item->GetID() == item_id) { + quantity += item->IsStackable() ? item->GetCharges() : 1; + } + } + } + + return quantity; +} + void QuestManager::UpdateSpawnTimer(uint32 id, uint32 newTime) { bool found = false; diff --git a/zone/questmgr.h b/zone/questmgr.h index 2aa1df109..21d5b5db1 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -219,6 +219,7 @@ public: int getlevel(uint8 type); int collectitems(uint32 item_id, bool remove); int collectitems_processSlot(int16 slot_id, uint32 item_id, bool remove); + int countitem(uint32 item_id); void enabletitle(int titleset); bool checktitle(int titlecheck); void removetitle(int titlecheck); From e431c56f7c432a0171cfc847ce40ec904066804d Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 21 Mar 2020 18:41:36 -0500 Subject: [PATCH 29/42] Remove tables that no longer exist --- .../sql/git/required/2020_03_09_convert_myisam_to_innodb.sql | 4 ---- 1 file changed, 4 deletions(-) diff --git a/utils/sql/git/required/2020_03_09_convert_myisam_to_innodb.sql b/utils/sql/git/required/2020_03_09_convert_myisam_to_innodb.sql index ec9f6607b..31ccf1094 100644 --- a/utils/sql/git/required/2020_03_09_convert_myisam_to_innodb.sql +++ b/utils/sql/git/required/2020_03_09_convert_myisam_to_innodb.sql @@ -1,7 +1,3 @@ -ALTER TABLE `aa_actions` ENGINE=InnoDB; -ALTER TABLE `aa_effects` ENGINE=InnoDB; -ALTER TABLE `aa_required_level_cost` ENGINE=InnoDB; -ALTER TABLE `aa_timers` ENGINE=InnoDB; ALTER TABLE `account_flags` ENGINE=InnoDB; ALTER TABLE `account_ip` ENGINE=InnoDB; ALTER TABLE `account` ENGINE=InnoDB; From 52d2469da291184039beaf0923358765312d2068 Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 21 Mar 2020 17:05:28 -0700 Subject: [PATCH 30/42] Rewrite how zone finds ports --- common/event/event_loop.h | 4 ++++ world/main.cpp | 1 + world/zonelist.cpp | 41 ++++++++++++++++++--------------------- world/zonelist.h | 5 +++-- zone/main.cpp | 19 +++++++++--------- zone/worldserver.cpp | 15 ++++++++++---- 6 files changed, 47 insertions(+), 38 deletions(-) diff --git a/common/event/event_loop.h b/common/event/event_loop.h index 295c0532d..537c3280a 100644 --- a/common/event/event_loop.h +++ b/common/event/event_loop.h @@ -25,6 +25,10 @@ namespace EQ uv_run(&m_loop, UV_RUN_DEFAULT); } + void Shutdown() { + uv_stop(&m_loop); + } + uv_loop_t* Handle() { return &m_loop; } private: diff --git a/world/main.cpp b/world/main.cpp index 72cc6d391..9aac1a903 100644 --- a/world/main.cpp +++ b/world/main.cpp @@ -415,6 +415,7 @@ int main(int argc, char** argv) { RegisterConsoleFunctions(console); } + zoneserver_list.Init(); std::unique_ptr server_connection; server_connection.reset(new EQ::Net::ServertalkServer()); diff --git a/world/zonelist.cpp b/world/zonelist.cpp index abb2a5f6f..7f898f89c 100644 --- a/world/zonelist.cpp +++ b/world/zonelist.cpp @@ -39,7 +39,6 @@ ZSList::ZSList() { NextID = 1; CurGroupID = 1; - LastAllocatedPort = 0; memset(pLockedZones, 0, sizeof(pLockedZones)); m_tick.reset(new EQ::Timer(5000, true, std::bind(&ZSList::OnTick, this, std::placeholders::_1))); @@ -76,7 +75,12 @@ void ZSList::Remove(const std::string &uuid) auto iter = zone_server_list.begin(); while (iter != zone_server_list.end()) { if ((*iter)->GetUUID().compare(uuid) == 0) { + auto port = (*iter)->GetCPort(); zone_server_list.erase(iter); + + if (port != 0) { + m_ports_free.push_back(port); + } return; } iter++; @@ -239,6 +243,14 @@ bool ZSList::SetLockedZone(uint16 iZoneID, bool iLock) { return false; } +void ZSList::Init() +{ + const WorldConfig* Config = WorldConfig::get(); + for (uint16 i = Config->ZonePortLow; i <= Config->ZonePortHigh; ++i) { + m_ports_free.push_back(i); + } +} + bool ZSList::IsZoneLocked(uint16 iZoneID) { for (auto &zone : pLockedZones) { if (zone == iZoneID) @@ -577,30 +589,15 @@ void ZSList::RebootZone(const char* ip1, uint16 port, const char* ip2, uint32 sk safe_delete_array(tmp); } -uint16 ZSList::GetAvailableZonePort() +uint16 ZSList::GetAvailableZonePort() { - const WorldConfig *Config = WorldConfig::get(); - int i; - uint16 port = 0; - - if (LastAllocatedPort == 0) - i = Config->ZonePortLow; - else - i = LastAllocatedPort + 1; - - while (i != LastAllocatedPort && port == 0) { - if (i>Config->ZonePortHigh) - i = Config->ZonePortLow; - - if (!FindByPort(i)) { - port = i; - break; - } - i++; + if (m_ports_free.empty()) { + return 0; } - LastAllocatedPort = port; - return port; + auto first = m_ports_free.front(); + m_ports_free.pop_front(); + return first; } uint32 ZSList::TriggerBootup(uint32 iZoneID, uint32 iInstanceID) { diff --git a/world/zonelist.h b/world/zonelist.h index 8b8525f57..5066d4e6d 100644 --- a/world/zonelist.h +++ b/world/zonelist.h @@ -7,6 +7,7 @@ #include "../common/event/timer.h" #include #include +#include class WorldTCPConnection; class ServerPacket; @@ -22,6 +23,7 @@ public: ZSList(); ~ZSList(); + void Init(); bool IsZoneLocked(uint16 iZoneID); bool SendPacket(ServerPacket *pack); bool SendPacket(uint32 zoneid, ServerPacket *pack); @@ -73,8 +75,7 @@ private: uint32 NextID; uint16 pLockedZones[MaxLockedZones]; uint32 CurGroupID; - uint16 LastAllocatedPort; - + std::deque m_ports_free; std::unique_ptr m_tick; std::unique_ptr m_keepalive; diff --git a/zone/main.cpp b/zone/main.cpp index 6d3eee96c..0445534d4 100644 --- a/zone/main.cpp +++ b/zone/main.cpp @@ -92,7 +92,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../common/unix.h" #endif -volatile bool RunLoops = true; extern volatile bool is_zone_loaded; EntityList entity_list; @@ -577,19 +576,19 @@ int main(int argc, char** argv) { return 0; } +void Shutdown() +{ + Zone::Shutdown(true); + LogInfo("Shutting down..."); + LogSys.CloseFileLogs(); + EQ::EventLoop::Get().Shutdown(); +} + void CatchSignal(int sig_num) { #ifdef _WINDOWS LogInfo("Recieved signal: [{}]", sig_num); #endif - RunLoops = false; -} - -void Shutdown() -{ - Zone::Shutdown(true); - RunLoops = false; - LogInfo("Shutting down..."); - LogSys.CloseFileLogs(); + Shutdown(); } /* Update Window Title with relevant information */ diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 60f770c92..87cfb13ef 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -57,7 +57,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA extern EntityList entity_list; extern Zone* zone; extern volatile bool is_zone_loaded; -extern void CatchSignal(int); +extern void Shutdown(); extern WorldServer worldserver; extern PetitionList petition_list; extern uint32 numclients; @@ -192,8 +192,15 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) if (pack->size != sizeof(ServerConnectInfo)) break; ServerConnectInfo* sci = (ServerConnectInfo*)pack->pBuffer; - LogInfo("World assigned Port: [{}] for this zone", sci->port); - ZoneConfig::SetZonePort(sci->port); + + if (sci->port == 0) { + LogCritical("World did not have a port to assign from this server, the port range was not large enough."); + Shutdown(); + } + else { + LogInfo("World assigned Port: [{}] for this zone", sci->port); + ZoneConfig::SetZonePort(sci->port); + } break; } case ServerOP_ChannelMessage: { @@ -482,7 +489,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } case ServerOP_ShutdownAll: { entity_list.Save(); - CatchSignal(2); + Shutdown(); break; } case ServerOP_ZoneShutdown: { From 1cdf507b9fd475c13a9910bfb20dbfe7640c5f1a Mon Sep 17 00:00:00 2001 From: Ali Date: Tue, 24 Mar 2020 12:44:45 +0300 Subject: [PATCH 31/42] [ci skip] Enhanced .gitignore * Removes the generated files from both CMake and VS --- .gitignore | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 287c07412..b8ec6881f 100644 --- a/.gitignore +++ b/.gitignore @@ -37,4 +37,19 @@ perl/ submodules/* cmake-build-debug/ -.nfs.* \ No newline at end of file +.nfs.* + +# Visual Studio and CMAKE Generated Files +/.vs/ +*.vcxproj +*.vcxproj.filters +*.vcxproj.user +*.cmake +*.ilk +*.pdb +*.sln +*.dir/ +libs/ +bin/ +/Win32 +/client_files/**/CMakeFiles/ From 60e194e32bb5af2049ff1900c408fa663e60ffef Mon Sep 17 00:00:00 2001 From: Ali Date: Tue, 24 Mar 2020 10:06:49 +0300 Subject: [PATCH 32/42] Fix double damaging spell messages to non-attacked and non-attacker With handling for client attacker and pets thanks to @noudess --- zone/spells.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 5b8ee33f8..2a129fb6b 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3426,6 +3426,8 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r bool isproc, int level_override) { + bool isDamageOrLifetapSpell = IsDamageSpell(spell_id) || IsLifetapSpell(spell_id); + // well we can't cast a spell on target without a target if(!spelltar) { @@ -3967,9 +3969,6 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r // send to people in the area, ignoring caster and target //live dosent send this to anybody but the caster //entity_list.QueueCloseClients(spelltar, action_packet, true, 200, this, true, spelltar->IsClient() ? FILTER_PCSPELLS : FILTER_NPCSPELLS); - - // TEMPORARY - this is the message for the spell. - // double message on effects that use ChangeHP - working on this message_packet = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct)); CombatDamage_Struct *cd = (CombatDamage_Struct *)message_packet->pBuffer; cd->target = action->target; @@ -3980,7 +3979,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r cd->hit_heading = action->hit_heading; cd->hit_pitch = action->hit_pitch; cd->damage = 0; - if(!IsEffectInSpell(spell_id, SE_BindAffinity)){ + if(!IsEffectInSpell(spell_id, SE_BindAffinity) && !isDamageOrLifetapSpell){ entity_list.QueueCloseClients( spelltar, /* Sender */ message_packet, /* Packet */ @@ -3990,6 +3989,19 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r true, /* Packet ACK */ (spelltar->IsClient() ? FilterPCSpells : FilterNPCSpells) /* Message Filter Type: (8 or 9) */ ); + } else if (isDamageOrLifetapSpell && + (IsClient() || + (HasOwner() && + GetOwner()->IsClient() + ) + ) + ) { + (HasOwner() ? GetOwner() : this)->CastToClient()->QueuePacket( + message_packet, + true, + Mob::CLIENT_CONNECTINGALL, + (spelltar->IsClient() ? FilterPCSpells : FilterNPCSpells) + ); } safe_delete(action_packet); safe_delete(message_packet); From a2b381bc9edf5886f536ba5e055544248bcc71ab Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 29 Mar 2020 16:34:07 -0400 Subject: [PATCH 33/42] Added command 'editmassrespawn' for mass editing of respawn times --- zone/command.cpp | 143 ++++++++++++++++++++++++++++++++++++++++++++++- zone/command.h | 1 + 2 files changed, 142 insertions(+), 2 deletions(-) diff --git a/zone/command.cpp b/zone/command.cpp index 757e2d522..23b269395 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -196,6 +196,7 @@ int command_init(void) command_add("disarmtrap", "Analog for ldon disarm trap for the newer clients since we still don't have it working.", 80, command_disarmtrap) || command_add("distance", "- Reports the distance between you and your target.", 80, command_distance) || command_add("doanim", "[animnum] [type] - Send an EmoteAnim for you or your target", 50, command_doanim) || + command_add("editmassrespawn", "[name-search] [second-value] - Mass (Zone wide) NPC respawn timer editing command", 100, command_editmassrespawn) || command_add("emote", "['name'/'world'/'zone'] [type] [message] - Send an emote message", 80, command_emote) || command_add("emotesearch", "Searches NPC Emotes", 80, command_emotesearch) || command_add("emoteview", "Lists all NPC Emotes", 80, command_emoteview) || @@ -6525,6 +6526,144 @@ void command_doanim(Client *c, const Seperator *sep) c->DoAnim(atoi(sep->arg[1]),atoi(sep->arg[2])); } +void command_editmassrespawn(Client* c, const Seperator* sep) +{ + if (strcasecmp(sep->arg[1], "usage") == 0) { + c->Message(Chat::White, "#editmassrespawn [exact_match: =]npc_type_name new_respawn_seconds (apply)"); + return; + } + + std::string search_npc_type; + if (sep->arg[1]) { + search_npc_type = sep->arg[1]; + } + + int change_respawn_seconds = 0; + if (sep->arg[2] && sep->IsNumber(2)) { + change_respawn_seconds = atoi(sep->arg[2]); + } + + bool change_apply = false; + if (sep->arg[3] && strcasecmp(sep->arg[3], "apply") == 0) { + change_apply = true; + } + + std::string search_encapsulator = "%"; + if (search_npc_type[0] == '=') { + + search_npc_type = search_npc_type.substr(1); + search_encapsulator = ""; + } + + std::string query = fmt::format( + SQL( + SELECT tc.id, ta.spawngroupID, ta.id, tc.name, ta.respawntime + FROM spawn2 ta + INNER JOIN spawnentry tb ON ta.spawngroupID = tb.spawngroupID + INNER JOIN npc_types tc ON tb.npcID = tc.id + WHERE ta.zone LIKE '{}' + AND ta.version = '{}' + AND tc.name LIKE '{}{}{}' + ORDER BY tc.id, ta.spawngroupID, ta.id + ), + zone->GetShortName(), + zone->GetInstanceVersion(), + search_encapsulator, + search_npc_type, + search_encapsulator + ); + + std::string status = "(Searching)"; + if (change_apply) { + status = "(Applying)"; + } + + int results_count = 0; + + auto results = database.QueryDatabase(query); + if (results.Success() && results.RowCount()) { + + results_count = results.RowCount(); + + for (auto row : results) { + c->Message( + Chat::Yellow, + fmt::format( + "NPC (npcid:{}) (sgid:{}) (s2id:{}) [{}] Respawn: Current [{}] New [{}] {}", + row[0], + row[1], + row[2], + row[3], + row[4], + change_respawn_seconds, + status + ).c_str() + ); + } + + c->Message(Chat::Yellow, "Found (%i) NPC's that match this search...", results_count); + + if (change_respawn_seconds > 0) { + + if (change_apply) { + + results = database.QueryDatabase( + fmt::format( + SQL( + UPDATE spawn2 + SET respawntime = '{}' + WHERE id IN ( + SELECT ta.id + FROM spawn2 ta + INNER JOIN spawnentry tb ON ta.spawngroupID = tb.spawngroupID + INNER JOIN npc_types tc ON tb.npcID = tc.id + WHERE ta.zone LIKE '{}' + AND ta.version = '{}' + AND tc.name LIKE '{}{}{}' + ) + ), + change_respawn_seconds, + zone->GetShortName(), + zone->GetInstanceVersion(), + search_encapsulator, + search_npc_type, + search_encapsulator + ) + ); + + if (results.Success()) { + + c->Message(Chat::Yellow, "Changes applied to (%i) NPC 'Spawn2' entries", results_count); + zone->Repop(); + } + else { + + c->Message(Chat::Yellow, "Found (0) NPC's that match this search..."); + } + } + else { + + std::string saylink = fmt::format( + "#editmassrespawn {}{} {} apply", + (search_encapsulator.empty() ? "=" : ""), + search_npc_type, + change_respawn_seconds + ); + + c->Message( + Chat::Yellow, "To apply these changes, click <%s> or type [%s]", + EQEmu::SayLinkEngine::GenerateQuestSaylink(saylink, false, "Apply").c_str(), + saylink.c_str() + ); + } + } + } + else { + + c->Message(Chat::Yellow, "Found (0) NPC's that match this search..."); + } +} + void command_randomfeatures(Client *c, const Seperator *sep) { Mob *target=c->GetTarget(); @@ -7782,7 +7921,7 @@ void command_npcemote(Client *c, const Seperator *sep) void command_npceditmass(Client *c, const Seperator *sep) { if (strcasecmp(sep->arg[1], "usage") == 0) { - c->Message(Chat::White, "#npceditmass search_column [exact_match: =]search_value change_column change_value"); + c->Message(Chat::White, "#npceditmass search_column [exact_match: =]search_value change_column change_value (apply)"); return; } @@ -7930,7 +8069,7 @@ void command_npceditmass(Client *c, const Seperator *sep) std::string saylink = fmt::format( "#npceditmass {} {}{} {} {} apply", search_column, - (exact_match ? '=' : '\0'), + (exact_match ? "=" : ""), search_value, change_column, change_value diff --git a/zone/command.h b/zone/command.h index d64950f9c..7c1af0edf 100644 --- a/zone/command.h +++ b/zone/command.h @@ -91,6 +91,7 @@ void command_disablerecipe(Client *c, const Seperator *sep); void command_disarmtrap(Client *c, const Seperator *sep); void command_distance(Client *c, const Seperator *sep); void command_doanim(Client *c, const Seperator *sep); +void command_editmassrespawn(Client* c, const Seperator* sep); void command_emote(Client *c, const Seperator *sep); void command_emotesearch(Client* c, const Seperator *sep); void command_emoteview(Client* c, const Seperator *sep); From a48153baa1ec458d91642aec6cc0061698efb0f1 Mon Sep 17 00:00:00 2001 From: Ali Al-Khalifa Date: Mon, 30 Mar 2020 00:26:56 +0300 Subject: [PATCH 34/42] Fix errant formatting Mistakenly had a variable in camelCase --- zone/spells.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 2a129fb6b..be1419caa 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3426,7 +3426,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r bool isproc, int level_override) { - bool isDamageOrLifetapSpell = IsDamageSpell(spell_id) || IsLifetapSpell(spell_id); + bool is_damage_or_lifetap_spell = IsDamageSpell(spell_id) || IsLifetapSpell(spell_id); // well we can't cast a spell on target without a target if(!spelltar) @@ -3979,7 +3979,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r cd->hit_heading = action->hit_heading; cd->hit_pitch = action->hit_pitch; cd->damage = 0; - if(!IsEffectInSpell(spell_id, SE_BindAffinity) && !isDamageOrLifetapSpell){ + if(!IsEffectInSpell(spell_id, SE_BindAffinity) && !is_damage_or_lifetap_spell){ entity_list.QueueCloseClients( spelltar, /* Sender */ message_packet, /* Packet */ @@ -3989,7 +3989,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r true, /* Packet ACK */ (spelltar->IsClient() ? FilterPCSpells : FilterNPCSpells) /* Message Filter Type: (8 or 9) */ ); - } else if (isDamageOrLifetapSpell && + } else if (is_damage_or_lifetap_spell && (IsClient() || (HasOwner() && GetOwner()->IsClient() From b94fdda429de46d133560ef993d764af26ebec6b Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 29 Mar 2020 18:02:27 -0400 Subject: [PATCH 35/42] Updated command 'editmassrespawn' queries to use resolved names over aliases --- zone/command.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/zone/command.cpp b/zone/command.cpp index 23b269395..42453faab 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -6557,14 +6557,14 @@ void command_editmassrespawn(Client* c, const Seperator* sep) std::string query = fmt::format( SQL( - SELECT tc.id, ta.spawngroupID, ta.id, tc.name, ta.respawntime - FROM spawn2 ta - INNER JOIN spawnentry tb ON ta.spawngroupID = tb.spawngroupID - INNER JOIN npc_types tc ON tb.npcID = tc.id - WHERE ta.zone LIKE '{}' - AND ta.version = '{}' - AND tc.name LIKE '{}{}{}' - ORDER BY tc.id, ta.spawngroupID, ta.id + SELECT npc_types.id, spawn2.spawngroupID, spawn2.id, npc_types.name, spawn2.respawntime + FROM spawn2 + INNER JOIN spawnentry ON spawn2.spawngroupID = spawnentry.spawngroupID + INNER JOIN npc_types ON spawnentry.npcID = npc_types.id + WHERE spawn2.zone LIKE '{}' + AND spawn2.version = '{}' + AND npc_types.name LIKE '{}{}{}' + ORDER BY npc_types.id, spawn2.spawngroupID, spawn2.id ), zone->GetShortName(), zone->GetInstanceVersion(), @@ -6613,13 +6613,13 @@ void command_editmassrespawn(Client* c, const Seperator* sep) UPDATE spawn2 SET respawntime = '{}' WHERE id IN ( - SELECT ta.id - FROM spawn2 ta - INNER JOIN spawnentry tb ON ta.spawngroupID = tb.spawngroupID - INNER JOIN npc_types tc ON tb.npcID = tc.id - WHERE ta.zone LIKE '{}' - AND ta.version = '{}' - AND tc.name LIKE '{}{}{}' + SELECT spawn2.id + FROM spawn2 + INNER JOIN spawnentry ON spawn2.spawngroupID = spawnentry.spawngroupID + INNER JOIN npc_types ON spawnentry.npcID = npc_types.id + WHERE spawn2.zone LIKE '{}' + AND spawn2.version = '{}' + AND npc_types.name LIKE '{}{}{}' ) ), change_respawn_seconds, From 99c1c826a8acbe7d4820632257ef7d5a357642fa Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 30 Mar 2020 08:02:45 -0400 Subject: [PATCH 36/42] Fix for bots guild-related view query issue --- common/version.h | 2 +- .../sql/git/bots/bots_db_update_manifest.txt | 1 + .../required/2020_03_30_bots_view_update.sql | 24 +++++++++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 utils/sql/git/bots/required/2020_03_30_bots_view_update.sql diff --git a/common/version.h b/common/version.h index 99261fe83..7c378e763 100644 --- a/common/version.h +++ b/common/version.h @@ -37,7 +37,7 @@ #define CURRENT_BINARY_DATABASE_VERSION 9152 #ifdef BOTS - #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9026 + #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9027 #else #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0 #endif diff --git a/utils/sql/git/bots/bots_db_update_manifest.txt b/utils/sql/git/bots/bots_db_update_manifest.txt index 1e18516b7..86e7c49dd 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -25,6 +25,7 @@ 9024|2019_06_27_bots_pet_get_lost.sql|SELECT `bot_command` FROM `bot_command_settings` WHERE `bot_command` LIKE 'petgetlost'|empty| 9025|2019_08_26_bots_owner_option_spawn_message.sql|SELECT * FROM db_version WHERE bots_version >= 9025|empty| 9026|2019_09_09_bots_owner_options_rework.sql|SHOW COLUMNS FROM `bot_owner_options` LIKE 'option_type'|empty| +9027|2020_03_30_bots_view_update.sql|SELECT * FROM db_version WHERE bots_version >= 9027|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/bots/required/2020_03_30_bots_view_update.sql b/utils/sql/git/bots/required/2020_03_30_bots_view_update.sql new file mode 100644 index 000000000..d4948efed --- /dev/null +++ b/utils/sql/git/bots/required/2020_03_30_bots_view_update.sql @@ -0,0 +1,24 @@ +DROP VIEW IF EXISTS `vw_bot_character_mobs`; + +-- Views +CREATE VIEW `vw_bot_character_mobs` AS +SELECT +_utf8'C' AS mob_type, +c.`id`, +c.`name`, +c.`class`, +c.`level`, +c.`last_login`, +c.`zone_id`, +c.`deleted_at` +FROM `character_data` AS c +UNION ALL +SELECT _utf8'B' AS mob_type, +b.`bot_id` AS id, +b.`name`, +b.`class`, +b.`level`, +b.`last_spawn` AS last_login, +b.`zone_id`, +NULL AS `deleted_at` +FROM `bot_data` AS b; From 3a7908b1de0da73f3a844c3a81f7525d04808aaa Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 30 Mar 2020 16:45:50 -0400 Subject: [PATCH 37/42] Fix for bots database updates not running when invoked from world.exe [skip ci] --- utils/scripts/eqemu_server.pl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 3c8663273..6618b021e 100755 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -537,7 +537,10 @@ sub check_for_world_bootup_database_update { if ($binary_database_version == $local_database_version && $ARGV[0] eq "ran_from_world") { print "[Update] Database up to date...\n"; - exit; + if (trim($db_version[2]) == 0) { + print "[Update] Continuing bootup\n"; + exit; + } } else { #::: We ran world - Database needs to update, lets backup and run updates and continue world bootup From 51b31b5e531cb6ebb44bc8bad5241ac37e34b40b Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 31 Mar 2020 19:31:04 -0400 Subject: [PATCH 38/42] Add getitemname(item_id) to Perl/Lua. --- zone/embparser_api.cpp | 17 +++++++++++++++++ zone/lua_general.cpp | 5 +++++ zone/questmgr.cpp | 10 ++++++++++ zone/questmgr.h | 1 + 4 files changed, 33 insertions(+) diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index cf55925b8..901d25ce2 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -2810,6 +2810,22 @@ XS(XS__countitem) { XSRETURN_IV(quantity); } +XS(XS__getitemname); +XS(XS__getitemname) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: quest::getitemname(uint32 item_id)"); + + dXSTARG; + uint32 item_id = (int) SvIV(ST(0)); + std::string item_name = quest_manager.getitemname(item_id); + + sv_setpv(TARG, item_name.c_str()); + XSprePUSH; + PUSHTARG; + XSRETURN(1); +} + XS(XS__UpdateSpawnTimer); XS(XS__UpdateSpawnTimer) { dXSARGS; @@ -4005,6 +4021,7 @@ EXTERN_C XS(boot_quest) { newXS(strcpy(buf, "forcedoorclose"), XS__forcedoorclose, file); newXS(strcpy(buf, "forcedooropen"), XS__forcedooropen, file); newXS(strcpy(buf, "getinventoryslotid"), XS__getinventoryslotid, file); + newXS(strcpy(buf, "getitemname"), XS__getitemname, file); newXS(strcpy(buf, "getItemName"), XS_qc_getItemName, file); newXS(strcpy(buf, "get_spawn_condition"), XS__get_spawn_condition, file); newXS(strcpy(buf, "getguildnamebyid"), XS__getguildnamebyid, file); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 9367cef21..15fc3d3e1 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -807,6 +807,10 @@ std::string lua_item_link(int item_id) { return quest_manager.varlink(text, item_id); } +std::string lua_get_item_name(uint32 item_id) { + return quest_manager.getitemname(item_id); +} + std::string lua_say_link(const char *phrase, bool silent, const char *link_name) { char text[256] = { 0 }; strncpy(text, phrase, 255); @@ -1734,6 +1738,7 @@ luabind::scope lua_register_general() { luabind::def("merchant_set_item", (void(*)(uint32,uint32,uint32))&lua_merchant_set_item), luabind::def("merchant_count_item", &lua_merchant_count_item), luabind::def("item_link", &lua_item_link), + luabind::def("get_item_name", (std::string(*)(uint32))&lua_get_item_name), luabind::def("say_link", (std::string(*)(const char*,bool,const char*))&lua_say_link), luabind::def("say_link", (std::string(*)(const char*,bool))&lua_say_link), luabind::def("say_link", (std::string(*)(const char*))&lua_say_link), diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 0c36b876a..a1ec7d959 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2696,6 +2696,16 @@ const char* QuestManager::varlink(char* perltext, int item_id) { return perltext; } +std::string QuestManager::getitemname(uint32 item_id) { + const EQEmu::ItemData* item_data = database.GetItem(item_id); + if (!item_data) { + return "INVALID ITEM ID IN GETITEMNAME"; + } + + std::string item_name = item_data->Name; + return item_name; +} + uint16 QuestManager::CreateInstance(const char *zone, int16 version, uint32 duration) { QuestManagerCurrentQuestVars(); diff --git a/zone/questmgr.h b/zone/questmgr.h index 21d5b5db1..cde58fc0d 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -220,6 +220,7 @@ public: int collectitems(uint32 item_id, bool remove); int collectitems_processSlot(int16 slot_id, uint32 item_id, bool remove); int countitem(uint32 item_id); + std::string getitemname(uint32 item_id); void enabletitle(int titleset); bool checktitle(int titlecheck); void removetitle(int titlecheck); From ceb8b31bc0570dbb0bc17b50e96fefb0212f8369 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 31 Mar 2020 19:48:44 -0400 Subject: [PATCH 39/42] Add getspellname(spell_id) to Perl/Lua. --- zone/embparser_api.cpp | 17 +++++++++++++++++ zone/lua_general.cpp | 5 +++++ zone/questmgr.cpp | 9 +++++++++ zone/questmgr.h | 1 + 4 files changed, 32 insertions(+) diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index cf55925b8..bb90d77ce 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -822,6 +822,22 @@ XS(XS__isdisctome) { XSRETURN(1); } +XS(XS__getspellname); +XS(XS__getspellname) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: quest::getspellname(uint32 spell_id)"); + + dXSTARG; + uint32 spell_id = (int) SvIV(ST(0)); + std::string spell_name = quest_manager.getspellname(spell_id); + + sv_setpv(TARG, spell_name.c_str()); + XSprePUSH; + PUSHTARG; + XSRETURN(1); +} + XS(XS__safemove); XS(XS__safemove) { dXSARGS; @@ -4011,6 +4027,7 @@ EXTERN_C XS(boot_quest) { newXS(strcpy(buf, "getguildidbycharid"), XS__getguildidbycharid, file); newXS(strcpy(buf, "getgroupidbycharid"), XS__getgroupidbycharid, file); newXS(strcpy(buf, "getraididbycharid"), XS__getraididbycharid, file); + newXS(strcpy(buf, "getspellname"), XS__getspellname, file); newXS(strcpy(buf, "getlevel"), XS__getlevel, file); newXS(strcpy(buf, "getplayerburiedcorpsecount"), XS__getplayerburiedcorpsecount, file); newXS(strcpy(buf, "getplayercorpsecount"), XS__getplayercorpsecount, file); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 9367cef21..ef07d3742 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -393,6 +393,10 @@ bool lua_is_disc_tome(int item_id) { return quest_manager.isdisctome(item_id); } +std::string lua_get_spell_name(uint32 spell_id) { + return quest_manager.getspellname(spell_id); +} + void lua_safe_move() { quest_manager.safemove(); } @@ -1648,6 +1652,7 @@ luabind::scope lua_register_general() { luabind::def("depop_zone", &lua_depop_zone), luabind::def("repop_zone", &lua_repop_zone), luabind::def("is_disc_tome", &lua_is_disc_tome), + luabind::def("get_spell_name", (std::string(*)(uint32))&lua_get_spell_name), luabind::def("safe_move", &lua_safe_move), luabind::def("rain", &lua_rain), luabind::def("snow", &lua_snow), diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 0c36b876a..7fb1474fd 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -906,6 +906,15 @@ bool QuestManager::isdisctome(int item_id) { return(true); } +std::string QuestManager::getspellname(uint32 spell_id) { + if (!IsValidSpell(spell_id)) { + return "INVALID SPELL ID IN GETSPELLNAME"; + } + + std::string spell_name = GetSpellName(spell_id); + return spell_name; +} + void QuestManager::safemove() { QuestManagerCurrentQuestVars(); if (initiator && initiator->IsClient()) diff --git a/zone/questmgr.h b/zone/questmgr.h index 21d5b5db1..6ea7fcf38 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -107,6 +107,7 @@ public: void level(int newlevel); void traindisc(int discipline_tome_item_id); bool isdisctome(int item_id); + std::string getspellname(uint32 spell_id); void safemove(); void rain(int weather); void snow(int weather); From 89740595779c7a3a2b2fe87425166b508e469c3e Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 31 Mar 2020 20:01:12 -0400 Subject: [PATCH 40/42] Remove unused variables in resettaskactivity. --- zone/embparser_api.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 6e07ad9f0..19c3a2b38 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -2358,7 +2358,6 @@ XS(XS__updatetaskactivity) { XS(XS__resettaskactivity); XS(XS__resettaskactivity) { dXSARGS; - unsigned int task, activity; if (items == 2) { int task_id = (int) SvIV(ST(0)); int activity_id = (int) SvIV(ST(1)); From 4712b56078266a84c36aba76a598dc9aa24a3a60 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 31 Mar 2020 22:24:09 -0400 Subject: [PATCH 41/42] Add gettaskname(task_id) to Perl/Lua. --- zone/embparser_api.cpp | 18 ++++++++++++++++++ zone/lua_general.cpp | 5 +++++ zone/questmgr.cpp | 10 ++++++++++ zone/questmgr.h | 1 + zone/tasks.cpp | 11 +++++++++++ zone/tasks.h | 1 + 6 files changed, 46 insertions(+) diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 6e07ad9f0..b299a42b5 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -2629,6 +2629,23 @@ XS(XS__istaskappropriate) { XSRETURN(1); } +XS(XS__gettaskname); +XS(XS__gettaskname) { + dXSARGS; + if (items != 1) { + Perl_croak(aTHX_ "Usage: quest::gettaskname(uint32 task_id)"); + } + + dXSTARG; + uint32 task_id = (int) SvIV(ST(0)); + std::string task_name = quest_manager.gettaskname(task_id); + + sv_setpv(TARG, task_name.c_str()); + XSprePUSH; + PUSHTARG; + XSRETURN(1); +} + XS(XS__popup); // prototype to pass -Wmissing-prototypes XS(XS__popup) { dXSARGS; @@ -4050,6 +4067,7 @@ EXTERN_C XS(boot_quest) { newXS(strcpy(buf, "getplayercorpsecount"), XS__getplayercorpsecount, file); newXS(strcpy(buf, "getplayercorpsecountbyzoneid"), XS__getplayercorpsecountbyzoneid, file); newXS(strcpy(buf, "gettaskactivitydonecount"), XS__gettaskactivitydonecount, file); + newXS(strcpy(buf, "gettaskname"), XS__gettaskname, file); newXS(strcpy(buf, "givecash"), XS__givecash, file); newXS(strcpy(buf, "gmmove"), XS__gmmove, file); newXS(strcpy(buf, "gmsay"), XS__gmsay, file); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 346ad4042..e388a9e1b 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -733,6 +733,10 @@ bool lua_is_task_appropriate(int task) { return quest_manager.istaskappropriate(task); } +std::string lua_get_task_name(uint32 task_id) { + return quest_manager.gettaskname(task_id); +} + void lua_popup(const char *title, const char *text, uint32 id, uint32 buttons, uint32 duration) { quest_manager.popup(title, text, id, buttons, duration); } @@ -1724,6 +1728,7 @@ luabind::scope lua_register_general() { luabind::def("active_tasks_in_set", &lua_active_tasks_in_set), luabind::def("completed_tasks_in_set", &lua_completed_tasks_in_set), luabind::def("is_task_appropriate", &lua_is_task_appropriate), + luabind::def("get_task_name", (std::string(*)(uint32))&lua_get_task_name), luabind::def("popup", &lua_popup), luabind::def("clear_spawn_timers", &lua_clear_spawn_timers), luabind::def("zone_emote", &lua_zone_emote), diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 7479767c3..7e0f9eb5f 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2441,6 +2441,16 @@ bool QuestManager::istaskappropriate(int task) { return false; } +std::string QuestManager::gettaskname(uint32 task_id) { + QuestManagerCurrentQuestVars(); + + if (RuleB(TaskSystem, EnableTaskSystem)) { + return taskmanager->GetTaskName(task_id); + } + + return std::string(); +} + void QuestManager::clearspawntimers() { if(!zone) return; diff --git a/zone/questmgr.h b/zone/questmgr.h index b5947b67e..04b16a902 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -214,6 +214,7 @@ public: int activetasksinset(int taskset); int completedtasksinset(int taskset); bool istaskappropriate(int task); + std::string gettaskname(uint32 task_id); void clearspawntimers(); void ze(int type, const char *str); void we(int type, const char *str); diff --git a/zone/tasks.cpp b/zone/tasks.cpp index 778a556e3..afa7b2062 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -955,6 +955,17 @@ bool TaskManager::AppropriateLevel(int TaskID, int PlayerLevel) { } +std::string TaskManager::GetTaskName(uint32 task_id) +{ + if (task_id > 0 && task_id < MAXTASKS) { + if (Tasks[task_id] != nullptr) { + return Tasks[task_id]->Title; + } + } + + return std::string(); +} + int TaskManager::GetTaskMinLevel(int TaskID) { if (Tasks[TaskID]->MinLevel) diff --git a/zone/tasks.h b/zone/tasks.h index 0bc45c146..48fc8e2cc 100644 --- a/zone/tasks.h +++ b/zone/tasks.h @@ -299,6 +299,7 @@ public: bool AppropriateLevel(int TaskID, int PlayerLevel); int GetTaskMinLevel(int TaskID); int GetTaskMaxLevel(int TaskID); + std::string GetTaskName(uint32 task_id); void TaskSetSelector(Client *c, ClientTaskState *state, Mob *mob, int TaskSetID); void TaskQuestSetSelector(Client *c, ClientTaskState *state, Mob *mob, int count, int *tasks); // task list provided by QuestManager (perl/lua) void SendActiveTasksToClient(Client *c, bool TaskComplete=false); From a4bf484c74e68e718c4420ff66eaac489a6aab7a Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 31 Mar 2020 23:09:19 -0400 Subject: [PATCH 42/42] Add CheckInstanceByCharID(instance_id, char_id) to Perl/Lua. --- zone/embparser_api.cpp | 20 ++++++++++++++++++++ zone/lua_general.cpp | 5 +++++ zone/questmgr.cpp | 4 ++++ zone/questmgr.h | 1 + 4 files changed, 30 insertions(+) diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 6e07ad9f0..c9ee6ea8a 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -3108,6 +3108,25 @@ XS(XS__RemoveFromInstanceByCharID) { XSRETURN_EMPTY; } +XS(XS__CheckInstanceByCharID); +XS(XS__CheckInstanceByCharID) { + dXSARGS; + if (items != 2) { + Perl_croak(aTHX_ "Usage: quest::CheckInstanceByCharID(uint16 instance_id, uint32 char_id)"); + } + + bool RETVAL; + dXSTARG; + + uint16 instance_id = (int) SvUV(ST(0)); + uint32 char_id = (int) SvUV(ST(1)); + RETVAL = quest_manager.CheckInstanceByCharID(instance_id, char_id); + XSprePUSH; + PUSHu((IV) RETVAL); + + XSRETURN(1); +} + XS(XS__RemoveAllFromInstance); XS(XS__RemoveAllFromInstance) { dXSARGS; @@ -3972,6 +3991,7 @@ EXTERN_C XS(boot_quest) { newXS(strcpy(buf, "RemoveAllFromInstance"), XS__RemoveAllFromInstance, file); newXS(strcpy(buf, "RemoveFromInstance"), XS__RemoveFromInstance, file); newXS(strcpy(buf, "RemoveFromInstanceByCharID"), XS__RemoveFromInstanceByCharID, file); + newXS(strcpy(buf, "CheckInstanceByCharID"), XS__CheckInstanceByCharID, file); newXS(strcpy(buf, "SendMail"), XS__SendMail, file); newXS(strcpy(buf, "SetRunning"), XS__SetRunning, file); newXS(strcpy(buf, "activespeakactivity"), XS__activespeakactivity, file); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 346ad4042..4c2358594 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -934,6 +934,10 @@ void lua_remove_from_instance_by_char_id(uint32 instance_id, uint32 char_id) { quest_manager.RemoveFromInstanceByCharID(instance_id, char_id); } +bool lua_check_instance_by_char_id(uint32 instance_id, uint32 char_id) { + return quest_manager.CheckInstanceByCharID(instance_id, char_id); +} + void lua_remove_all_from_instance(uint32 instance_id) { quest_manager.RemoveAllFromInstance(instance_id); } @@ -1772,6 +1776,7 @@ luabind::scope lua_register_general() { luabind::def("assign_raid_to_instance", &lua_assign_raid_to_instance), luabind::def("remove_from_instance", &lua_remove_from_instance), luabind::def("remove_from_instance_by_char_id", &lua_remove_from_instance_by_char_id), + luabind::def("check_instance_by_char_id", (bool(*)(uint16, uint32))&lua_check_instance_by_char_id), luabind::def("remove_all_from_instance", &lua_remove_all_from_instance), luabind::def("flag_instance_by_group_leader", &lua_flag_instance_by_group_leader), luabind::def("flag_instance_by_raid_leader", &lua_flag_instance_by_raid_leader), diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 7479767c3..30511c309 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2856,6 +2856,10 @@ void QuestManager::RemoveFromInstanceByCharID(uint16 instance_id, uint32 char_id database.RemoveClientFromInstance(instance_id, char_id); } +bool QuestManager::CheckInstanceByCharID(uint16 instance_id, uint32 char_id) { + return database.CharacterInInstanceGroup(instance_id, char_id); +} + void QuestManager::RemoveAllFromInstance(uint16 instance_id) { QuestManagerCurrentQuestVars(); diff --git a/zone/questmgr.h b/zone/questmgr.h index b5947b67e..b81e6fbe9 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -245,6 +245,7 @@ public: void AssignRaidToInstance(uint16 instance_id); void RemoveFromInstance(uint16 instance_id); void RemoveFromInstanceByCharID(uint16 instance_id, uint32 char_id); + bool CheckInstanceByCharID(uint16 instance_id, uint32 char_id); //void RemoveGroupFromInstance(uint16 instance_id); //potentially useful but not implmented at this time. //void RemoveRaidFromInstance(uint16 instance_id); //potentially useful but not implmented at this time. void RemoveAllFromInstance(uint16 instance_id);