Compare commits

...

25 Commits

Author SHA1 Message Date
Chris Miles 490cffb5ea [Release] 22.61.0 (#4587) 2025-01-06 00:27:11 -06:00
Alex King d95b64e0b8 [Cleanup] Fix GM Flag Spell Restriction Bypasses (#4571)
* [Cleanup] Fix GM Flag Spell Restriction Bypasses

* Update spells.cpp
2025-01-06 00:18:25 -06:00
Alex King 1ed282f6ff [Inventory] Add GetInventorySlots() Method (#4566)
* [Inventory] Add GetInventorySlots() Method

* Update client.cpp

* Push
2025-01-05 23:48:39 -06:00
Chris Miles a3a498634f [Maps] Fix broken Map MMFS implementation (#4576) 2025-01-05 23:48:09 -06:00
Chris Miles c44596b38a [Network] Prune / disconnect TCP connections gracefully (#4574) 2025-01-05 23:48:00 -06:00
Mitch Freeman fe43d26dd6 [Fix] Guild creation to propagate across zones (#4575)
Fix guild creation to propagate across zones
2025-01-05 23:47:22 -06:00
Chris Miles 3155b82abb [Command] Fix #copycharacter (#4582)
* [Command] Fix #copycharacter

* Update copy_character.cpp
2025-01-05 23:46:59 -06:00
Chris Miles 4c6aaa6995 [Logs] Improve Crash log defaults (#4579) 2025-01-05 23:46:43 -06:00
Mitch Freeman c82dee575a [Fix] Guild Membership Update Fix (#4581)
When the guild membership was large (1k+) the client would studder for half a sec when a guild member would login or logout.  This was reproduceable with a guild size of 2k members though floor would be client dependent most likely.
2025-01-05 23:46:19 -06:00
Mitch Freeman 33db85f2ee [Fix] Repair a EQEMUConfig Memory Leak (#4584)
Co-authored-by: Mitch Freeman <neckkola@gmail.com>
2025-01-05 23:45:28 -06:00
Mitch Freeman b40e4ce7cd [Fix] Repair a memory leak in GuildsList (#4585)
There was a leak generated when sending the GuildsList

Co-authored-by: Mitch Freeman <neckkola@gmail.com>
2025-01-05 23:45:09 -06:00
Mitch Freeman 20ff325013 [Fix] Repair a LoadNPCEmote MemoryLeak (#4586) 2025-01-05 23:44:51 -06:00
Chris Miles 8a7d5e72cb [Filesystem] Path Manager Improvements (#4557)
* [Filesystem] Path Manager Improvements

* Update path_manager.cpp

* Use native fs path building syntax
2025-01-05 23:44:16 -06:00
Mitch Freeman 4493ebebab [Bug Fix] Resolve a client crash when logging in or zoning (#4572) 2024-12-14 14:27:43 -05:00
Alex King 77793f364e [Commands] Add #find bot Subcommand (#4563)
* [Commands] Add #find bot Subcommand

* Update find.cpp

* Update find.cpp
2024-12-12 16:55:33 -06:00
Alex King e258aaa068 [Bug Fix] Allow Items in ROF2 to Stack to 32,767 (#4556)
* [Bug Fix] Allow Items in ROF2 to Stack to 32,767

* Update rof2.cpp
2024-12-12 16:39:38 -06:00
Paul Johnson 3b779ef301 [Rules] Add rules for requiring custom files from client (#4561)
* rules for enabling requiring custom files

* shorten default

* variable name

* check account status for enforcing client key

* rule for custom files admin level

---------

Co-authored-by: Paul Johnson <Paul@pjohnsomac-6366.digi.box>
2024-12-12 01:47:50 -06:00
Alex King 3f3c0f2fda [Commands] Add #find ldon_theme Subcommand (#4564) 2024-12-12 01:27:25 -06:00
Alex King 0f164c456e [Cleanup] Remove Unused Group Methods (#4559) 2024-12-12 01:25:36 -06:00
Mitch Freeman 6172c49b08 [Feature] Enable bazaar window 'Find Trader' functionality (#4560)
* First pass to enable trader 'Find Trader' functionality

* Move SendBulkTraders out of zoning routines and send as part of the opening of the bazaar search window.
Add zone instance to SendBulkTraders to support multi-instanced bazaars.
2024-12-12 01:25:12 -06:00
Chris Miles 66a7dd0143 [Databuckets] Improved Reliability and Performance of Databuckets (#4562)
* [Databuckets] Don't broadcast client-scoped updates

* Remove temp feature flag

* Remove distributed caching, only cache for character scoped data, simplify

* Update bot.cpp

* Cleanup

* Update data_bucket.cpp

* Cleanup

* Cleanup

* Remove BulkLoadEntities from LoadNPCTypes

* Update data_bucket.cpp

* Cleanup

* More cleanup

* More cleanup

* BulkLoadEntities to BulkLoadEntitiesToCache

* Add CanCache in DeleteData to gate an unnecessary call
2024-12-12 01:17:08 -06:00
Alex King 5c6e7a8b09 [Cleanup] Convert Event Parses to Single Line (#4569)
* [Cleanup] Convert Event Parses to Single Line

* Push

* Update spells.cpp

* Update spells.cpp

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2024-12-12 00:43:22 -06:00
dependabot[bot] bd85fc96a0 Bump golang.org/x/crypto in /utils/scripts/build/should-release (#4570)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.21.0 to 0.31.0.
- [Commits](https://github.com/golang/crypto/compare/v0.21.0...v0.31.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-12 00:17:28 -06:00
nytmyr 8e40e5357c [Bots] Fix AA ranks to account for level (#4567)
Previously level requirement was only being checked on the initial rank of an AA. If passed, bots would gain all ranks for that AA regardless of level, this will now check for the level requirement for each rank before granting the AA
2024-12-06 23:58:11 -05:00
nytmyr 5f0b999ca9 [Groups] Fix AmIMainAssist incorrectly checking for MainTankName (#4565) 2024-12-04 16:04:34 -05:00
93 changed files with 1262 additions and 1310 deletions
+65
View File
@@ -1,3 +1,68 @@
## [22.61.0] 1/6/2025
### Bots
* Fix AA ranks to account for level ([#4567](https://github.com/EQEmu/Server/pull/4567)) @nytmyr 2024-12-07
### Code
* Convert Event Parses to Single Line ([#4569](https://github.com/EQEmu/Server/pull/4569)) @Kinglykrab 2024-12-12
* Fix GM Flag Spell Restriction Bypasses ([#4571](https://github.com/EQEmu/Server/pull/4571)) @Kinglykrab 2025-01-06
* Remove Unused Group Methods ([#4559](https://github.com/EQEmu/Server/pull/4559)) @Kinglykrab 2024-12-12
### Commands
* Add #find bot Subcommand ([#4563](https://github.com/EQEmu/Server/pull/4563)) @Kinglykrab 2024-12-12
* Add #find ldon_theme Subcommand ([#4564](https://github.com/EQEmu/Server/pull/4564)) @Kinglykrab 2024-12-12
* Fix #copycharacter ([#4582](https://github.com/EQEmu/Server/pull/4582)) @Akkadius 2025-01-06
### Databuckets
* Improved Reliability and Performance of Databuckets ([#4562](https://github.com/EQEmu/Server/pull/4562)) @Akkadius 2024-12-12
### Feature
* Enable bazaar window 'Find Trader' functionality ([#4560](https://github.com/EQEmu/Server/pull/4560)) @neckkola 2024-12-12
### Filesystem
* Path Manager Improvements ([#4557](https://github.com/EQEmu/Server/pull/4557)) @Akkadius 2025-01-06
### Fixes
* Allow Items in ROF2 to Stack to 32,767 ([#4556](https://github.com/EQEmu/Server/pull/4556)) @Kinglykrab 2024-12-12
* Fix EVENT_COMBAT on NPC Death ([#4558](https://github.com/EQEmu/Server/pull/4558)) @Kinglykrab 2024-11-28
* Guild Membership Update Fix ([#4581](https://github.com/EQEmu/Server/pull/4581)) @neckkola 2025-01-06
* Guild creation to propagate across zones ([#4575](https://github.com/EQEmu/Server/pull/4575)) @neckkola 2025-01-06
* Repair a EQEMUConfig Memory Leak ([#4584](https://github.com/EQEmu/Server/pull/4584)) @neckkola 2025-01-06
* Repair a LoadNPCEmote MemoryLeak ([#4586](https://github.com/EQEmu/Server/pull/4586)) @neckkola 2025-01-06
* Repair a memory leak in GuildsList ([#4585](https://github.com/EQEmu/Server/pull/4585)) @neckkola 2025-01-06
* Resolve a client crash when logging in or zoning ([#4572](https://github.com/EQEmu/Server/pull/4572)) @neckkola 2024-12-14
### Groups
* Fix AmIMainAssist incorrectly checking for MainTankName ([#4565](https://github.com/EQEmu/Server/pull/4565)) @nytmyr 2024-12-04
### Inventory
* Add GetInventorySlots() Method ([#4566](https://github.com/EQEmu/Server/pull/4566)) @Kinglykrab 2025-01-06
### Logs
* Improve Crash log defaults ([#4579](https://github.com/EQEmu/Server/pull/4579)) @Akkadius 2025-01-06
### Maps
* Fix broken Map MMFS implementation ([#4576](https://github.com/EQEmu/Server/pull/4576)) @Akkadius 2025-01-06
### Network
* Prune / disconnect TCP connections gracefully ([#4574](https://github.com/EQEmu/Server/pull/4574)) @Akkadius 2025-01-06
### Rules
* Add rules for requiring custom files from client ([#4561](https://github.com/EQEmu/Server/pull/4561)) @knervous 2024-12-12
## [22.60.0] 11/25/2024 ## [22.60.0] 11/25/2024
### Bazaar ### Bazaar
+3
View File
@@ -37,6 +37,9 @@ IF(EQEMU_ADD_PROFILER)
SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--no-as-needed,-lprofiler,--as-needed") SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--no-as-needed,-lprofiler,--as-needed")
ENDIF(EQEMU_ADD_PROFILER) ENDIF(EQEMU_ADD_PROFILER)
IF(USE_MAP_MMFS)
ADD_DEFINITIONS(-DUSE_MAP_MMFS)
ENDIF (USE_MAP_MMFS)
IF(MSVC) IF(MSVC)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
+15 -7
View File
@@ -8,13 +8,14 @@ std::vector<BazaarSearchResultsFromDB_Struct>
Bazaar::GetSearchResults( Bazaar::GetSearchResults(
SharedDatabase &db, SharedDatabase &db,
BazaarSearchCriteria_Struct search, BazaarSearchCriteria_Struct search,
uint32 char_zone_id uint32 char_zone_id,
int32 char_zone_instance_id
) )
{ {
LogTrading( LogTrading(
"Searching for items with search criteria - item_name [{}] min_cost [{}] max_cost [{}] min_level [{}] " "Searching for items with search criteria - item_name [{}] min_cost [{}] max_cost [{}] min_level [{}] "
"max_level [{}] max_results [{}] prestige [{}] augment [{}] trader_entity_id [{}] trader_id [{}] " "max_level [{}] max_results [{}] prestige [{}] augment [{}] trader_entity_id [{}] trader_id [{}] "
"search_scope [{}] char_zone_id [{}]", "search_scope [{}] char_zone_id [{}], char_zone_instance_id [{}]",
search.item_name, search.item_name,
search.min_cost, search.min_cost,
search.max_cost, search.max_cost,
@@ -26,7 +27,8 @@ Bazaar::GetSearchResults(
search.trader_entity_id, search.trader_entity_id,
search.trader_id, search.trader_id,
search.search_scope, search.search_scope,
char_zone_id char_zone_id,
char_zone_instance_id
); );
std::string search_criteria_trader("TRUE "); std::string search_criteria_trader("TRUE ");
@@ -34,14 +36,19 @@ Bazaar::GetSearchResults(
if (search.search_scope == NonRoFBazaarSearchScope) { if (search.search_scope == NonRoFBazaarSearchScope) {
search_criteria_trader.append( search_criteria_trader.append(
fmt::format( fmt::format(
" AND trader.char_entity_id = {} AND trader.char_zone_id = {}", " AND trader.char_entity_id = {} AND trader.char_zone_id = {} AND trader.char_zone_instance_id = {}",
search.trader_entity_id, search.trader_entity_id,
Zones::BAZAAR Zones::BAZAAR,
char_zone_instance_id
) )
); );
} }
else if (search.search_scope == Local_Scope) { else if (search.search_scope == Local_Scope) {
search_criteria_trader.append(fmt::format(" AND trader.char_zone_id = {}", char_zone_id)); search_criteria_trader.append(fmt::format(
" AND trader.char_zone_id = {} AND trader.char_zone_instance_id = {}",
char_zone_id,
char_zone_instance_id)
);
} }
else if (search.trader_id > 0) { else if (search.trader_id > 0) {
search_criteria_trader.append(fmt::format(" AND trader.char_id = {}", search.trader_id)); search_criteria_trader.append(fmt::format(" AND trader.char_id = {}", search.trader_id));
@@ -62,7 +69,7 @@ Bazaar::GetSearchResults(
std::string query = fmt::format( std::string query = fmt::format(
"SELECT COUNT(item_id), trader.char_id, trader.item_id, trader.item_sn, trader.item_charges, trader.item_cost, " "SELECT COUNT(item_id), trader.char_id, trader.item_id, trader.item_sn, trader.item_charges, trader.item_cost, "
"trader.slot_id, SUM(trader.item_charges), trader.char_zone_id, trader.char_entity_id, character_data.name, " "trader.slot_id, SUM(trader.item_charges), trader.char_zone_id, trader.char_entity_id, character_data.name, "
"aug_slot_1, aug_slot_2, aug_slot_3, aug_slot_4, aug_slot_5, aug_slot_6 " "aug_slot_1, aug_slot_2, aug_slot_3, aug_slot_4, aug_slot_5, aug_slot_6, trader.char_zone_instance_id "
"FROM trader, character_data " "FROM trader, character_data "
"WHERE {} AND trader.char_id = character_data.id " "WHERE {} AND trader.char_id = character_data.id "
"GROUP BY trader.item_sn, trader.item_charges, trader.char_id", "GROUP BY trader.item_sn, trader.item_charges, trader.char_id",
@@ -131,6 +138,7 @@ Bazaar::GetSearchResults(
r.stackable = item->Stackable; r.stackable = item->Stackable;
r.icon_id = item->Icon; r.icon_id = item->Icon;
r.trader_zone_id = Strings::ToInt(row[8]); r.trader_zone_id = Strings::ToInt(row[8]);
r.trader_zone_instance_id = Strings::ToInt(row[17]);
r.trader_entity_id = Strings::ToInt(row[9]); r.trader_entity_id = Strings::ToInt(row[9]);
r.serial_number_RoF = fmt::format("{:016}\0", Strings::ToInt(row[3])); r.serial_number_RoF = fmt::format("{:016}\0", Strings::ToInt(row[3]));
r.item_name = fmt::format("{:.63}\0", item->Name); r.item_name = fmt::format("{:.63}\0", item->Name);
+1 -1
View File
@@ -7,7 +7,7 @@
class Bazaar { class Bazaar {
public: public:
static std::vector<BazaarSearchResultsFromDB_Struct> static std::vector<BazaarSearchResultsFromDB_Struct>
GetSearchResults(SharedDatabase &db, BazaarSearchCriteria_Struct search, unsigned int char_zone_id); GetSearchResults(SharedDatabase &db, BazaarSearchCriteria_Struct search, unsigned int char_zone_id, int char_zone_instance_id);
}; };
+2
View File
@@ -294,6 +294,8 @@ void print_trace()
SendCrashReport(crash_report); SendCrashReport(crash_report);
} }
LogSys.CloseFileLogs();
exit(1); exit(1);
} }
+49 -1
View File
@@ -1860,7 +1860,35 @@ bool Database::CopyCharacter(
const int64 new_character_id = (CharacterDataRepository::GetMaxId(*this) + 1); const int64 new_character_id = (CharacterDataRepository::GetMaxId(*this) + 1);
std::vector<std::string> tables_to_zero_id = { "keyring", "data_buckets", "character_instance_safereturns" }; // validate destination name doesn't exist already
const auto& destination_characters = CharacterDataRepository::GetWhere(
*this,
fmt::format(
"`name` = '{}' AND `deleted_at` IS NULL LIMIT 1",
Strings::Escape(destination_character_name)
)
);
if (!destination_characters.empty()) {
LogError("Character [{}] already exists", destination_character_name);
return false;
}
std::vector<std::string> tables_to_zero_id = {
"keyring",
"data_buckets",
"character_instance_safereturns",
"character_expedition_lockouts",
"character_instance_lockouts",
"character_parcels",
"character_tribute",
"player_titlesets",
};
std::vector<std::string> ignore_tables = {
"guilds",
};
size_t total_rows_copied = 0;
TransactionBegin(); TransactionBegin();
@@ -1868,6 +1896,10 @@ bool Database::CopyCharacter(
const std::string& table_name = t.first; const std::string& table_name = t.first;
const std::string& character_id_column_name = t.second; const std::string& character_id_column_name = t.second;
if (Strings::Contains(ignore_tables, table_name)) {
continue;
}
auto results = QueryDatabase( auto results = QueryDatabase(
fmt::format( fmt::format(
"SHOW COLUMNS FROM {}", "SHOW COLUMNS FROM {}",
@@ -1918,6 +1950,10 @@ bool Database::CopyCharacter(
value = std::to_string(destination_account_id); value = std::to_string(destination_account_id);
} }
if (!Strings::IsNumber(value)) {
value = Strings::Escape(value);
}
new_values.emplace_back(value); new_values.emplace_back(value);
} }
@@ -1950,6 +1986,11 @@ bool Database::CopyCharacter(
) )
); );
size_t rows_copied = insert_rows.size(); // Rows copied for this table
total_rows_copied += rows_copied; // Increment grand total
LogInfo("Copying table [{}] rows [{}]", table_name, Strings::Commify(rows_copied));
if (!insert.ErrorMessage().empty()) { if (!insert.ErrorMessage().empty()) {
TransactionRollback(); TransactionRollback();
return false; return false;
@@ -1959,6 +2000,13 @@ bool Database::CopyCharacter(
TransactionCommit(); TransactionCommit();
LogInfo(
"Character [{}] copied to [{}] total rows [{}]",
source_character_name,
destination_character_name,
Strings::Commify(total_rows_copied)
);
return true; return true;
} }
@@ -5770,6 +5770,17 @@ MODIFY COLUMN `exp_modifier` float NOT NULL DEFAULT 1.0 AFTER `aa_modifier`;
CREATE INDEX idx_character_expires ON data_buckets (character_id, expires); CREATE INDEX idx_character_expires ON data_buckets (character_id, expires);
CREATE INDEX idx_npc_expires ON data_buckets (npc_id, expires); CREATE INDEX idx_npc_expires ON data_buckets (npc_id, expires);
CREATE INDEX idx_bot_expires ON data_buckets (bot_id, expires); CREATE INDEX idx_bot_expires ON data_buckets (bot_id, expires);
)"
},
ManifestEntry{
.version = 9286,
.description = "2024_11_26_bazaar_find_trader.sql",
.check = "SHOW COLUMNS FROM `trader` LIKE 'char_zone_instance_id'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `trader`
ADD COLUMN `char_zone_instance_id` INT NULL DEFAULT '0' AFTER `char_zone_id`;
)" )"
} }
// -- template; copy/paste this when you need to create a new entry // -- template; copy/paste this when you need to create a new entry
+15 -23
View File
@@ -140,29 +140,6 @@ std::string EQ::constants::GetLanguageName(uint8 language_id)
return EQ::constants::GetLanguageMap().find(language_id)->second; return EQ::constants::GetLanguageMap().find(language_id)->second;
} }
const std::map<uint32, std::string>& EQ::constants::GetLDoNThemeMap()
{
static const std::map<uint32, std::string> ldon_theme_map = {
{ LDoNThemes::Unused, "Unused" },
{ LDoNThemes::GUK, "Deepest Guk" },
{ LDoNThemes::MIR, "Miragul's Menagerie" },
{ LDoNThemes::MMC, "Mistmoore Catacombs" },
{ LDoNThemes::RUJ, "Rujarkian Hills" },
{ LDoNThemes::TAK, "Takish-Hiz" },
};
return ldon_theme_map;
}
std::string EQ::constants::GetLDoNThemeName(uint32 theme_id)
{
if (!EQ::ValueWithin(theme_id, LDoNThemes::Unused, LDoNThemes::TAK)) {
return std::string();
}
return EQ::constants::GetLDoNThemeMap().find(theme_id)->second;
}
const std::map<int8, std::string>& EQ::constants::GetFlyModeMap() const std::map<int8, std::string>& EQ::constants::GetFlyModeMap()
{ {
static const std::map<int8, std::string> flymode_map = { static const std::map<int8, std::string> flymode_map = {
@@ -459,3 +436,18 @@ bool ComparisonType::IsValid(uint8 type)
{ {
return comparison_types.find(type) != comparison_types.end(); return comparison_types.find(type) != comparison_types.end();
} }
uint32 LDoNTheme::GetBitmask(uint32 theme_id)
{
return IsValid(theme_id) ? ldon_theme_names[theme_id].second : LDoNTheme::UnusedBit;
}
std::string LDoNTheme::GetName(uint32 theme_id)
{
return IsValid(theme_id) ? ldon_theme_names[theme_id].first : "UNKNOWN LDON THEME";
}
bool LDoNTheme::IsValid(uint32 theme_id)
{
return ldon_theme_names.find(theme_id) != ldon_theme_names.end();
}
+29 -3
View File
@@ -352,9 +352,6 @@ namespace EQ
extern const std::map<uint8, std::string>& GetLanguageMap(); extern const std::map<uint8, std::string>& GetLanguageMap();
std::string GetLanguageName(uint8 language_id); std::string GetLanguageName(uint8 language_id);
extern const std::map<uint32, std::string>& GetLDoNThemeMap();
std::string GetLDoNThemeName(uint32 theme_id);
extern const std::map<int8, std::string>& GetFlyModeMap(); extern const std::map<int8, std::string>& GetFlyModeMap();
std::string GetFlyModeName(int8 flymode_id); std::string GetFlyModeName(int8 flymode_id);
@@ -751,6 +748,35 @@ static std::map<uint32, std::string> stance_names = {
{ Stance::AEBurn, "AE Burn" } { Stance::AEBurn, "AE Burn" }
}; };
namespace LDoNTheme {
constexpr uint32 Unused = 0;
constexpr uint32 GUK = 1;
constexpr uint32 MIR = 2;
constexpr uint32 MMC = 3;
constexpr uint32 RUJ = 4;
constexpr uint32 TAK = 5;
constexpr uint32 UnusedBit = 0;
constexpr uint32 GUKBit = 1;
constexpr uint32 MIRBit = 2;
constexpr uint32 MMCBit = 4;
constexpr uint32 RUJBit = 8;
constexpr uint32 TAKBit = 16;
uint32 GetBitmask(uint32 theme_id);
std::string GetName(uint32 theme_id);
bool IsValid(uint32 theme_id);
}
static std::map<uint32, std::pair<std::string, uint32>> ldon_theme_names = {
{ LDoNTheme::Unused, { "Unused", LDoNTheme::UnusedBit }, },
{ LDoNTheme::GUK, { "Deepest Guk", LDoNTheme::GUKBit }, },
{ LDoNTheme::MIR, { "Miragul's Menagerie", LDoNTheme::MIRBit }, },
{ LDoNTheme::MMC, { "Mistmoore Catacombs", LDoNTheme::MMCBit }, },
{ LDoNTheme::RUJ, { "Rujarkian Hills", LDoNTheme::RUJBit }, },
{ LDoNTheme::TAK, { "Takish-Hiz", LDoNTheme::TAKBit }, },
};
namespace PCNPCOnlyFlagType { namespace PCNPCOnlyFlagType {
constexpr int PC = 1; constexpr int PC = 1;
constexpr int NPC = 2; constexpr int NPC = 2;
-18
View File
@@ -993,24 +993,6 @@ enum class DynamicZoneMemberStatus : uint8_t
LinkDead LinkDead
}; };
enum LDoNThemes {
Unused = 0,
GUK,
MIR,
MMC,
RUJ,
TAK
};
enum LDoNThemeBits {
UnusedBit = 0,
GUKBit = 1,
MIRBit = 2,
MMCBit = 4,
RUJBit = 8,
TAKBit = 16
};
enum StartZoneIndex { enum StartZoneIndex {
Odus = 0, Odus = 0,
Qeynos, Qeynos,
+5 -1
View File
@@ -3742,7 +3742,8 @@ struct GetItems_Struct{
struct BecomeTrader_Struct { struct BecomeTrader_Struct {
uint32 action; uint32 action;
uint32 zone_id; uint16 zone_id;
uint16 zone_instance_id;
uint32 trader_id; uint32 trader_id;
uint32 entity_id; uint32 entity_id;
char trader_name[64]; char trader_name[64];
@@ -6347,6 +6348,7 @@ enum BazaarTraderBarterActions {
TraderAck2 = 22, TraderAck2 = 22,
AddTraderToBazaarWindow = 24, AddTraderToBazaarWindow = 24,
RemoveTraderFromBazaarWindow = 25, RemoveTraderFromBazaarWindow = 25,
FirstOpenSearch = 26,
ClickTrader = 28, ClickTrader = 28,
DeliveryCostUpdate = 29 DeliveryCostUpdate = 29
}; };
@@ -6386,6 +6388,7 @@ struct BazaarSearchResultsFromDB_Struct {
uint32 icon_id; uint32 icon_id;
uint32 sum_charges; uint32 sum_charges;
uint32 trader_zone_id; uint32 trader_zone_id;
int32 trader_zone_instance_id;
uint32 trader_entity_id; uint32 trader_entity_id;
uint32 item_stat; uint32 item_stat;
bool stackable; bool stackable;
@@ -6407,6 +6410,7 @@ struct BazaarSearchResultsFromDB_Struct {
CEREAL_NVP(icon_id), CEREAL_NVP(icon_id),
CEREAL_NVP(sum_charges), CEREAL_NVP(sum_charges),
CEREAL_NVP(trader_zone_id), CEREAL_NVP(trader_zone_id),
CEREAL_NVP(trader_zone_instance_id),
CEREAL_NVP(trader_entity_id), CEREAL_NVP(trader_entity_id),
CEREAL_NVP(item_stat), CEREAL_NVP(item_stat),
CEREAL_NVP(stackable), CEREAL_NVP(stackable),
+1 -1
View File
@@ -137,9 +137,9 @@ class EQEmuConfig
{ {
} }
virtual ~EQEmuConfig() {}
public: public:
virtual ~EQEmuConfig() {}
// Produce a const singleton // Produce a const singleton
static const EQEmuConfig *get() static const EQEmuConfig *get()
+8
View File
@@ -25,6 +25,8 @@
#include "repositories/discord_webhooks_repository.h" #include "repositories/discord_webhooks_repository.h"
#include "repositories/logsys_categories_repository.h" #include "repositories/logsys_categories_repository.h"
#include "termcolor/rang.hpp" #include "termcolor/rang.hpp"
#include "path_manager.h"
#include "file.h"
#include <iostream> #include <iostream>
#include <string> #include <string>
@@ -85,6 +87,7 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
* Set Defaults * Set Defaults
*/ */
log_settings[Logs::Crash].log_to_console = static_cast<uint8>(Logs::General); log_settings[Logs::Crash].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Crash].log_to_file = static_cast<uint8>(Logs::General);
log_settings[Logs::MySQLError].log_to_console = static_cast<uint8>(Logs::General); log_settings[Logs::MySQLError].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::NPCScaling].log_to_gmsay = static_cast<uint8>(Logs::General); log_settings[Logs::NPCScaling].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::HotReload].log_to_gmsay = static_cast<uint8>(Logs::General); log_settings[Logs::HotReload].log_to_gmsay = static_cast<uint8>(Logs::General);
@@ -532,6 +535,11 @@ void EQEmuLogSys::StartFileLogs(const std::string &log_name)
{ {
EQEmuLogSys::CloseFileLogs(); EQEmuLogSys::CloseFileLogs();
if (!File::Exists(path.GetLogPath())) {
LogInfo("Logs directory not found, creating [{}]", path.GetLogPath());
File::Makedir(path.GetLogPath());
}
/** /**
* When loading settings, we must have been given a reason in category based logging to output to a file in order to even create or open one... * When loading settings, we must have been given a reason in category based logging to output to a file in order to even create or open one...
*/ */
+4 -4
View File
@@ -612,9 +612,9 @@ bool EQ::InventoryProfile::HasAugmentEquippedByID(uint32 item_id)
return has_equipped; return has_equipped;
} }
int EQ::InventoryProfile::CountAugmentEquippedByID(uint32 item_id) uint32 EQ::InventoryProfile::CountAugmentEquippedByID(uint32 item_id)
{ {
int quantity = 0; uint32 quantity = 0;
ItemInstance* item = nullptr; ItemInstance* item = nullptr;
for (int slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) { for (int slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
@@ -643,9 +643,9 @@ bool EQ::InventoryProfile::HasItemEquippedByID(uint32 item_id)
return has_equipped; return has_equipped;
} }
int EQ::InventoryProfile::CountItemEquippedByID(uint32 item_id) uint32 EQ::InventoryProfile::CountItemEquippedByID(uint32 item_id)
{ {
int quantity = 0; uint32 quantity = 0;
ItemInstance* item = nullptr; ItemInstance* item = nullptr;
for (int slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) { for (int slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
+2 -2
View File
@@ -147,13 +147,13 @@ namespace EQ
bool HasItemEquippedByID(uint32 item_id); bool HasItemEquippedByID(uint32 item_id);
// Check how many of a specific item the player has equipped by Item ID // Check how many of a specific item the player has equipped by Item ID
int CountItemEquippedByID(uint32 item_id); uint32 CountItemEquippedByID(uint32 item_id);
// Check if player has a specific augment equipped by Item ID // Check if player has a specific augment equipped by Item ID
bool HasAugmentEquippedByID(uint32 item_id); bool HasAugmentEquippedByID(uint32 item_id);
// Check how many of a specific augment the player has equipped by Item ID // Check how many of a specific augment the player has equipped by Item ID
int CountAugmentEquippedByID(uint32 item_id); uint32 CountAugmentEquippedByID(uint32 item_id);
// Get a list of augments from a specific slot ID // Get a list of augments from a specific slot ID
std::vector<uint32> GetAugmentIDsBySlotID(int16 slot_id); std::vector<uint32> GetAugmentIDsBySlotID(int16 slot_id);
+2
View File
@@ -80,6 +80,8 @@ void EQ::Net::TCPConnection::Start() {
} }
} }
else if (nread == UV_EOF) { else if (nread == UV_EOF) {
connection->Disconnect();
if (buf->base) { if (buf->base) {
delete[] buf->base; delete[] buf->base;
} }
+26 -10
View File
@@ -587,15 +587,17 @@ namespace RoF2
eq->entity_id = emu->entity_id; eq->entity_id = emu->entity_id;
eq->trader_id = emu->trader_id; eq->trader_id = emu->trader_id;
eq->zone_id = emu->zone_id; eq->zone_id = emu->zone_id;
eq->zone_instance_id = emu->zone_instance_id;
strn0cpy(eq->trader_name, emu->trader_name, sizeof(eq->trader_name)); strn0cpy(eq->trader_name, emu->trader_name, sizeof(eq->trader_name));
LogTrading( LogTrading(
"(RoF2) AddTraderToBazaarWindow action <green>[{}] trader_id <green>[{}] entity_id <green>[{}] zone_id <green>[{}]", "(RoF2) AddTraderToBazaarWindow action <green>[{}] trader_id <green>[{}] entity_id <green>[{}] "
"zone_id <green>[{}] zone_instance_id <green>[{}]",
eq->action, eq->action,
eq->trader_id, eq->trader_id,
eq->entity_id, eq->entity_id,
eq->zone_id eq->zone_id,
); eq->zone_instance_id);
dest->FastQueuePacket(&outapp); dest->FastQueuePacket(&outapp);
break; break;
} }
@@ -1843,11 +1845,11 @@ namespace RoF2
} }
} }
auto outapp = new EQApplicationPacket(OP_GuildsList); safe_delete_array(in->pBuffer);
outapp->size = packet_size;
outapp->pBuffer = buffer;
dest->FastQueuePacket(&outapp); in->pBuffer = buffer;
in->size = packet_size;
dest->FastQueuePacket(&in);
} }
ENCODE(OP_GuildTributeDonateItem) ENCODE(OP_GuildTributeDonateItem)
@@ -6218,6 +6220,11 @@ namespace RoF2
FINISH_DIRECT_DECODE(); FINISH_DIRECT_DECODE();
break; break;
} }
case structs::RoF2BazaarTraderBuyerActions::FirstOpenSearch: {
__packet->SetOpcode(OP_BazaarSearch);
LogTrading("(RoF2) First time opening Bazaar Search since zoning. Action <green>[{}]", action);
break;
}
case structs::RoF2BazaarTraderBuyerActions::WelcomeMessage: { case structs::RoF2BazaarTraderBuyerActions::WelcomeMessage: {
__packet->SetOpcode(OP_BazaarSearch); __packet->SetOpcode(OP_BazaarSearch);
LogTrading("(RoF2) WelcomeMessage action <green>[{}]", action); LogTrading("(RoF2) WelcomeMessage action <green>[{}]", action);
@@ -6358,9 +6365,18 @@ namespace RoF2
//sprintf(hdr.unknown000, "06e0002Y1W00"); //sprintf(hdr.unknown000, "06e0002Y1W00");
strn0cpy(hdr.unknown000, fmt::format("{:016}\0", inst->GetSerialNumber()).c_str(),sizeof(hdr.unknown000)); strn0cpy(hdr.unknown000, fmt::format("{:016}\0", inst->GetSerialNumber()).c_str(),sizeof(hdr.unknown000));
hdr.stacksize = hdr.stacksize = 1;
item->ID == PARCEL_MONEY_ITEM_ID ? inst->GetPrice() : (inst->IsStackable() ? ((inst->GetCharges() > 1000)
? 0xFFFFFFFF : inst->GetCharges()) : 1); if (item->ID == PARCEL_MONEY_ITEM_ID) {
hdr.stacksize = inst->GetPrice();
} else if (inst->IsStackable()) {
if (inst->GetCharges() > std::numeric_limits<int16>::max()) {
hdr.stacksize = std::numeric_limits<uint32>::max();
} else {
hdr.stacksize = inst->GetCharges();
}
}
hdr.unknown004 = 0; hdr.unknown004 = 0;
structs::InventorySlot_Struct slot_id{}; structs::InventorySlot_Struct slot_id{};
+2 -1
View File
@@ -3119,7 +3119,8 @@ enum RoF2BazaarTraderBuyerActions {
BazaarInspect = 18, BazaarInspect = 18,
ClickTrader = 28, ClickTrader = 28,
ItemMove = 19, ItemMove = 19,
ReconcileItems = 20 ReconcileItems = 20,
FirstOpenSearch = 26
}; };
enum RoF2BuyerActions { enum RoF2BuyerActions {
+48 -62
View File
@@ -5,31 +5,19 @@
#include "strings.h" #include "strings.h"
#include <filesystem> #include <filesystem>
namespace fs = std::filesystem; namespace fs = std::filesystem;
inline std::string striptrailingslash(const std::string &file_path)
{
if (file_path.back() == '/' || file_path.back() == '\\') {
return file_path.substr(0, file_path.length() - 1);
}
return file_path;
}
void PathManager::LoadPaths() void PathManager::LoadPaths()
{ {
m_server_path = File::FindEqemuConfigPath(); m_server_path = File::FindEqemuConfigPath();
if (!m_server_path.empty()) {
std::filesystem::current_path(m_server_path);
}
if (m_server_path.empty()) { if (m_server_path.empty()) {
LogInfo("Failed to load server path"); LogInfo("Failed to load server path");
return; return;
} }
LogInfo("server [{}]", m_server_path); std::filesystem::current_path(m_server_path);
if (!EQEmuConfig::LoadConfig()) { if (!EQEmuConfig::LoadConfig()) {
LogError("Failed to load eqemu config"); LogError("Failed to load eqemu config");
@@ -38,66 +26,64 @@ void PathManager::LoadPaths()
const auto c = EQEmuConfig::get(); const auto c = EQEmuConfig::get();
// maps auto resolve_path = [&](const std::string& dir, const std::vector<std::string>& fallback_dirs = {}) -> std::string {
if (File::Exists(fs::path{m_server_path + "/" + c->MapDir}.string())) { // relative
m_maps_path = fs::relative(fs::path{m_server_path + "/" + c->MapDir}).string(); if (File::Exists((fs::path{m_server_path} / dir).string())) {
} return fs::relative(fs::path{m_server_path} / dir).lexically_normal().string();
else if (File::Exists(fs::path{m_server_path + "/maps"}.string())) {
m_maps_path = fs::relative(fs::path{m_server_path + "/maps"}).string();
}
else if (File::Exists(fs::path{m_server_path + "/Maps"}.string())) {
m_maps_path = fs::relative(fs::path{m_server_path + "/Maps"}).string();
} }
// quests // absolute
if (File::Exists(fs::path{m_server_path + "/" + c->QuestDir}.string())) { if (File::Exists(fs::path{dir}.string())) {
m_quests_path = fs::relative(fs::path{m_server_path + "/" + c->QuestDir}).string(); return fs::absolute(fs::path{dir}).string();
} }
// plugins // fallback search options if specified
if (File::Exists(fs::path{m_server_path + "/" + c->PluginDir}.string())) { for (const auto& fallback : fallback_dirs) {
m_plugins_path = fs::relative(fs::path{m_server_path + "/" + c->PluginDir}).string(); if (File::Exists((fs::path{m_server_path} / fallback).string())) {
return fs::relative(fs::path{m_server_path} / fallback).lexically_normal().string();
}
} }
// lua_modules // if all else fails, just set it to the config value
if (File::Exists(fs::path{m_server_path + "/" + c->LuaModuleDir}.string())) { return dir;
m_lua_modules_path = fs::relative(fs::path{m_server_path + "/" + c->LuaModuleDir}).string(); };
}
// lua mods m_maps_path = resolve_path(c->MapDir, {"maps", "Maps"});
if (File::Exists(fs::path{ m_server_path + "/mods" }.string())) { m_quests_path = resolve_path(c->QuestDir);
m_lua_mods_path = fs::relative(fs::path{ m_server_path + "/mods" }).string(); m_plugins_path = resolve_path(c->PluginDir);
} m_lua_modules_path = resolve_path(c->LuaModuleDir);
m_lua_mods_path = resolve_path("mods");
m_patch_path = resolve_path(c->PatchDir);
m_opcode_path = resolve_path(c->OpcodeDir);
m_shared_memory_path = resolve_path(c->SharedMemDir);
m_log_path = resolve_path(c->LogDir, {"logs"});
// patches // Log all paths in a loop
if (File::Exists(fs::path{m_server_path + "/" + c->PatchDir}.string())) { std::vector<std::pair<std::string, std::string>> paths = {
m_patch_path = fs::relative(fs::path{m_server_path + "/" + c->PatchDir}).string(); {"server", m_server_path},
} {"logs", m_log_path},
{"lua mods", m_lua_mods_path},
{"lua_modules", m_lua_modules_path},
{"maps", m_maps_path},
{"patches", m_patch_path},
{"opcode", m_opcode_path},
{"plugins", m_plugins_path},
{"quests", m_quests_path},
{"shared_memory", m_shared_memory_path}
};
// patches constexpr int name_width = 15;
if (File::Exists(fs::path{ m_server_path + "/" + c->OpcodeDir }.string())) { constexpr int path_width = 0;
m_opcode_path = fs::relative(fs::path{ m_server_path + "/" + c->OpcodeDir }).string(); constexpr int break_length = 70;
}
// shared_memory_path std::cout << std::endl;
if (File::Exists(fs::path{m_server_path + "/" + c->SharedMemDir}.string())) { LogInfo("{}", Strings::Repeat("-", break_length));
m_shared_memory_path = fs::relative(fs::path{ m_server_path + "/" + c->SharedMemDir }).string(); for (const auto& [name, in_path] : paths) {
if (!in_path.empty()) {
LogInfo("{:>{}} > [{:<{}}]", name, name_width, in_path, path_width);
} }
// logging path
if (File::Exists(fs::path{m_server_path + "/" + c->LogDir}.string())) {
m_log_path = fs::relative(fs::path{m_server_path + "/" + c->LogDir}).string();
} }
LogInfo("{}", Strings::Repeat("-", break_length));
LogInfo("logs path [{}]", m_log_path);
LogInfo("lua mods path [{}]", m_lua_mods_path);
LogInfo("lua_modules path [{}]", m_lua_modules_path);
LogInfo("maps path [{}]", m_maps_path);
LogInfo("patches path [{}]", m_patch_path);
LogInfo("opcode path [{}]", m_opcode_path);
LogInfo("plugins path [{}]", m_plugins_path);
LogInfo("quests path [{}]", m_quests_path);
LogInfo("shared_memory path [{}]", m_shared_memory_path);
} }
const std::string &PathManager::GetServerPath() const const std::string &PathManager::GetServerPath() const
@@ -49,23 +49,23 @@ public:
std::string field; std::string field;
switch (theme_id) { switch (theme_id) {
case LDoNThemes::GUK: { case LDoNTheme::GUK: {
field = "guk_"; field = "guk_";
break; break;
} }
case LDoNThemes::MIR: { case LDoNTheme::MIR: {
field = "mir_"; field = "mir_";
break; break;
} }
case LDoNThemes::MMC: { case LDoNTheme::MMC: {
field = "mmc_"; field = "mmc_";
break; break;
} }
case LDoNThemes::RUJ: { case LDoNTheme::RUJ: {
field = "ruj_"; field = "ruj_";
break; break;
} }
case LDoNThemes::TAK: { case LDoNTheme::TAK: {
field = "tak_"; field = "tak_";
break; break;
} }
@@ -28,13 +28,14 @@ public:
uint32_t aug_slot_4; uint32_t aug_slot_4;
uint32_t aug_slot_5; uint32_t aug_slot_5;
uint32_t aug_slot_6; uint32_t aug_slot_6;
int32_t item_sn; uint32_t item_sn;
int32_t item_charges; int32_t item_charges;
uint64_t item_cost; uint32_t item_cost;
uint8_t slot_id; uint8_t slot_id;
uint32_t char_entity_id; uint32_t char_entity_id;
uint32_t char_zone_id; uint32_t char_zone_id;
int8_t active_transaction; int32_t char_zone_instance_id;
uint8_t active_transaction;
}; };
static std::string PrimaryKey() static std::string PrimaryKey()
@@ -60,6 +61,7 @@ public:
"slot_id", "slot_id",
"char_entity_id", "char_entity_id",
"char_zone_id", "char_zone_id",
"char_zone_instance_id",
"active_transaction", "active_transaction",
}; };
} }
@@ -82,6 +84,7 @@ public:
"slot_id", "slot_id",
"char_entity_id", "char_entity_id",
"char_zone_id", "char_zone_id",
"char_zone_instance_id",
"active_transaction", "active_transaction",
}; };
} }
@@ -138,6 +141,7 @@ public:
e.slot_id = 0; e.slot_id = 0;
e.char_entity_id = 0; e.char_entity_id = 0;
e.char_zone_id = 0; e.char_zone_id = 0;
e.char_zone_instance_id = 0;
e.active_transaction = 0; e.active_transaction = 0;
return e; return e;
@@ -184,13 +188,14 @@ public:
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0; e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0; e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0; e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.item_sn = row[9] ? static_cast<int32_t>(atoi(row[9])) : 0; e.item_sn = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.item_charges = row[10] ? static_cast<int32_t>(atoi(row[10])) : 0; e.item_charges = row[10] ? static_cast<int32_t>(atoi(row[10])) : 0;
e.item_cost = row[11] ? strtoull(row[11], nullptr, 10) : 0; e.item_cost = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
e.slot_id = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0; e.slot_id = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0;
e.char_entity_id = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0; e.char_entity_id = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.char_zone_id = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0; e.char_zone_id = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.active_transaction = row[15] ? static_cast<int8_t>(atoi(row[15])) : 0; e.char_zone_instance_id = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
e.active_transaction = row[16] ? static_cast<uint8_t>(strtoul(row[16], nullptr, 10)) : 0;
return e; return e;
} }
@@ -238,7 +243,8 @@ public:
v.push_back(columns[12] + " = " + std::to_string(e.slot_id)); v.push_back(columns[12] + " = " + std::to_string(e.slot_id));
v.push_back(columns[13] + " = " + std::to_string(e.char_entity_id)); v.push_back(columns[13] + " = " + std::to_string(e.char_entity_id));
v.push_back(columns[14] + " = " + std::to_string(e.char_zone_id)); v.push_back(columns[14] + " = " + std::to_string(e.char_zone_id));
v.push_back(columns[15] + " = " + std::to_string(e.active_transaction)); v.push_back(columns[15] + " = " + std::to_string(e.char_zone_instance_id));
v.push_back(columns[16] + " = " + std::to_string(e.active_transaction));
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
@@ -275,6 +281,7 @@ public:
v.push_back(std::to_string(e.slot_id)); v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.char_entity_id)); v.push_back(std::to_string(e.char_entity_id));
v.push_back(std::to_string(e.char_zone_id)); v.push_back(std::to_string(e.char_zone_id));
v.push_back(std::to_string(e.char_zone_instance_id));
v.push_back(std::to_string(e.active_transaction)); v.push_back(std::to_string(e.active_transaction));
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
@@ -320,6 +327,7 @@ public:
v.push_back(std::to_string(e.slot_id)); v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.char_entity_id)); v.push_back(std::to_string(e.char_entity_id));
v.push_back(std::to_string(e.char_zone_id)); v.push_back(std::to_string(e.char_zone_id));
v.push_back(std::to_string(e.char_zone_instance_id));
v.push_back(std::to_string(e.active_transaction)); v.push_back(std::to_string(e.active_transaction));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
@@ -363,13 +371,14 @@ public:
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0; e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0; e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0; e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.item_sn = row[9] ? static_cast<int32_t>(atoi(row[9])) : 0; e.item_sn = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.item_charges = row[10] ? static_cast<int32_t>(atoi(row[10])) : 0; e.item_charges = row[10] ? static_cast<int32_t>(atoi(row[10])) : 0;
e.item_cost = row[11] ? strtoull(row[11], nullptr, 10) : 0; e.item_cost = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
e.slot_id = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0; e.slot_id = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0;
e.char_entity_id = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0; e.char_entity_id = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.char_zone_id = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0; e.char_zone_id = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.active_transaction = row[15] ? static_cast<int8_t>(atoi(row[15])) : 0; e.char_zone_instance_id = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
e.active_transaction = row[16] ? static_cast<uint8_t>(strtoul(row[16], nullptr, 10)) : 0;
all_entries.push_back(e); all_entries.push_back(e);
} }
@@ -403,13 +412,14 @@ public:
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0; e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0; e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0; e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.item_sn = row[9] ? static_cast<int32_t>(atoi(row[9])) : 0; e.item_sn = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.item_charges = row[10] ? static_cast<int32_t>(atoi(row[10])) : 0; e.item_charges = row[10] ? static_cast<int32_t>(atoi(row[10])) : 0;
e.item_cost = row[11] ? strtoull(row[11], nullptr, 10) : 0; e.item_cost = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
e.slot_id = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0; e.slot_id = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0;
e.char_entity_id = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0; e.char_entity_id = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.char_zone_id = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0; e.char_zone_id = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.active_transaction = row[15] ? static_cast<int8_t>(atoi(row[15])) : 0; e.char_zone_instance_id = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
e.active_transaction = row[16] ? static_cast<uint8_t>(strtoul(row[16], nullptr, 10)) : 0;
all_entries.push_back(e); all_entries.push_back(e);
} }
@@ -499,6 +509,7 @@ public:
v.push_back(std::to_string(e.slot_id)); v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.char_entity_id)); v.push_back(std::to_string(e.char_entity_id));
v.push_back(std::to_string(e.char_zone_id)); v.push_back(std::to_string(e.char_zone_id));
v.push_back(std::to_string(e.char_zone_instance_id));
v.push_back(std::to_string(e.active_transaction)); v.push_back(std::to_string(e.active_transaction));
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
@@ -537,6 +548,7 @@ public:
v.push_back(std::to_string(e.slot_id)); v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.char_entity_id)); v.push_back(std::to_string(e.char_entity_id));
v.push_back(std::to_string(e.char_zone_id)); v.push_back(std::to_string(e.char_zone_id));
v.push_back(std::to_string(e.char_zone_instance_id));
v.push_back(std::to_string(e.active_transaction)); v.push_back(std::to_string(e.active_transaction));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
+7 -4
View File
@@ -16,6 +16,7 @@ public:
struct DistinctTraders_Struct { struct DistinctTraders_Struct {
uint32 trader_id; uint32 trader_id;
uint32 zone_id; uint32 zone_id;
uint32 zone_instance_id;
uint32 entity_id; uint32 entity_id;
std::string trader_name; std::string trader_name;
}; };
@@ -35,7 +36,8 @@ public:
GetBazaarSearchResults( GetBazaarSearchResults(
SharedDatabase &db, SharedDatabase &db,
BazaarSearchCriteria_Struct search, BazaarSearchCriteria_Struct search,
uint32 char_zone_id uint32 char_zone_id,
int32 char_zone_instance_id
); );
static BulkTraders_Struct GetDistinctTraders(Database &db) static BulkTraders_Struct GetDistinctTraders(Database &db)
@@ -44,7 +46,7 @@ public:
std::vector<DistinctTraders_Struct> distinct_traders; std::vector<DistinctTraders_Struct> distinct_traders;
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
"SELECT DISTINCT(t.char_id), t.char_zone_id, t.char_entity_id, c.name " "SELECT DISTINCT(t.char_id), t.char_zone_id, t.char_zone_instance_id, t.char_entity_id, c.name "
"FROM trader AS t " "FROM trader AS t "
"JOIN character_data AS c ON t.char_id = c.id;" "JOIN character_data AS c ON t.char_id = c.id;"
); );
@@ -56,8 +58,9 @@ public:
e.trader_id = Strings::ToInt(row[0]); e.trader_id = Strings::ToInt(row[0]);
e.zone_id = Strings::ToInt(row[1]); e.zone_id = Strings::ToInt(row[1]);
e.entity_id = Strings::ToInt(row[2]); e.zone_instance_id = Strings::ToInt(row[2]);
e.trader_name = row[3] ? row[3] : ""; e.entity_id = Strings::ToInt(row[3]);
e.trader_name = row[4] ? row[4] : "";
all_entries.name_length += e.trader_name.length() + 1; all_entries.name_length += e.trader_name.length() + 1;
all_entries.traders.push_back(e); all_entries.traders.push_back(e);
+3
View File
@@ -340,6 +340,9 @@ RULE_STRING(World, Rules, "", "Server Rules, change from empty to have this be u
RULE_BOOL(World, EnableAutoLogin, false, "Enables or disables auto login of characters, allowing people to log characters in directly from loginserver to ingame") RULE_BOOL(World, EnableAutoLogin, false, "Enables or disables auto login of characters, allowing people to log characters in directly from loginserver to ingame")
RULE_BOOL(World, EnablePVPRegions, true, "Enables or disables PVP Regions automatically setting your PVP flag") RULE_BOOL(World, EnablePVPRegions, true, "Enables or disables PVP Regions automatically setting your PVP flag")
RULE_STRING(World, SupportedClients, "", "Comma-delimited list of clients to restrict to. Supported values are Titanium | SoF | SoD | UF | RoF | RoF2. Example: Titanium,RoF2") RULE_STRING(World, SupportedClients, "", "Comma-delimited list of clients to restrict to. Supported values are Titanium | SoF | SoD | UF | RoF | RoF2. Example: Titanium,RoF2")
RULE_STRING(World, CustomFilesKey, "", "Enable if the server requires custom files and sends a key to validate. Empty string to disable. Example: eqcustom_v1")
RULE_STRING(World, CustomFilesUrl, "github.com/knervous/eqnexus/releases", "URL to display at character select if client is missing custom files")
RULE_INT(World, CustomFilesAdminLevel, 20, "Admin level at which custom file key is not required when CustomFilesKey is specified")
RULE_CATEGORY_END() RULE_CATEGORY_END()
RULE_CATEGORY(Zone) RULE_CATEGORY(Zone)
-2
View File
@@ -319,8 +319,6 @@
// player events // player events
#define ServerOP_PlayerEvent 0x5100 #define ServerOP_PlayerEvent 0x5100
#define ServerOP_DataBucketCacheUpdate 0x5200
enum { enum {
CZUpdateType_Character, CZUpdateType_Character,
CZUpdateType_Group, CZUpdateType_Group,
+2 -2
View File
@@ -25,7 +25,7 @@
// Build variables // Build variables
// these get injected during the build pipeline // these get injected during the build pipeline
#define CURRENT_VERSION "22.60.0-dev" // always append -dev to the current version for custom-builds #define CURRENT_VERSION "22.61.0-dev" // always append -dev to the current version for custom-builds
#define LOGIN_VERSION "0.8.0" #define LOGIN_VERSION "0.8.0"
#define COMPILE_DATE __DATE__ #define COMPILE_DATE __DATE__
#define COMPILE_TIME __TIME__ #define COMPILE_TIME __TIME__
@@ -42,7 +42,7 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/ */
#define CURRENT_BINARY_DATABASE_VERSION 9285 #define CURRENT_BINARY_DATABASE_VERSION 9286
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9045 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9045
#endif #endif
-12
View File
@@ -51,12 +51,6 @@ WorldServer::WorldServer(std::shared_ptr<EQ::Net::ServertalkServerConnection> wo
ServerOP_LSAccountUpdate, ServerOP_LSAccountUpdate,
std::bind(&WorldServer::ProcessLSAccountUpdate, this, std::placeholders::_1, std::placeholders::_2) std::bind(&WorldServer::ProcessLSAccountUpdate, this, std::placeholders::_1, std::placeholders::_2)
); );
m_keepalive = std::make_unique<EQ::Timer>(
1000,
true,
std::bind(&WorldServer::OnKeepAlive, this, std::placeholders::_1)
);
} }
WorldServer::~WorldServer() = default; WorldServer::~WorldServer() = default;
@@ -1307,12 +1301,6 @@ const std::string &WorldServer::GetVersion() const
return m_version; return m_version;
} }
void WorldServer::OnKeepAlive(EQ::Timer *t)
{
ServerPacket pack(ServerOP_KeepAlive, 0);
m_connection->SendPacket(&pack);
}
void WorldServer::FormatWorldServerName(char *name, int8 server_list_type) void WorldServer::FormatWorldServerName(char *name, int8 server_list_type)
{ {
std::string server_long_name = name; std::string server_long_name = name;
-7
View File
@@ -187,13 +187,6 @@ private:
bool m_is_server_logged_in; bool m_is_server_logged_in;
bool m_is_server_trusted; bool m_is_server_trusted;
/**
* Keepalive
* @param t
*/
void OnKeepAlive(EQ::Timer *t);
std::unique_ptr<EQ::Timer> m_keepalive;
static void FormatWorldServerName(char *name, int8 server_list_type); static void FormatWorldServerName(char *name, int8 server_list_type);
}; };
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "eqemu-server", "name": "eqemu-server",
"version": "22.60.0", "version": "22.61.0",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/EQEmu/Server.git" "url": "https://github.com/EQEmu/Server.git"
+1 -1
View File
@@ -10,7 +10,7 @@ require (
require ( require (
github.com/golang/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.3.2 // indirect
github.com/google/go-querystring v1.1.0 // indirect github.com/google/go-querystring v1.1.0 // indirect
golang.org/x/crypto v0.21.0 // indirect golang.org/x/crypto v0.31.0 // indirect
golang.org/x/net v0.23.0 // indirect golang.org/x/net v0.23.0 // indirect
google.golang.org/appengine v1.6.7 // indirect google.golang.org/appengine v1.6.7 // indirect
) )
+2 -2
View File
@@ -10,8 +10,8 @@ github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
+2 -2
View File
@@ -12,12 +12,12 @@ void WorldserverCLI::CopyCharacter(int argc, char **argv, argh::parser &cmd, std
}; };
std::vector<std::string> options = {}; std::vector<std::string> options = {};
EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv);
if (cmd[{"-h", "--help"}]) { if (cmd[{"-h", "--help"}]) {
return; return;
} }
EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv);
std::string source_character_name = cmd(2).str(); std::string source_character_name = cmd(2).str();
std::string destination_character_name = cmd(3).str(); std::string destination_character_name = cmd(3).str();
std::string destination_account_name = cmd(4).str(); std::string destination_account_name = cmd(4).str();
+11
View File
@@ -541,6 +541,17 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app)
skip_char_info = true; skip_char_info = true;
} }
} }
const auto& custom_files_key = RuleS(World, CustomFilesKey);
if (!skip_char_info && !custom_files_key.empty() && cle->Admin() < RuleI(World, CustomFilesAdminLevel)) {
// Modified clients can utilize this unused block in login_info to send custom payloads on login
// which indicates they are using custom client files with the correct version, based on key payload.
const auto client_key = std::string(reinterpret_cast<char*>(login_info->unknown064));
if (custom_files_key != client_key) {
std::string message = fmt::format("Missing Files [{}]", RuleS(World, CustomFilesUrl) );
SendUnsupportedClientPacket(message);
skip_char_info = true;
}
}
if (!skip_char_info) { if (!skip_char_info) {
SendExpansionInfo(); SendExpansionInfo();
-10
View File
@@ -595,11 +595,6 @@ bool LoginServer::Connect()
); );
} }
m_keepalive = std::make_unique<EQ::Timer>(
1000,
true,
std::bind(&LoginServer::OnKeepAlive, this, std::placeholders::_1));
return true; return true;
} }
@@ -716,8 +711,3 @@ void LoginServer::SendAccountUpdate(ServerPacket *pack)
} }
} }
void LoginServer::OnKeepAlive(EQ::Timer *t)
{
ServerPacket pack(ServerOP_KeepAlive, 0);
SendPacket(&pack);
}
-1
View File
@@ -50,7 +50,6 @@ private:
void ProcessLSRemoteAddr(uint16_t opcode, EQ::Net::Packet &p); void ProcessLSRemoteAddr(uint16_t opcode, EQ::Net::Packet &p);
void ProcessLSAccountUpdate(uint16_t opcode, EQ::Net::Packet &p); void ProcessLSAccountUpdate(uint16_t opcode, EQ::Net::Packet &p);
void OnKeepAlive(EQ::Timer *t);
std::unique_ptr<EQ::Timer> m_keepalive; std::unique_ptr<EQ::Timer> m_keepalive;
std::unique_ptr<EQ::Net::ServertalkClient> m_client; std::unique_ptr<EQ::Net::ServertalkClient> m_client;
-6
View File
@@ -22,7 +22,6 @@ void QueryServConnection::AddConnection(std::shared_ptr<EQ::Net::ServertalkServe
connection->OnMessage(ServerOP_QueryServGeneric, std::bind(&QueryServConnection::HandleGenericMessage, this, std::placeholders::_1, std::placeholders::_2)); connection->OnMessage(ServerOP_QueryServGeneric, std::bind(&QueryServConnection::HandleGenericMessage, this, std::placeholders::_1, std::placeholders::_2));
connection->OnMessage(ServerOP_LFGuildUpdate, std::bind(&QueryServConnection::HandleLFGuildUpdateMessage, this, std::placeholders::_1, std::placeholders::_2)); connection->OnMessage(ServerOP_LFGuildUpdate, std::bind(&QueryServConnection::HandleLFGuildUpdateMessage, this, std::placeholders::_1, std::placeholders::_2));
m_streams.emplace(std::make_pair(connection->GetUUID(), connection)); m_streams.emplace(std::make_pair(connection->GetUUID(), connection));
m_keepalive = std::make_unique<EQ::Timer>(1000, true, std::bind(&QueryServConnection::OnKeepAlive, this, std::placeholders::_1));
} }
void QueryServConnection::RemoveConnection(std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) void QueryServConnection::RemoveConnection(std::shared_ptr<EQ::Net::ServertalkServerConnection> connection)
@@ -54,8 +53,3 @@ bool QueryServConnection::SendPacket(ServerPacket* pack)
return true; return true;
} }
void QueryServConnection::OnKeepAlive(EQ::Timer *t)
{
ServerPacket pack(ServerOP_KeepAlive, 0);
SendPacket(&pack);
}
-1
View File
@@ -15,7 +15,6 @@ public:
void HandleGenericMessage(uint16_t opcode, EQ::Net::Packet &p); void HandleGenericMessage(uint16_t opcode, EQ::Net::Packet &p);
void HandleLFGuildUpdateMessage(uint16_t opcode, EQ::Net::Packet &p); void HandleLFGuildUpdateMessage(uint16_t opcode, EQ::Net::Packet &p);
bool SendPacket(ServerPacket* pack); bool SendPacket(ServerPacket* pack);
void OnKeepAlive(EQ::Timer *t);
private: private:
std::map<std::string, std::shared_ptr<EQ::Net::ServertalkServerConnection>> m_streams; std::map<std::string, std::shared_ptr<EQ::Net::ServertalkServerConnection>> m_streams;
std::unique_ptr<EQ::Timer> m_keepalive; std::unique_ptr<EQ::Timer> m_keepalive;
-12
View File
@@ -31,8 +31,6 @@ void UCSConnection::SetConnection(std::shared_ptr<EQ::Net::ServertalkServerConne
) )
); );
} }
m_keepalive = std::make_unique<EQ::Timer>(1000, true, std::bind(&UCSConnection::OnKeepAlive, this, std::placeholders::_1));
} }
const std::shared_ptr<EQ::Net::ServertalkServerConnection> &UCSConnection::GetConnection() const const std::shared_ptr<EQ::Net::ServertalkServerConnection> &UCSConnection::GetConnection() const
@@ -92,13 +90,3 @@ void UCSConnection::SendMessage(const char *From, const char *Message)
SendPacket(pack); SendPacket(pack);
safe_delete(pack); safe_delete(pack);
} }
void UCSConnection::OnKeepAlive(EQ::Timer *t)
{
if (!connection) {
return;
}
ServerPacket pack(ServerOP_KeepAlive, 0);
connection->SendPacket(&pack);
}
-5
View File
@@ -23,11 +23,6 @@ private:
inline std::string GetIP() const { return (connection && connection->Handle()) ? connection->Handle()->RemoteIP() : 0; } inline std::string GetIP() const { return (connection && connection->Handle()) ? connection->Handle()->RemoteIP() : 0; }
std::shared_ptr<EQ::Net::ServertalkServerConnection> connection; std::shared_ptr<EQ::Net::ServertalkServerConnection> connection;
/**
* Keepalive
*/
std::unique_ptr<EQ::Timer> m_keepalive;
void OnKeepAlive(EQ::Timer *t);
}; };
#endif /*UCS_H_*/ #endif /*UCS_H_*/
-8
View File
@@ -42,7 +42,6 @@ ZSList::ZSList()
memset(pLockedZones, 0, sizeof(pLockedZones)); memset(pLockedZones, 0, sizeof(pLockedZones));
m_tick = std::make_unique<EQ::Timer>(5000, true, std::bind(&ZSList::OnTick, this, std::placeholders::_1)); m_tick = std::make_unique<EQ::Timer>(5000, true, std::bind(&ZSList::OnTick, this, std::placeholders::_1));
m_keepalive = std::make_unique<EQ::Timer>(1000, true, std::bind(&ZSList::OnKeepAlive, this, std::placeholders::_1));
} }
ZSList::~ZSList() { ZSList::~ZSList() {
@@ -846,13 +845,6 @@ void ZSList::OnTick(EQ::Timer *t)
web_interface.SendEvent(out); web_interface.SendEvent(out);
} }
void ZSList::OnKeepAlive(EQ::Timer *t)
{
for (auto &zone : zone_server_list) {
zone->SendKeepAlive();
}
}
const std::list<std::unique_ptr<ZoneServer>> &ZSList::getZoneServerList() const const std::list<std::unique_ptr<ZoneServer>> &ZSList::getZoneServerList() const
{ {
return zone_server_list; return zone_server_list;
-1
View File
@@ -72,7 +72,6 @@ public:
private: private:
void OnTick(EQ::Timer *t); void OnTick(EQ::Timer *t);
void OnKeepAlive(EQ::Timer *t);
uint32 NextID; uint32 NextID;
uint16 pLockedZones[MaxLockedZones]; uint16 pLockedZones[MaxLockedZones];
uint32 CurGroupID; uint32 CurGroupID;
-5
View File
@@ -1564,11 +1564,6 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
DynamicZone::HandleZoneMessage(pack); DynamicZone::HandleZoneMessage(pack);
break; break;
} }
case ServerOP_DataBucketCacheUpdate: {
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_GuildTributeUpdate: { case ServerOP_GuildTributeUpdate: {
auto data = (GuildTributeUpdate *)pack->pBuffer; auto data = (GuildTributeUpdate *)pack->pBuffer;
auto guild = guild_mgr.GetGuildByGuildID(data->guild_id); auto guild = guild_mgr.GetGuildByGuildID(data->guild_id);
+7 -22
View File
@@ -1550,10 +1550,7 @@ void Mob::DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts, boo
hit.damage_done = 0; hit.damage_done = 0;
} }
parse->EventBotMerc( parse->EventBotMerc(EVENT_USE_SKILL, this, nullptr,
EVENT_USE_SKILL,
this,
nullptr,
[&]() { [&]() {
return fmt::format( return fmt::format(
"{} {}", "{} {}",
@@ -3078,10 +3075,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
std::vector<std::any> args = { corpse }; std::vector<std::any> args = { corpse };
parse->EventMercNPC( parse->EventMercNPC(EVENT_DEATH_COMPLETE, this, owner_or_self,
EVENT_DEATH_COMPLETE,
this,
owner_or_self,
[&]() { [&]() {
return fmt::format( return fmt::format(
"{} {} {} {} {} {} {} {} {}", "{} {} {} {} {} {} {} {} {}",
@@ -3096,8 +3090,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
m_combat_record.GetHealingReceived() m_combat_record.GetHealingReceived()
); );
}, },
0, 0, &args
&args
); );
// Zone controller process EVENT_DEATH_ZONE (Death events) // Zone controller process EVENT_DEATH_ZONE (Death events)
@@ -4266,10 +4259,7 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
if (attacker) { if (attacker) {
args = { this }; args = { this };
parse->EventMob( parse->EventMob(EVENT_DAMAGE_GIVEN, attacker, this,
EVENT_DAMAGE_GIVEN,
attacker,
this,
[&]() { [&]() {
return fmt::format( return fmt::format(
"{} {} {} {} {} {} {} {} {}", "{} {} {} {} {} {} {} {} {}",
@@ -4284,17 +4274,13 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
static_cast<int>(special) static_cast<int>(special)
); );
}, },
0, 0, &args
&args
); );
} }
args = { attacker }; args = { attacker };
damage_override = parse->EventMob( damage_override = parse->EventMob(EVENT_DAMAGE_TAKEN, this, attacker,
EVENT_DAMAGE_TAKEN,
this,
attacker,
[&]() { [&]() {
return fmt::format( return fmt::format(
"{} {} {} {} {} {} {} {} {}", "{} {} {} {} {} {} {} {} {}",
@@ -4309,8 +4295,7 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
static_cast<int>(special) static_cast<int>(special)
); );
}, },
0, 0, &args
&args
); );
if (damage_override > 0) { if (damage_override > 0) {
+4 -17
View File
@@ -1265,7 +1265,7 @@ void Bot::LoadAAs() {
} }
while(current) { while(current) {
if (!CanUseAlternateAdvancementRank(current)) { if (current->level_req > GetLevel() || !CanUseAlternateAdvancementRank(current)) {
current = nullptr; current = nullptr;
} else { } else {
current = current->next; current = current->next;
@@ -3089,6 +3089,7 @@ bool Bot::Spawn(Client* botCharacterOwner) {
m_targetable = true; m_targetable = true;
entity_list.AddBot(this, true, true); entity_list.AddBot(this, true, true);
ClearDataBucketCache();
DataBucket::GetDataBuckets(this); DataBucket::GetDataBuckets(this);
LoadBotSpellSettings(); LoadBotSpellSettings();
if (!AI_AddBotSpells(GetBotSpellID())) { if (!AI_AddBotSpells(GetBotSpellID())) {
@@ -4192,14 +4193,7 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client*
std::vector<std::any> args = { return_iterator.return_item_instance }; std::vector<std::any> args = { return_iterator.return_item_instance };
parse->EventBot( parse->EventBot(EVENT_UNEQUIP_ITEM_BOT, this, nullptr, export_string, return_iterator.return_item_instance->GetID(), &args);
EVENT_UNEQUIP_ITEM_BOT,
this,
nullptr,
export_string,
return_iterator.return_item_instance->GetID(),
&args
);
} }
if (return_instance) { if (return_instance) {
@@ -4264,14 +4258,7 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client*
std::vector<std::any> args = { trade_iterator.trade_item_instance }; std::vector<std::any> args = { trade_iterator.trade_item_instance };
parse->EventBot( parse->EventBot(EVENT_EQUIP_ITEM_BOT, this, nullptr, export_string, trade_iterator.trade_item_instance->GetID(), &args);
EVENT_EQUIP_ITEM_BOT,
this,
nullptr,
export_string,
trade_iterator.trade_item_instance->GetID(),
&args
);
} }
trade_iterator.trade_item_instance = nullptr; // actual deletion occurs in client delete below trade_iterator.trade_item_instance = nullptr; // actual deletion occurs in client delete below
+97 -114
View File
@@ -329,7 +329,7 @@ Client::Client(EQStreamInterface *ieqs) : Mob(
adventure_stats_timer = nullptr; adventure_stats_timer = nullptr;
adventure_leaderboard_timer = nullptr; adventure_leaderboard_timer = nullptr;
adv_data = nullptr; adv_data = nullptr;
adv_requested_theme = LDoNThemes::Unused; adv_requested_theme = LDoNTheme::Unused;
adv_requested_id = 0; adv_requested_id = 0;
adv_requested_member_count = 0; adv_requested_member_count = 0;
@@ -1469,7 +1469,7 @@ bool Client::UpdateLDoNPoints(uint32 theme_id, int points)
bool is_loss = false; bool is_loss = false;
switch (theme_id) { switch (theme_id) {
case LDoNThemes::Unused: { // No theme, so distribute evenly across all case LDoNTheme::Unused: { // No theme, so distribute evenly across all
int split_points = (points / 5); int split_points = (points / 5);
int guk_points = (split_points + (points % 5)); int guk_points = (split_points + (points % 5));
@@ -1522,12 +1522,12 @@ bool Client::UpdateLDoNPoints(uint32 theme_id, int points)
points -= split_points; points -= split_points;
if (split_points != 0) { // if anything left, recursively loop thru again if (split_points != 0) { // if anything left, recursively loop thru again
UpdateLDoNPoints(LDoNThemes::Unused, split_points); UpdateLDoNPoints(LDoNTheme::Unused, split_points);
} }
break; break;
} }
case LDoNThemes::GUK: { case LDoNTheme::GUK: {
if (points < 0) { if (points < 0) {
if (m_pp.ldon_points_guk < (0 - points)) { if (m_pp.ldon_points_guk < (0 - points)) {
return false; return false;
@@ -1539,7 +1539,7 @@ bool Client::UpdateLDoNPoints(uint32 theme_id, int points)
m_pp.ldon_points_guk += points; m_pp.ldon_points_guk += points;
break; break;
} }
case LDoNThemes::MIR: { case LDoNTheme::MIR: {
if (points < 0) { if (points < 0) {
if (m_pp.ldon_points_mir < (0 - points)) { if (m_pp.ldon_points_mir < (0 - points)) {
return false; return false;
@@ -1551,7 +1551,7 @@ bool Client::UpdateLDoNPoints(uint32 theme_id, int points)
m_pp.ldon_points_mir += points; m_pp.ldon_points_mir += points;
break; break;
} }
case LDoNThemes::MMC: { case LDoNTheme::MMC: {
if (points < 0) { if (points < 0) {
if (m_pp.ldon_points_mmc < (0 - points)) { if (m_pp.ldon_points_mmc < (0 - points)) {
return false; return false;
@@ -1563,7 +1563,7 @@ bool Client::UpdateLDoNPoints(uint32 theme_id, int points)
m_pp.ldon_points_mmc += points; m_pp.ldon_points_mmc += points;
break; break;
} }
case LDoNThemes::RUJ: { case LDoNTheme::RUJ: {
if (points < 0) { if (points < 0) {
if (m_pp.ldon_points_ruj < (0 - points)) { if (m_pp.ldon_points_ruj < (0 - points)) {
return false; return false;
@@ -1575,7 +1575,7 @@ bool Client::UpdateLDoNPoints(uint32 theme_id, int points)
m_pp.ldon_points_ruj += points; m_pp.ldon_points_ruj += points;
break; break;
} }
case LDoNThemes::TAK: { case LDoNTheme::TAK: {
if (points < 0) { if (points < 0) {
if (m_pp.ldon_points_tak < (0 - points)) { if (m_pp.ldon_points_tak < (0 - points)) {
return false; return false;
@@ -1623,23 +1623,23 @@ bool Client::UpdateLDoNPoints(uint32 theme_id, int points)
void Client::SetLDoNPoints(uint32 theme_id, uint32 points) void Client::SetLDoNPoints(uint32 theme_id, uint32 points)
{ {
switch (theme_id) { switch (theme_id) {
case LDoNThemes::GUK: { case LDoNTheme::GUK: {
m_pp.ldon_points_guk = points; m_pp.ldon_points_guk = points;
break; break;
} }
case LDoNThemes::MIR: { case LDoNTheme::MIR: {
m_pp.ldon_points_mir = points; m_pp.ldon_points_mir = points;
break; break;
} }
case LDoNThemes::MMC: { case LDoNTheme::MMC: {
m_pp.ldon_points_mmc = points; m_pp.ldon_points_mmc = points;
break; break;
} }
case LDoNThemes::RUJ: { case LDoNTheme::RUJ: {
m_pp.ldon_points_ruj = points; m_pp.ldon_points_ruj = points;
break; break;
} }
case LDoNThemes::TAK: { case LDoNTheme::TAK: {
m_pp.ldon_points_tak = points; m_pp.ldon_points_tak = points;
break; break;
} }
@@ -5676,15 +5676,15 @@ uint32 Client::GetLDoNPointsTheme(uint32 t)
{ {
switch(t) switch(t)
{ {
case LDoNThemes::GUK: case LDoNTheme::GUK:
return m_pp.ldon_points_guk; return m_pp.ldon_points_guk;
case LDoNThemes::MIR: case LDoNTheme::MIR:
return m_pp.ldon_points_mir; return m_pp.ldon_points_mir;
case LDoNThemes::MMC: case LDoNTheme::MMC:
return m_pp.ldon_points_mmc; return m_pp.ldon_points_mmc;
case LDoNThemes::RUJ: case LDoNTheme::RUJ:
return m_pp.ldon_points_ruj; return m_pp.ldon_points_ruj;
case LDoNThemes::TAK: case LDoNTheme::TAK:
return m_pp.ldon_points_tak; return m_pp.ldon_points_tak;
default: default:
return 0; return 0;
@@ -5695,15 +5695,15 @@ uint32 Client::GetLDoNWinsTheme(uint32 t)
{ {
switch(t) switch(t)
{ {
case LDoNThemes::GUK: case LDoNTheme::GUK:
return m_pp.ldon_wins_guk; return m_pp.ldon_wins_guk;
case LDoNThemes::MIR: case LDoNTheme::MIR:
return m_pp.ldon_wins_mir; return m_pp.ldon_wins_mir;
case LDoNThemes::MMC: case LDoNTheme::MMC:
return m_pp.ldon_wins_mmc; return m_pp.ldon_wins_mmc;
case LDoNThemes::RUJ: case LDoNTheme::RUJ:
return m_pp.ldon_wins_ruj; return m_pp.ldon_wins_ruj;
case LDoNThemes::TAK: case LDoNTheme::TAK:
return m_pp.ldon_wins_tak; return m_pp.ldon_wins_tak;
default: default:
return 0; return 0;
@@ -5714,15 +5714,15 @@ uint32 Client::GetLDoNLossesTheme(uint32 t)
{ {
switch(t) switch(t)
{ {
case LDoNThemes::GUK: case LDoNTheme::GUK:
return m_pp.ldon_losses_guk; return m_pp.ldon_losses_guk;
case LDoNThemes::MIR: case LDoNTheme::MIR:
return m_pp.ldon_losses_mir; return m_pp.ldon_losses_mir;
case LDoNThemes::MMC: case LDoNTheme::MMC:
return m_pp.ldon_losses_mmc; return m_pp.ldon_losses_mmc;
case LDoNThemes::RUJ: case LDoNTheme::RUJ:
return m_pp.ldon_losses_ruj; return m_pp.ldon_losses_ruj;
case LDoNThemes::TAK: case LDoNTheme::TAK:
return m_pp.ldon_losses_tak; return m_pp.ldon_losses_tak;
default: default:
return 0; return 0;
@@ -5731,35 +5731,35 @@ uint32 Client::GetLDoNLossesTheme(uint32 t)
void Client::UpdateLDoNWinLoss(uint32 theme_id, bool win, bool remove) { void Client::UpdateLDoNWinLoss(uint32 theme_id, bool win, bool remove) {
switch (theme_id) { switch (theme_id) {
case LDoNThemes::GUK: case LDoNTheme::GUK:
if (win) { if (win) {
m_pp.ldon_wins_guk += (remove ? -1 : 1); m_pp.ldon_wins_guk += (remove ? -1 : 1);
} else { } else {
m_pp.ldon_losses_guk += (remove ? -1 : 1); m_pp.ldon_losses_guk += (remove ? -1 : 1);
} }
break; break;
case LDoNThemes::MIR: case LDoNTheme::MIR:
if (win) { if (win) {
m_pp.ldon_wins_mir += (remove ? -1 : 1); m_pp.ldon_wins_mir += (remove ? -1 : 1);
} else { } else {
m_pp.ldon_losses_mir += (remove ? -1 : 1); m_pp.ldon_losses_mir += (remove ? -1 : 1);
} }
break; break;
case LDoNThemes::MMC: case LDoNTheme::MMC:
if (win) { if (win) {
m_pp.ldon_wins_mmc += (remove ? -1 : 1); m_pp.ldon_wins_mmc += (remove ? -1 : 1);
} else { } else {
m_pp.ldon_losses_mmc += (remove ? -1 : 1); m_pp.ldon_losses_mmc += (remove ? -1 : 1);
} }
break; break;
case LDoNThemes::RUJ: case LDoNTheme::RUJ:
if (win) { if (win) {
m_pp.ldon_wins_ruj += (remove ? -1 : 1); m_pp.ldon_wins_ruj += (remove ? -1 : 1);
} else { } else {
m_pp.ldon_losses_ruj += (remove ? -1 : 1); m_pp.ldon_losses_ruj += (remove ? -1 : 1);
} }
break; break;
case LDoNThemes::TAK: case LDoNTheme::TAK:
if (win) { if (win) {
m_pp.ldon_wins_tak += (remove ? -1 : 1); m_pp.ldon_wins_tak += (remove ? -1 : 1);
} else { } else {
@@ -6227,7 +6227,7 @@ void Client::NewAdventure(int id, int theme, const char *text, int member_count,
void Client::ClearPendingAdventureData() void Client::ClearPendingAdventureData()
{ {
adv_requested_id = 0; adv_requested_id = 0;
adv_requested_theme = LDoNThemes::Unused; adv_requested_theme = LDoNTheme::Unused;
safe_delete_array(adv_requested_data); safe_delete_array(adv_requested_data);
adv_requested_member_count = 0; adv_requested_member_count = 0;
} }
@@ -10461,29 +10461,17 @@ void Client::SendToInstance(std::string instance_type, std::string zone_short_na
MovePC(zone_id, instance_id, x, y, z, heading); MovePC(zone_id, instance_id, x, y, z, heading);
} }
int Client::CountItem(uint32 item_id) uint32 Client::CountItem(uint32 item_id)
{ {
int quantity = 0; uint32 quantity = 0;
EQ::ItemInstance *item = nullptr; EQ::ItemInstance *item = nullptr;
static const int16 slots[][2] = {
{ EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END }, for (const int16& slot_id : GetInventorySlots()) {
{ EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END },
{ EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END},
{ EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END },
{ EQ::invslot::GUILD_TRIBUTE_BEGIN, EQ::invslot::GUILD_TRIBUTE_END },
{ EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END },
{ EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END },
{ EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END },
};
const size_t slot_index_count = sizeof(slots) / sizeof(slots[0]);
for (int slot_index = 0; slot_index < slot_index_count; ++slot_index) {
for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) {
item = GetInv().GetItem(slot_id); item = GetInv().GetItem(slot_id);
if (item && item->GetID() == item_id) { if (item && item->GetID() == item_id) {
quantity += (item->IsStackable() ? item->GetCharges() : 1); quantity += (item->IsStackable() ? item->GetCharges() : 1);
} }
} }
}
return quantity; return quantity;
} }
@@ -10498,22 +10486,18 @@ void Client::ResetItemCooldown(uint32 item_id)
int recast_type = item_d->RecastType; int recast_type = item_d->RecastType;
bool found_item = false; bool found_item = false;
static const int16 slots[][2] = { for (const int16& slot_id : GetInventorySlots()) {
{ EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END },
{ EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END },
{ EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END},
{ EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END },
{ EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END },
{ EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END },
{ EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END },
};
const size_t slot_index_count = sizeof(slots) / sizeof(slots[0]);
for (int slot_index = 0; slot_index < slot_index_count; ++slot_index) {
for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) {
item = GetInv().GetItem(slot_id); item = GetInv().GetItem(slot_id);
if (item) { if (item) {
item_d = item->GetItem(); item_d = item->GetItem();
if (item_d && item->GetID() == item_id || (item_d->RecastType != RECAST_TYPE_UNLINKED_ITEM && item_d->RecastType == recast_type)) { if (
item_d &&
item->GetID() == item_id ||
(
item_d->RecastType != RECAST_TYPE_UNLINKED_ITEM &&
item_d->RecastType == recast_type
)
) {
item->SetRecastTimestamp(0); item->SetRecastTimestamp(0);
DeleteItemRecastTimer(item_d->ID); DeleteItemRecastTimer(item_d->ID);
SendItemPacket(slot_id, item, ItemPacketCharmUpdate); SendItemPacket(slot_id, item, ItemPacketCharmUpdate);
@@ -10521,7 +10505,7 @@ void Client::ResetItemCooldown(uint32 item_id)
} }
} }
} }
}
if (!found_item) { if (!found_item) {
DeleteItemRecastTimer(item_id); //We didn't find the item but we still want to remove the timer DeleteItemRecastTimer(item_id); //We didn't find the item but we still want to remove the timer
} }
@@ -10556,28 +10540,23 @@ void Client::SetItemCooldown(uint32 item_id, bool use_saved_timer, uint32 in_sec
final_time = total_time - current_time; final_time = total_time - current_time;
} }
static const int16 slots[][2] = { for (const int16& slot_id : GetInventorySlots()) {
{ EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END },
{ EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END },
{ EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END},
{ EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END },
{ EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END },
{ EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END },
{ EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END },
};
const size_t slot_index_count = sizeof(slots) / sizeof(slots[0]);
for (int slot_index = 0; slot_index < slot_index_count; ++slot_index) {
for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) {
item = GetInv().GetItem(slot_id); item = GetInv().GetItem(slot_id);
if (item) { if (item) {
item_d = item->GetItem(); item_d = item->GetItem();
if (item_d && item->GetID() == item_id || (item_d->RecastType != RECAST_TYPE_UNLINKED_ITEM && item_d->RecastType == recast_type)) { if (
item_d &&
item->GetID() == item_id ||
(
item_d->RecastType != RECAST_TYPE_UNLINKED_ITEM &&
item_d->RecastType == recast_type
)
) {
item->SetRecastTimestamp(total_time); item->SetRecastTimestamp(total_time);
SendItemPacket(slot_id, item, ItemPacketCharmUpdate); SendItemPacket(slot_id, item, ItemPacketCharmUpdate);
} }
} }
} }
}
//Start timers and update in database only when timer is changed //Start timers and update in database only when timer is changed
if (!use_saved_timer) { if (!use_saved_timer) {
@@ -10617,34 +10596,23 @@ uint32 Client::GetItemCooldown(uint32 item_id)
void Client::RemoveItem(uint32 item_id, uint32 quantity) void Client::RemoveItem(uint32 item_id, uint32 quantity)
{ {
uint32 removed_count = 0;
EQ::ItemInstance *item = nullptr; EQ::ItemInstance *item = nullptr;
static const int16 slots[][2] = {
{ EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END }, for (const int16& slot_id : GetInventorySlots()) {
{ EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END },
{ EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END},
{ EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END },
{ EQ::invslot::GUILD_TRIBUTE_BEGIN, EQ::invslot::GUILD_TRIBUTE_END },
{ EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END },
{ EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END },
{ EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END },
};
int16 removed_count = 0;
const size_t slot_index_count = sizeof(slots) / sizeof(slots[0]);
for (int slot_index = 0; slot_index < slot_index_count; ++slot_index) {
for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) {
if (removed_count == quantity) { if (removed_count == quantity) {
break; break;
} }
item = GetInv().GetItem(slot_id); item = GetInv().GetItem(slot_id);
if (item && item->GetID() == item_id) { if (item && item->GetID() == item_id) {
int16 charges = item->IsStackable() ? item->GetCharges() : 0; uint32 charges = item->IsStackable() ? item->GetCharges() : 0;
int16 stack_size = std::max(charges, static_cast<int16>(1)); uint32 stack_size = std::max(charges, static_cast<uint32>(1));
if ((removed_count + stack_size) <= quantity) { if ((removed_count + stack_size) <= quantity) {
removed_count += stack_size; removed_count += stack_size;
DeleteItemInInventory(slot_id, charges, true); DeleteItemInInventory(slot_id, charges, true);
} else { } else {
int16 amount_left = (quantity - removed_count); uint32 amount_left = (quantity - removed_count);
if (amount_left > 0 && stack_size >= amount_left) { if (amount_left > 0 && stack_size >= amount_left) {
removed_count += amount_left; removed_count += amount_left;
DeleteItemInInventory(slot_id, amount_left, true); DeleteItemInInventory(slot_id, amount_left, true);
@@ -10653,7 +10621,6 @@ void Client::RemoveItem(uint32 item_id, uint32 quantity)
} }
} }
} }
}
void Client::SetGMStatus(int new_status) { void Client::SetGMStatus(int new_status) {
if (Admin() != new_status) { if (Admin() != new_status) {
@@ -12820,33 +12787,25 @@ uint16 Client::GetSkill(EQ::skills::SkillType skill_id) const
void Client::RemoveItemBySerialNumber(uint32 serial_number, uint32 quantity) void Client::RemoveItemBySerialNumber(uint32 serial_number, uint32 quantity)
{ {
EQ::ItemInstance *item = nullptr; EQ::ItemInstance *item = nullptr;
static const int16 slots[][2] = {
{ EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END }, uint32 removed_count = 0;
{ EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END },
{ EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END}, const auto& slot_ids = GetInventorySlots();
{ EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END },
{ EQ::invslot::GUILD_TRIBUTE_BEGIN, EQ::invslot::GUILD_TRIBUTE_END }, for (const int16& slot_id : slot_ids) {
{ EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END },
{ EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END },
{ EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END },
};
int16 removed_count = 0;
const size_t slot_index_count = sizeof(slots) / sizeof(slots[0]);
for (int slot_index = 0; slot_index < slot_index_count; ++slot_index) {
for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) {
if (removed_count == quantity) { if (removed_count == quantity) {
break; break;
} }
item = GetInv().GetItem(slot_id); item = GetInv().GetItem(slot_id);
if (item && item->GetSerialNumber() == serial_number) { if (item && item->GetSerialNumber() == serial_number) {
int16 charges = item->IsStackable() ? item->GetCharges() : 0; uint32 charges = item->IsStackable() ? item->GetCharges() : 0;
int16 stack_size = std::max(charges, static_cast<int16>(1)); uint32 stack_size = std::max(charges, static_cast<uint32>(1));
if ((removed_count + stack_size) <= quantity) { if ((removed_count + stack_size) <= quantity) {
removed_count += stack_size; removed_count += stack_size;
DeleteItemInInventory(slot_id, charges, true); DeleteItemInInventory(slot_id, charges, true);
} else { } else {
int16 amount_left = (quantity - removed_count); uint32 amount_left = (quantity - removed_count);
if (amount_left > 0 && stack_size >= amount_left) { if (amount_left > 0 && stack_size >= amount_left) {
removed_count += amount_left; removed_count += amount_left;
DeleteItemInInventory(slot_id, amount_left, true); DeleteItemInInventory(slot_id, amount_left, true);
@@ -12855,7 +12814,6 @@ void Client::RemoveItemBySerialNumber(uint32 serial_number, uint32 quantity)
} }
} }
} }
}
void Client::AddMoneyToPPWithOverflow(uint64 copper, bool update_client) void Client::AddMoneyToPPWithOverflow(uint64 copper, bool update_client)
{ {
@@ -13075,3 +13033,28 @@ void Client::ClientToNpcAggroProcess()
LogAggro("Checking Reverse Aggro (client->npc) scanned_npcs ([{}])", npc_scan_count); LogAggro("Checking Reverse Aggro (client->npc) scanned_npcs ([{}])", npc_scan_count);
} }
} }
const std::vector<int16>& Client::GetInventorySlots()
{
static const std::vector<std::pair<int16, int16>> slots = {
{ EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END },
{ EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END },
{ EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END },
{ EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END },
{ EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END },
{ EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END },
{ EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END },
};
static std::vector<int16> slot_ids;
if (slot_ids.empty()) {
for (const auto& [begin, end] : slots) {
for (int16 slot_id = begin; slot_id <= end; ++slot_id) {
slot_ids.emplace_back(slot_id);
}
}
}
return slot_ids;
}
+2 -1
View File
@@ -467,6 +467,7 @@ public:
inline ExtendedProfile_Struct& GetEPP() { return m_epp; } inline ExtendedProfile_Struct& GetEPP() { return m_epp; }
inline EQ::InventoryProfile& GetInv() { return m_inv; } inline EQ::InventoryProfile& GetInv() { return m_inv; }
inline const EQ::InventoryProfile& GetInv() const { return m_inv; } inline const EQ::InventoryProfile& GetInv() const { return m_inv; }
const std::vector<int16>& GetInventorySlots();
inline PetInfo* GetPetInfo(int pet_info_type) { return pet_info_type == PetInfoType::Suspended ? &m_suspendedminion : &m_petinfo; } inline PetInfo* GetPetInfo(int pet_info_type) { return pet_info_type == PetInfoType::Suspended ? &m_suspendedminion : &m_petinfo; }
inline InspectMessage_Struct& GetInspectMessage() { return m_inspect_message; } inline InspectMessage_Struct& GetInspectMessage() { return m_inspect_message; }
inline const InspectMessage_Struct& GetInspectMessage() const { return m_inspect_message; } inline const InspectMessage_Struct& GetInspectMessage() const { return m_inspect_message; }
@@ -1093,7 +1094,7 @@ public:
bool PushItemOnCursor(const EQ::ItemInstance& inst, bool client_update = false); bool PushItemOnCursor(const EQ::ItemInstance& inst, bool client_update = false);
void SendCursorBuffer(); void SendCursorBuffer();
void DeleteItemInInventory(int16 slot_id, int16 quantity = 0, bool client_update = false, bool update_db = true); void DeleteItemInInventory(int16 slot_id, int16 quantity = 0, bool client_update = false, bool update_db = true);
int CountItem(uint32 item_id); uint32 CountItem(uint32 item_id);
void ResetItemCooldown(uint32 item_id); void ResetItemCooldown(uint32 item_id);
void SetItemCooldown(uint32 item_id, bool use_saved_timer = false, uint32 in_seconds = 1); void SetItemCooldown(uint32 item_id, bool use_saved_timer = false, uint32 in_seconds = 1);
uint32 GetItemCooldown(uint32 item_id); uint32 GetItemCooldown(uint32 item_id);
+44 -135
View File
@@ -524,7 +524,6 @@ int Client::HandlePacket(const EQApplicationPacket *app)
// Finish client connecting state // Finish client connecting state
void Client::CompleteConnect() void Client::CompleteConnect()
{ {
UpdateWho(); UpdateWho();
client_state = CLIENT_CONNECTED; client_state = CLIENT_CONNECTED;
SendAllPackets(); SendAllPackets();
@@ -861,7 +860,7 @@ void Client::CompleteConnect()
if (IsInAGuild()) { if (IsInAGuild()) {
if (firstlogon == 1) { if (firstlogon == 1) {
guild_mgr.UpdateDbMemberOnline(CharacterID(), true); guild_mgr.UpdateDbMemberOnline(CharacterID(), true);
guild_mgr.SendToWorldSendGuildMembersList(GuildID()); SendGuildMembersList();
} }
guild_mgr.SendGuildMemberUpdateToWorld(GetName(), GuildID(), zone->GetZoneID(), time(nullptr)); guild_mgr.SendGuildMemberUpdateToWorld(GetName(), GuildID(), zone->GetZoneID(), time(nullptr));
@@ -913,10 +912,6 @@ void Client::CompleteConnect()
CastToClient()->FastQueuePacket(&outapp); CastToClient()->FastQueuePacket(&outapp);
} }
if (ClientVersion() >= EQ::versions::ClientVersion::RoF) {
SendBulkBazaarTraders();
}
// TODO: load these states // TODO: load these states
// We at least will set them to the correct state for now // We at least will set them to the correct state for now
if (m_ClientVersionBit & EQ::versions::maskUFAndLater && GetPet()) { if (m_ClientVersionBit & EQ::versions::maskUFAndLater && GetPet()) {
@@ -1413,6 +1408,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
drakkin_details = m_pp.drakkin_details; drakkin_details = m_pp.drakkin_details;
// Load Data Buckets // Load Data Buckets
ClearDataBucketCache();
DataBucket::GetDataBuckets(this); DataBucket::GetDataBuckets(this);
// Max Level for Character:PerCharacterQglobalMaxLevel and Character:PerCharacterBucketMaxLevel // Max Level for Character:PerCharacterQglobalMaxLevel and Character:PerCharacterBucketMaxLevel
@@ -2023,38 +2019,38 @@ void Client::Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app)
return; return;
} }
if (item->LDoNTheme <= LDoNThemeBits::TAKBit) { if (item->LDoNTheme <= LDoNTheme::TAKBit) {
uint32 ldon_theme; uint32 ldon_theme;
if (item->LDoNTheme & LDoNThemeBits::TAKBit) { if (item->LDoNTheme & LDoNTheme::TAKBit) {
if (m_pp.ldon_points_tak < item_cost) { if (m_pp.ldon_points_tak < item_cost) {
cannot_afford = true; cannot_afford = true;
ldon_theme = LDoNThemes::TAK; ldon_theme = LDoNTheme::TAK;
} }
} else if (item->LDoNTheme & LDoNThemeBits::RUJBit) { } else if (item->LDoNTheme & LDoNTheme::RUJBit) {
if (m_pp.ldon_points_ruj < item_cost) { if (m_pp.ldon_points_ruj < item_cost) {
cannot_afford = true; cannot_afford = true;
ldon_theme = LDoNThemes::RUJ; ldon_theme = LDoNTheme::RUJ;
} }
} else if (item->LDoNTheme & LDoNThemeBits::MMCBit) { } else if (item->LDoNTheme & LDoNTheme::MMCBit) {
if (m_pp.ldon_points_mmc < item_cost) { if (m_pp.ldon_points_mmc < item_cost) {
cannot_afford = true; cannot_afford = true;
ldon_theme = LDoNThemes::MMC; ldon_theme = LDoNTheme::MMC;
} }
} else if (item->LDoNTheme & LDoNThemeBits::MIRBit) { } else if (item->LDoNTheme & LDoNTheme::MIRBit) {
if (m_pp.ldon_points_mir < item_cost) { if (m_pp.ldon_points_mir < item_cost) {
cannot_afford = true; cannot_afford = true;
ldon_theme = LDoNThemes::MIR; ldon_theme = LDoNTheme::MIR;
} }
} else if (item->LDoNTheme & LDoNThemeBits::GUKBit) { } else if (item->LDoNTheme & LDoNTheme::GUKBit) {
if (m_pp.ldon_points_guk < item_cost) { if (m_pp.ldon_points_guk < item_cost) {
cannot_afford = true; cannot_afford = true;
ldon_theme = LDoNThemes::GUK; ldon_theme = LDoNTheme::GUK;
} }
} }
merchant_type = fmt::format( merchant_type = fmt::format(
"{} Point{}", "{} Point{}",
EQ::constants::GetLDoNThemeName(ldon_theme), LDoNTheme::GetName(ldon_theme),
item_cost != 1 ? "s" : "" item_cost != 1 ? "s" : ""
); );
} }
@@ -2198,19 +2194,19 @@ void Client::Handle_OP_AdventureMerchantRequest(const EQApplicationPacket *app)
item = database.GetItem(ml.item); item = database.GetItem(ml.item);
if (item) { if (item) {
uint32 theme = LDoNThemes::Unused; uint32 theme = LDoNTheme::Unused;
if (item->LDoNTheme > LDoNThemeBits::TAKBit) { if (item->LDoNTheme > LDoNTheme::TAKBit) {
theme = LDoNThemes::Unused; theme = LDoNTheme::Unused;
} else if (item->LDoNTheme & LDoNThemeBits::TAKBit) { } else if (item->LDoNTheme & LDoNTheme::TAKBit) {
theme = LDoNThemes::TAK; theme = LDoNTheme::TAK;
} else if (item->LDoNTheme & LDoNThemeBits::RUJBit) { } else if (item->LDoNTheme & LDoNTheme::RUJBit) {
theme = LDoNThemes::RUJ; theme = LDoNTheme::RUJ;
} else if (item->LDoNTheme & LDoNThemeBits::MMCBit) { } else if (item->LDoNTheme & LDoNTheme::MMCBit) {
theme = LDoNThemes::MMC; theme = LDoNTheme::MMC;
} else if (item->LDoNTheme & LDoNThemeBits::MIRBit) { } else if (item->LDoNTheme & LDoNTheme::MIRBit) {
theme = LDoNThemes::MIR; theme = LDoNTheme::MIR;
} else if (item->LDoNTheme & LDoNThemeBits::GUKBit) { } else if (item->LDoNTheme & LDoNTheme::GUKBit) {
theme = LDoNThemes::GUK; theme = LDoNTheme::GUK;
} }
ss << "^" << item->Name << "|"; ss << "^" << item->Name << "|";
ss << item->ID << "|"; ss << item->ID << "|";
@@ -3251,30 +3247,14 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app)
args.push_back(old_aug); args.push_back(old_aug);
if (parse->ItemHasQuestSub(tobe_auged, EVENT_UNAUGMENT_ITEM)) { if (parse->ItemHasQuestSub(tobe_auged, EVENT_UNAUGMENT_ITEM)) {
parse->EventItem( parse->EventItem(EVENT_UNAUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args);
EVENT_UNAUGMENT_ITEM,
this,
tobe_auged,
nullptr,
"",
in_augment->augment_index,
&args
);
} }
args.assign(1, tobe_auged); args.assign(1, tobe_auged);
args.push_back(false); args.push_back(false);
if (parse->ItemHasQuestSub(old_aug, EVENT_AUGMENT_REMOVE)) { if (parse->ItemHasQuestSub(old_aug, EVENT_AUGMENT_REMOVE)) {
parse->EventItem( parse->EventItem(EVENT_AUGMENT_REMOVE, this, old_aug, nullptr, "", in_augment->augment_index, &args);
EVENT_AUGMENT_REMOVE,
this,
old_aug,
nullptr,
"",
in_augment->augment_index,
&args
);
} }
if (parse->PlayerHasQuestSub(EVENT_AUGMENT_REMOVE_CLIENT)) { if (parse->PlayerHasQuestSub(EVENT_AUGMENT_REMOVE_CLIENT)) {
@@ -3306,29 +3286,13 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app)
args.push_back(aug); args.push_back(aug);
if (parse->ItemHasQuestSub(tobe_auged, EVENT_AUGMENT_ITEM)) { if (parse->ItemHasQuestSub(tobe_auged, EVENT_AUGMENT_ITEM)) {
parse->EventItem( parse->EventItem(EVENT_AUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args);
EVENT_AUGMENT_ITEM,
this,
tobe_auged,
nullptr,
"",
in_augment->augment_index,
&args
);
} }
args.assign(1, tobe_auged); args.assign(1, tobe_auged);
if (parse->ItemHasQuestSub(aug, EVENT_AUGMENT_INSERT)) { if (parse->ItemHasQuestSub(aug, EVENT_AUGMENT_INSERT)) {
parse->EventItem( parse->EventItem(EVENT_AUGMENT_INSERT, this, aug, nullptr, "", in_augment->augment_index, &args);
EVENT_AUGMENT_INSERT,
this,
aug,
nullptr,
"",
in_augment->augment_index,
&args
);
} }
args.push_back(aug); args.push_back(aug);
@@ -3398,30 +3362,14 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app)
args.push_back(aug); args.push_back(aug);
if (parse->ItemHasQuestSub(tobe_auged, EVENT_UNAUGMENT_ITEM)) { if (parse->ItemHasQuestSub(tobe_auged, EVENT_UNAUGMENT_ITEM)) {
parse->EventItem( parse->EventItem(EVENT_UNAUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args);
EVENT_UNAUGMENT_ITEM,
this,
tobe_auged,
nullptr,
"",
in_augment->augment_index,
&args
);
} }
args.assign(1, tobe_auged); args.assign(1, tobe_auged);
args.push_back(false); args.push_back(false);
if (parse->ItemHasQuestSub(aug, EVENT_AUGMENT_REMOVE)) { if (parse->ItemHasQuestSub(aug, EVENT_AUGMENT_REMOVE)) {
parse->EventItem( parse->EventItem(EVENT_AUGMENT_REMOVE, this, aug, nullptr, "", in_augment->augment_index, &args);
EVENT_AUGMENT_REMOVE,
this,
aug,
nullptr,
"",
in_augment->augment_index,
&args
);
} }
args.push_back(aug); args.push_back(aug);
@@ -3486,30 +3434,14 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app)
args.push_back(aug); args.push_back(aug);
if (parse->ItemHasQuestSub(tobe_auged, EVENT_UNAUGMENT_ITEM)) { if (parse->ItemHasQuestSub(tobe_auged, EVENT_UNAUGMENT_ITEM)) {
parse->EventItem( parse->EventItem(EVENT_UNAUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args);
EVENT_UNAUGMENT_ITEM,
this,
tobe_auged,
nullptr,
"",
in_augment->augment_index,
&args
);
} }
args.assign(1, tobe_auged); args.assign(1, tobe_auged);
args.push_back(true); args.push_back(true);
if (parse->ItemHasQuestSub(aug, EVENT_AUGMENT_REMOVE)) { if (parse->ItemHasQuestSub(aug, EVENT_AUGMENT_REMOVE)) {
parse->EventItem( parse->EventItem(EVENT_AUGMENT_REMOVE, this, aug, nullptr, "", in_augment->augment_index, &args);
EVENT_AUGMENT_REMOVE,
this,
aug,
nullptr,
"",
in_augment->augment_index,
&args
);
} }
args.push_back(aug); args.push_back(aug);
@@ -3985,6 +3917,10 @@ void Client::Handle_OP_BazaarSearch(const EQApplicationPacket *app)
SendBazaarWelcome(); SendBazaarWelcome();
break; break;
} }
case FirstOpenSearch: {
SendBulkBazaarTraders();
break;
}
default: { default: {
LogError("Malformed BazaarSearch_Struct packet received, ignoring\n"); LogError("Malformed BazaarSearch_Struct packet received, ignoring\n");
} }
@@ -4479,14 +4415,7 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app)
int i = 0; int i = 0;
if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) { if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) {
i = parse->EventItem( i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, nullptr, "", castspell->inventoryslot);
EVENT_ITEM_CLICK_CAST,
this,
p_inst,
nullptr,
"",
castspell->inventoryslot
);
} }
if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) { if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) {
@@ -4518,14 +4447,7 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app)
int i = 0; int i = 0;
if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) { if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) {
i = parse->EventItem( i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, nullptr, "", castspell->inventoryslot);
EVENT_ITEM_CLICK_CAST,
this,
p_inst,
nullptr,
"",
castspell->inventoryslot
);
} }
if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) { if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) {
@@ -8015,6 +7937,7 @@ void Client::Handle_OP_GuildCreate(const EQApplicationPacket *app)
SetGuildID(new_guild_id); SetGuildID(new_guild_id);
SendGuildList(); SendGuildList();
guild_mgr.MemberAdd(new_guild_id, CharacterID(), GetLevel(), GetClass(), GUILD_LEADER, GetZoneID(), GetName()); guild_mgr.MemberAdd(new_guild_id, CharacterID(), GetLevel(), GetClass(), GUILD_LEADER, GetZoneID(), GetName());
guild_mgr.SendGuildRefresh(new_guild_id, true, true, true, true);
guild_mgr.SendToWorldSendGuildList(); guild_mgr.SendToWorldSendGuildList();
SendGuildSpawnAppearance(); SendGuildSpawnAppearance();
@@ -9591,14 +9514,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
int i = 0; int i = 0;
if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) { if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) {
i = parse->EventItem( i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, nullptr, "", slot_id);
EVENT_ITEM_CLICK_CAST,
this,
p_inst,
nullptr,
"",
slot_id
);
} }
if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) { if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) {
@@ -9662,14 +9578,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
int i = 0; int i = 0;
if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) { if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) {
i = parse->EventItem( i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, clickaug, nullptr, "", slot_id);
EVENT_ITEM_CLICK_CAST,
this,
clickaug,
nullptr,
"",
slot_id
);
} }
if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) { if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) {
+3 -3
View File
@@ -179,7 +179,7 @@ bool Client::Process() {
} }
if (IsInAGuild()) { if (IsInAGuild()) {
guild_mgr.UpdateDbMemberOnline(CharacterID(), false); guild_mgr.UpdateDbMemberOnline(CharacterID(), false);
guild_mgr.SendToWorldSendGuildMembersList(GuildID()); guild_mgr.SendGuildMemberUpdateToWorld(GetName(), GuildID(), 0, time(nullptr));
} }
SetDynamicZoneMemberStatus(DynamicZoneMemberStatus::Offline); SetDynamicZoneMemberStatus(DynamicZoneMemberStatus::Offline);
@@ -202,7 +202,7 @@ bool Client::Process() {
Save(); Save();
if (IsInAGuild()) { if (IsInAGuild()) {
guild_mgr.UpdateDbMemberOnline(CharacterID(), false); guild_mgr.UpdateDbMemberOnline(CharacterID(), false);
guild_mgr.SendToWorldSendGuildMembersList(GuildID()); guild_mgr.SendGuildMemberUpdateToWorld(GetName(), GuildID(), 0, time(nullptr));
} }
if (GetMerc()) if (GetMerc())
@@ -578,7 +578,7 @@ bool Client::Process() {
} }
if (IsInAGuild()) { if (IsInAGuild()) {
guild_mgr.UpdateDbMemberOnline(CharacterID(), false); guild_mgr.UpdateDbMemberOnline(CharacterID(), false);
guild_mgr.SendToWorldSendGuildMembersList(GuildID()); guild_mgr.SendGuildMemberUpdateToWorld(GetName(), GuildID(), 0, time(nullptr));
} }
return false; return false;
+4 -2
View File
@@ -1871,9 +1871,10 @@ bool Corpse::HasItem(uint32 item_id)
return false; return false;
} }
uint16 Corpse::CountItem(uint32 item_id) uint32 Corpse::CountItem(uint32 item_id)
{ {
uint16 item_count = 0; uint32 item_count = 0;
if (!database.GetItem(item_id)) { if (!database.GetItem(item_id)) {
return item_count; return item_count;
} }
@@ -1893,6 +1894,7 @@ uint16 Corpse::CountItem(uint32 item_id)
item_count += i->charges > 0 ? i->charges : 1; item_count += i->charges > 0 ? i->charges : 1;
} }
} }
return item_count; return item_count;
} }
+1 -1
View File
@@ -196,7 +196,7 @@ public:
/* Corpse: Loot */ /* Corpse: Loot */
void QueryLoot(Client *to); void QueryLoot(Client *to);
bool HasItem(uint32 item_id); bool HasItem(uint32 item_id);
uint16 CountItem(uint32 item_id); uint32 CountItem(uint32 item_id);
uint32 GetItemIDBySlot(uint16 loot_slot); uint32 GetItemIDBySlot(uint16 loot_slot);
uint16 GetFirstLootSlotByItemID(uint32 item_id); uint16 GetFirstLootSlotByItemID(uint32 item_id);
std::vector<int> GetLootList(); std::vector<int> GetLootList();
+110 -232
View File
@@ -8,7 +8,7 @@
extern WorldServer worldserver; extern WorldServer worldserver;
std::vector<DataBucketCacheEntry> g_data_bucket_cache = {}; std::vector<DataBucketsRepository::DataBuckets> g_data_bucket_cache = {};
void DataBucket::SetData(const std::string &bucket_key, const std::string &bucket_value, std::string expires_time) void DataBucket::SetData(const std::string &bucket_key, const std::string &bucket_value, std::string expires_time)
{ {
@@ -58,44 +58,34 @@ void DataBucket::SetData(const DataBucketKey &k)
b.value = k.value; b.value = k.value;
if (bucket_id) { if (bucket_id) {
// loop cache and update cache value and timestamp
for (auto &ce: g_data_bucket_cache) { // update the cache if it exists
if (CheckBucketMatch(ce.e, k)) { if (CanCache(k)) {
ce.e = b; for (auto &e: g_data_bucket_cache) {
ce.updated_time = GetCurrentTimeUNIX(); if (CheckBucketMatch(e, k)) {
ce.update_action = DataBucketCacheUpdateAction::Upsert; e = b;
SendDataBucketCacheUpdate(ce);
break; break;
} }
} }
}
DataBucketsRepository::UpdateOne(database, b); DataBucketsRepository::UpdateOne(database, b);
} }
else { else {
b.key_ = k.key; b.key_ = k.key;
b = DataBucketsRepository::InsertOne(database, b); b = DataBucketsRepository::InsertOne(database, b);
if (!ExistsInCache(b)) {
// add data bucket and timestamp to cache
auto ce = DataBucketCacheEntry{
.e = b,
.updated_time = DataBucket::GetCurrentTimeUNIX(),
.update_action = DataBucketCacheUpdateAction::Upsert
};
g_data_bucket_cache.emplace_back(ce);
SendDataBucketCacheUpdate(ce);
// add to cache if it doesn't exist
if (CanCache(k) && !ExistsInCache(b)) {
DeleteFromMissesCache(b); DeleteFromMissesCache(b);
g_data_bucket_cache.emplace_back(b);
} }
} }
} }
std::string DataBucket::GetData(const std::string &bucket_key) std::string DataBucket::GetData(const std::string &bucket_key)
{ {
DataBucketKey k = {}; return GetData(DataBucketKey{.key = bucket_key}).value;
k.key = bucket_key;
return GetData(k).value;
} }
// GetData fetches bucket data from the database or cache if it exists // GetData fetches bucket data from the database or cache if it exists
@@ -112,22 +102,27 @@ DataBucketsRepository::DataBuckets DataBucket::GetData(const DataBucketKey &k, b
k.npc_id k.npc_id
); );
for (const auto &ce: g_data_bucket_cache) { bool can_cache = CanCache(k);
if (CheckBucketMatch(ce.e, k)) {
if (ce.e.expires > 0 && ce.e.expires < std::time(nullptr)) { // check the cache first if we can cache
LogDataBuckets("Attempted to read expired key [{}] removing from cache", ce.e.key_); if (can_cache) {
for (const auto &e: g_data_bucket_cache) {
if (CheckBucketMatch(e, k)) {
if (e.expires > 0 && e.expires < std::time(nullptr)) {
LogDataBuckets("Attempted to read expired key [{}] removing from cache", e.key_);
DeleteData(k); DeleteData(k);
return DataBucketsRepository::NewEntity(); return DataBucketsRepository::NewEntity();
} }
// this is a bucket miss, return empty entity // this is a bucket miss, return empty entity
// we still cache bucket misses, so we don't have to hit the database // we still cache bucket misses, so we don't have to hit the database
if (ce.e.id == 0) { if (e.id == 0) {
return DataBucketsRepository::NewEntity(); return DataBucketsRepository::NewEntity();
} }
LogDataBuckets("Returning key [{}] value [{}] from cache", ce.e.key_, ce.e.value); LogDataBuckets("Returning key [{}] value [{}] from cache", e.key_, e.value);
return ce.e; return e;
}
} }
} }
@@ -144,14 +139,14 @@ DataBucketsRepository::DataBuckets DataBucket::GetData(const DataBucketKey &k, b
// if we're ignoring the misses cache, don't add to the cache // if we're ignoring the misses cache, don't add to the cache
// the only place this is ignored is during the initial read of SetData // the only place this is ignored is during the initial read of SetData
if (!ignore_misses_cache) { bool add_to_misses_cache = !ignore_misses_cache && can_cache;
if (add_to_misses_cache) {
size_t size_before = g_data_bucket_cache.size(); size_t size_before = g_data_bucket_cache.size();
// cache bucket misses, so we don't have to hit the database // cache bucket misses, so we don't have to hit the database
// when scripts try to read a bucket that doesn't exist // when scripts try to read a bucket that doesn't exist
g_data_bucket_cache.emplace_back( g_data_bucket_cache.emplace_back(
DataBucketCacheEntry{ DataBucketsRepository::DataBuckets{
.e = DataBucketsRepository::DataBuckets{
.id = 0, .id = 0,
.key_ = k.key, .key_ = k.key,
.value = "", .value = "",
@@ -159,8 +154,6 @@ DataBucketsRepository::DataBuckets DataBucket::GetData(const DataBucketKey &k, b
.character_id = k.character_id, .character_id = k.character_id,
.npc_id = k.npc_id, .npc_id = k.npc_id,
.bot_id = k.bot_id .bot_id = k.bot_id
},
.updated_time = DataBucket::GetCurrentTimeUNIX()
} }
); );
@@ -178,59 +171,53 @@ DataBucketsRepository::DataBuckets DataBucket::GetData(const DataBucketKey &k, b
return {}; return {};
} }
auto bucket = r.front();
// if the entry has expired, delete it // if the entry has expired, delete it
if (r[0].expires > 0 && r[0].expires < (long long) std::time(nullptr)) { if (bucket.expires > 0 && bucket.expires < (long long) std::time(nullptr)) {
DeleteData(k); DeleteData(k);
return {}; return {};
} }
// add to cache if it doesn't exist
if (can_cache) {
bool has_cache = false; bool has_cache = false;
for (auto &ce: g_data_bucket_cache) {
if (ce.e.id == r[0].id) { for (auto &e: g_data_bucket_cache) {
if (e.id == bucket.id) {
has_cache = true; has_cache = true;
break; break;
} }
} }
if (!has_cache) { if (!has_cache) {
// add data bucket and timestamp to cache g_data_bucket_cache.emplace_back(bucket);
g_data_bucket_cache.emplace_back(
DataBucketCacheEntry{
.e = r[0],
.updated_time = DataBucket::GetCurrentTimeUNIX()
} }
);
} }
return r[0]; return bucket;
} }
std::string DataBucket::GetDataExpires(const std::string &bucket_key) std::string DataBucket::GetDataExpires(const std::string &bucket_key)
{ {
DataBucketKey k = {}; return GetDataExpires(DataBucketKey{.key = bucket_key});
k.key = bucket_key;
return GetDataExpires(k);
} }
std::string DataBucket::GetDataRemaining(const std::string &bucket_key) std::string DataBucket::GetDataRemaining(const std::string &bucket_key)
{ {
DataBucketKey k = {}; return GetDataRemaining(DataBucketKey{.key = bucket_key});
k.key = bucket_key;
return GetDataRemaining(k);
} }
bool DataBucket::DeleteData(const std::string &bucket_key) bool DataBucket::DeleteData(const std::string &bucket_key)
{ {
DataBucketKey k = {}; return DeleteData(DataBucketKey{.key = bucket_key});
k.key = bucket_key;
return DeleteData(k);
} }
// GetDataBuckets bulk loads all data buckets for a mob // GetDataBuckets bulk loads all data buckets for a mob
bool DataBucket::GetDataBuckets(Mob *mob) bool DataBucket::GetDataBuckets(Mob *mob)
{ {
DataBucketLoadType::Type t; DataBucketLoadType::Type t{};
const uint32 id = mob->GetMobTypeIdentifier(); const uint32 id = mob->GetMobTypeIdentifier();
if (!id) { if (!id) {
@@ -243,17 +230,15 @@ bool DataBucket::GetDataBuckets(Mob *mob)
else if (mob->IsClient()) { else if (mob->IsClient()) {
t = DataBucketLoadType::Client; t = DataBucketLoadType::Client;
} }
else if (mob->IsNPC()) {
t = DataBucketLoadType::NPC;
}
BulkLoadEntities(t, {id}); BulkLoadEntitiesToCache(t, {id});
return true; return true;
} }
bool DataBucket::DeleteData(const DataBucketKey &k) bool DataBucket::DeleteData(const DataBucketKey &k)
{ {
if (CanCache(k)) {
size_t size_before = g_data_bucket_cache.size(); size_t size_before = g_data_bucket_cache.size();
// delete from cache where contents match // delete from cache where contents match
@@ -261,14 +246,8 @@ bool DataBucket::DeleteData(const DataBucketKey &k)
std::remove_if( std::remove_if(
g_data_bucket_cache.begin(), g_data_bucket_cache.begin(),
g_data_bucket_cache.end(), g_data_bucket_cache.end(),
[&](DataBucketCacheEntry &ce) { [&](DataBucketsRepository::DataBuckets &e) {
bool match = CheckBucketMatch(ce.e, k); return CheckBucketMatch(e, k);
if (match) {
ce.update_action = DataBucketCacheUpdateAction::Delete;
SendDataBucketCacheUpdate(ce);
}
return match;
} }
), ),
g_data_bucket_cache.end() g_data_bucket_cache.end()
@@ -283,6 +262,7 @@ bool DataBucket::DeleteData(const DataBucketKey &k)
size_before, size_before,
g_data_bucket_cache.size() g_data_bucket_cache.size()
); );
}
return DataBucketsRepository::DeleteWhere( return DataBucketsRepository::DeleteWhere(
database, database,
@@ -371,7 +351,7 @@ bool DataBucket::CheckBucketMatch(const DataBucketsRepository::DataBuckets &dbe,
); );
} }
void DataBucket::BulkLoadEntities(DataBucketLoadType::Type t, std::vector<uint32> ids) void DataBucket::BulkLoadEntitiesToCache(DataBucketLoadType::Type t, std::vector<uint32> ids)
{ {
if (ids.empty()) { if (ids.empty()) {
return; return;
@@ -379,15 +359,13 @@ void DataBucket::BulkLoadEntities(DataBucketLoadType::Type t, std::vector<uint32
if (ids.size() == 1) { if (ids.size() == 1) {
bool has_cache = false; bool has_cache = false;
for (const auto &ce: g_data_bucket_cache) {
for (const auto &e: g_data_bucket_cache) {
if (t == DataBucketLoadType::Bot) { if (t == DataBucketLoadType::Bot) {
has_cache = ce.e.bot_id == ids[0]; has_cache = e.bot_id == ids[0];
} }
else if (t == DataBucketLoadType::Client) { else if (t == DataBucketLoadType::Client) {
has_cache = ce.e.character_id == ids[0]; has_cache = e.character_id == ids[0];
}
else if (t == DataBucketLoadType::NPC) {
has_cache = ce.e.npc_id == ids[0];
} }
} }
@@ -406,9 +384,6 @@ void DataBucket::BulkLoadEntities(DataBucketLoadType::Type t, std::vector<uint32
case DataBucketLoadType::Client: case DataBucketLoadType::Client:
column = "character_id"; column = "character_id";
break; break;
case DataBucketLoadType::NPC:
column = "npc_id";
break;
default: default:
LogError("Incorrect LoadType [{}]", static_cast<int>(t)); LogError("Incorrect LoadType [{}]", static_cast<int>(t));
break; break;
@@ -442,12 +417,7 @@ void DataBucket::BulkLoadEntities(DataBucketLoadType::Type t, std::vector<uint32
if (!ExistsInCache(e)) { if (!ExistsInCache(e)) {
LogDataBucketsDetail("bucket id [{}] bucket key [{}] bucket value [{}]", e.id, e.key_, e.value); LogDataBucketsDetail("bucket id [{}] bucket key [{}] bucket value [{}]", e.id, e.key_, e.value);
g_data_bucket_cache.emplace_back( g_data_bucket_cache.emplace_back(e);
DataBucketCacheEntry{
.e = e,
.updated_time = GetCurrentTimeUNIX()
}
);
} }
} }
@@ -461,7 +431,7 @@ void DataBucket::BulkLoadEntities(DataBucketLoadType::Type t, std::vector<uint32
); );
} }
void DataBucket::DeleteCachedBuckets(DataBucketLoadType::Type t, uint32 id) void DataBucket::DeleteCachedBuckets(DataBucketLoadType::Type type, uint32 id)
{ {
size_t size_before = g_data_bucket_cache.size(); size_t size_before = g_data_bucket_cache.size();
@@ -469,11 +439,10 @@ void DataBucket::DeleteCachedBuckets(DataBucketLoadType::Type t, uint32 id)
std::remove_if( std::remove_if(
g_data_bucket_cache.begin(), g_data_bucket_cache.begin(),
g_data_bucket_cache.end(), g_data_bucket_cache.end(),
[&](DataBucketCacheEntry &ce) { [&](DataBucketsRepository::DataBuckets &e) {
return ( return (
(t == DataBucketLoadType::Bot && ce.e.bot_id == id) || (type == DataBucketLoadType::Bot && e.bot_id == id) ||
(t == DataBucketLoadType::Client && ce.e.character_id == id) || (type == DataBucketLoadType::Client && e.character_id == id)
(t == DataBucketLoadType::NPC && ce.e.npc_id == id)
); );
} }
), ),
@@ -482,24 +451,17 @@ void DataBucket::DeleteCachedBuckets(DataBucketLoadType::Type t, uint32 id)
LogDataBuckets( LogDataBuckets(
"LoadType [{}] id [{}] cache size before [{}] after [{}]", "LoadType [{}] id [{}] cache size before [{}] after [{}]",
DataBucketLoadType::Name[t], DataBucketLoadType::Name[type],
id, id,
size_before, size_before,
g_data_bucket_cache.size() g_data_bucket_cache.size()
); );
} }
int64_t DataBucket::GetCurrentTimeUNIX() bool DataBucket::ExistsInCache(const DataBucketsRepository::DataBuckets &entry)
{ {
return std::chrono::duration_cast<std::chrono::nanoseconds>( for (const auto &e: g_data_bucket_cache) {
std::chrono::system_clock::now().time_since_epoch() if (e.id == entry.id) {
).count();
}
bool DataBucket::ExistsInCache(const DataBucketsRepository::DataBuckets &e)
{
for (const auto &ce: g_data_bucket_cache) {
if (ce.e.id == e.id) {
return true; return true;
} }
} }
@@ -507,134 +469,6 @@ bool DataBucket::ExistsInCache(const DataBucketsRepository::DataBuckets &e)
return false; return false;
} }
bool DataBucket::SendDataBucketCacheUpdate(const DataBucketCacheEntry &e)
{
if (!e.e.id) {
return false;
}
EQ::Net::DynamicPacket p;
p.PutSerialize(0, e);
auto pack_size = sizeof(ServerDataBucketCacheUpdate_Struct) + p.Length();
auto pack = new ServerPacket(ServerOP_DataBucketCacheUpdate, static_cast<uint32_t>(pack_size));
auto buf = reinterpret_cast<ServerDataBucketCacheUpdate_Struct *>(pack->pBuffer);
buf->cereal_size = static_cast<uint32_t>(p.Length());
memcpy(buf->cereal_data, p.Data(), p.Length());
worldserver.SendPacket(pack);
return true;
}
void DataBucket::HandleWorldMessage(ServerPacket *p)
{
DataBucketCacheEntry n;
auto s = (ServerDataBucketCacheUpdate_Struct *) p->pBuffer;
EQ::Util::MemoryStreamReader ss(s->cereal_data, s->cereal_size);
cereal::BinaryInputArchive archive(ss);
archive(n);
LogDataBucketsDetail(
"Received cache packet for id [{}] key [{}] value [{}] action [{}]",
n.e.id,
n.e.key_,
n.e.value,
static_cast<int>(n.update_action)
);
// delete
if (n.update_action == DataBucketCacheUpdateAction::Delete) {
DeleteFromMissesCache(n.e);
g_data_bucket_cache.erase(
std::remove_if(
g_data_bucket_cache.begin(),
g_data_bucket_cache.end(),
[&](DataBucketCacheEntry &ce) {
bool match = n.e.id > 0 && ce.e.id == n.e.id;
if (match) {
LogDataBuckets(
"[delete] cache key [{}] id [{}] cache_size before [{}] after [{}]",
ce.e.key_,
ce.e.id,
g_data_bucket_cache.size(),
g_data_bucket_cache.size() - 1
);
}
return match;
}
),
g_data_bucket_cache.end()
);
return;
}
// update
bool has_key = false;
for (auto &ce: g_data_bucket_cache) {
// update cache
if (ce.e.id == n.e.id) {
// reject old updates
int64 time_delta = ce.updated_time - n.updated_time;
if (ce.updated_time >= n.updated_time) {
LogDataBuckets(
"Attempted to update older cache key [{}] rejecting old time [{}] new time [{}] delta [{}] cache_size [{}]",
ce.e.key_,
ce.updated_time,
n.updated_time,
time_delta,
g_data_bucket_cache.size()
);
return;
}
DeleteFromMissesCache(n.e);
LogDataBuckets(
"[update] cache id [{}] key [{}] value [{}] old time [{}] new time [{}] delta [{}] cache_size [{}]",
ce.e.id,
ce.e.key_,
n.e.value,
ce.updated_time,
n.updated_time,
time_delta,
g_data_bucket_cache.size()
);
ce.e = n.e;
ce.updated_time = n.updated_time;
has_key = true;
break;
}
}
// create
if (!has_key) {
DeleteFromMissesCache(n.e);
size_t size_before = g_data_bucket_cache.size();
g_data_bucket_cache.emplace_back(
DataBucketCacheEntry{
.e = n.e,
.updated_time = GetCurrentTimeUNIX()
}
);
LogDataBuckets(
"[create] Adding new cache id [{}] key [{}] value [{}] cache size before [{}] after [{}]",
n.e.id,
n.e.key_,
n.e.value,
size_before,
g_data_bucket_cache.size()
);
}
}
void DataBucket::DeleteFromMissesCache(DataBucketsRepository::DataBuckets e) void DataBucket::DeleteFromMissesCache(DataBucketsRepository::DataBuckets e)
{ {
// delete from cache where there might have been a written bucket miss to the cache // delete from cache where there might have been a written bucket miss to the cache
@@ -645,11 +479,11 @@ void DataBucket::DeleteFromMissesCache(DataBucketsRepository::DataBuckets e)
std::remove_if( std::remove_if(
g_data_bucket_cache.begin(), g_data_bucket_cache.begin(),
g_data_bucket_cache.end(), g_data_bucket_cache.end(),
[&](DataBucketCacheEntry &ce) { [&](DataBucketsRepository::DataBuckets &ce) {
return ce.e.id == 0 && ce.e.key_ == e.key_ && return ce.id == 0 && ce.key_ == e.key_ &&
ce.e.character_id == e.character_id && ce.character_id == e.character_id &&
ce.e.npc_id == e.npc_id && ce.npc_id == e.npc_id &&
ce.e.bot_id == e.bot_id; ce.bot_id == e.bot_id;
} }
), ),
g_data_bucket_cache.end() g_data_bucket_cache.end()
@@ -667,3 +501,47 @@ void DataBucket::ClearCache()
g_data_bucket_cache.clear(); g_data_bucket_cache.clear();
LogInfo("Cleared data buckets cache"); LogInfo("Cleared data buckets cache");
} }
void DataBucket::DeleteFromCache(uint64 id, DataBucketLoadType::Type type)
{
size_t size_before = g_data_bucket_cache.size();
g_data_bucket_cache.erase(
std::remove_if(
g_data_bucket_cache.begin(),
g_data_bucket_cache.end(),
[&](DataBucketsRepository::DataBuckets &e) {
switch (type) {
case DataBucketLoadType::Bot:
return e.bot_id == id;
case DataBucketLoadType::Client:
return e.character_id == id;
default:
return false;
}
}
),
g_data_bucket_cache.end()
);
LogDataBuckets(
"Deleted [{}] id [{}] from cache size before [{}] after [{}]",
DataBucketLoadType::Name[type],
id,
size_before,
g_data_bucket_cache.size()
);
}
// CanCache returns whether a bucket can be cached or not
// characters are only in one zone at a time so we can cache locally to the zone
// bots (not implemented) are only in one zone at a time so we can cache locally to the zone
// npcs (ids) can be in multiple zones so we can't cache locally to the zone
bool DataBucket::CanCache(const DataBucketKey &key)
{
if (key.character_id > 0 || key.bot_id > 0) {
return true;
}
return false;
}
+5 -34
View File
@@ -1,7 +1,3 @@
//
// Created by Akkadius on 7/7/18.
//
#ifndef EQEMU_DATABUCKET_H #ifndef EQEMU_DATABUCKET_H
#define EQEMU_DATABUCKET_H #define EQEMU_DATABUCKET_H
@@ -12,27 +8,6 @@
#include "../common/json/json_archive_single_line.h" #include "../common/json/json_archive_single_line.h"
#include "../common/servertalk.h" #include "../common/servertalk.h"
enum DataBucketCacheUpdateAction : uint8 {
Upsert,
Delete
};
struct DataBucketCacheEntry {
DataBucketsRepository::DataBuckets e;
int64_t updated_time{};
DataBucketCacheUpdateAction update_action{};
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(e),
CEREAL_NVP(updated_time),
CEREAL_NVP(update_action)
);
}
};
struct DataBucketKey { struct DataBucketKey {
std::string key; std::string key;
std::string value; std::string value;
@@ -46,14 +21,12 @@ namespace DataBucketLoadType {
enum Type : uint8 { enum Type : uint8 {
Bot, Bot,
Client, Client,
NPC,
MaxType MaxType
}; };
static const std::string Name[Type::MaxType] = { static const std::string Name[Type::MaxType] = {
"Bot", "Bot",
"Client", "Client",
"NPC",
}; };
} }
@@ -68,8 +41,6 @@ public:
static bool GetDataBuckets(Mob *mob); static bool GetDataBuckets(Mob *mob);
static int64_t GetCurrentTimeUNIX();
// scoped bucket methods // scoped bucket methods
static void SetData(const DataBucketKey &k); static void SetData(const DataBucketKey &k);
static bool DeleteData(const DataBucketKey &k); static bool DeleteData(const DataBucketKey &k);
@@ -80,15 +51,15 @@ public:
// bucket repository versus key matching // bucket repository versus key matching
static bool CheckBucketMatch(const DataBucketsRepository::DataBuckets &dbe, const DataBucketKey &k); static bool CheckBucketMatch(const DataBucketsRepository::DataBuckets &dbe, const DataBucketKey &k);
static bool ExistsInCache(const DataBucketsRepository::DataBuckets &e); static bool ExistsInCache(const DataBucketsRepository::DataBuckets &entry);
static void BulkLoadEntities(DataBucketLoadType::Type t, std::vector<uint32> ids); static void BulkLoadEntitiesToCache(DataBucketLoadType::Type t, std::vector<uint32> ids);
static void DeleteCachedBuckets(DataBucketLoadType::Type t, uint32 id); static void DeleteCachedBuckets(DataBucketLoadType::Type type, uint32 id);
static bool SendDataBucketCacheUpdate(const DataBucketCacheEntry &e);
static void HandleWorldMessage(ServerPacket *p);
static void DeleteFromMissesCache(DataBucketsRepository::DataBuckets e); static void DeleteFromMissesCache(DataBucketsRepository::DataBuckets e);
static void ClearCache(); static void ClearCache();
static void DeleteFromCache(uint64 id, DataBucketLoadType::Type type);
static bool CanCache(const DataBucketKey &key);
}; };
#endif //EQEMU_DATABUCKET_H #endif //EQEMU_DATABUCKET_H
+1 -1
View File
@@ -1446,7 +1446,7 @@ int Perl__collectitems(uint32_t item_id, bool remove_item)
return quest_manager.collectitems(item_id, remove_item); return quest_manager.collectitems(item_id, remove_item);
} }
int Perl__countitem(uint32_t item_id) uint32 Perl__countitem(uint32_t item_id)
{ {
return quest_manager.countitem(item_id); return quest_manager.countitem(item_id);
} }
+2 -14
View File
@@ -1817,25 +1817,13 @@ void EntityList::DuelMessage(Mob *winner, Mob *loser, bool flee)
if (parse->PlayerHasQuestSub(EVENT_DUEL_WIN)) { if (parse->PlayerHasQuestSub(EVENT_DUEL_WIN)) {
std::vector<std::any> args = { winner, loser }; std::vector<std::any> args = { winner, loser };
parse->EventPlayer( parse->EventPlayer(EVENT_DUEL_WIN, winner->CastToClient(), loser->GetName(), loser->CastToClient()->CharacterID(), &args);
EVENT_DUEL_WIN,
winner->CastToClient(),
loser->GetName(),
loser->CastToClient()->CharacterID(),
&args
);
} }
if (parse->PlayerHasQuestSub(EVENT_DUEL_LOSE)) { if (parse->PlayerHasQuestSub(EVENT_DUEL_LOSE)) {
std::vector<std::any> args = { winner, loser }; std::vector<std::any> args = { winner, loser };
parse->EventPlayer( parse->EventPlayer(EVENT_DUEL_LOSE, loser->CastToClient(), winner->GetName(), winner->CastToClient()->CharacterID(), &args);
EVENT_DUEL_LOSE,
loser->CastToClient(),
winner->GetName(),
winner->CastToClient()->CharacterID(),
&args
);
} }
} }
+12 -22
View File
@@ -2,31 +2,21 @@
void command_emptyinventory(Client *c, const Seperator *sep) void command_emptyinventory(Client *c, const Seperator *sep)
{ {
auto target = c; Client* t = c;
if (c->GetGM() && c->GetTarget() && c->GetTarget()->IsClient()) { if (c->GetGM() && c->GetTarget() && c->GetTarget()->IsClient()) {
target = c->GetTarget()->CastToClient(); t = c->GetTarget()->CastToClient();
} }
EQ::ItemInstance *item = nullptr; EQ::ItemInstance *item = nullptr;
static const int16 slots[][2] = { uint32 removed_count = 0;
{ EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END },
{ EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END }, for (const int16& slot_id : t->GetInventorySlots()) {
{ EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END}, item = t->GetInv().GetItem(slot_id);
{ EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END },
{ EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END },
{ EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END },
{ EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END },
};
int removed_count = 0;
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 = target->GetInv().GetItem(slot_id);
if (item) { if (item) {
int stack_size = std::max(static_cast<int>(item->GetCharges()), 1); uint32 stack_size = std::max(static_cast<uint32>(item->GetCharges()), static_cast<uint32>(1));
removed_count += stack_size; removed_count += stack_size;
target->DeleteItemInInventory(slot_id, 0, true); t->DeleteItemInInventory(slot_id, 0, true);
}
} }
} }
@@ -35,8 +25,8 @@ void command_emptyinventory(Client *c, const Seperator *sep)
Chat::White, Chat::White,
fmt::format( fmt::format(
"{} {} no items to delete.", "{} {} no items to delete.",
c->GetTargetDescription(target, TargetDescriptionType::UCYou), c->GetTargetDescription(t, TargetDescriptionType::UCYou),
c == target ? "have" : "has" c == t ? "have" : "has"
).c_str() ).c_str()
); );
return; return;
@@ -46,7 +36,7 @@ void command_emptyinventory(Client *c, const Seperator *sep)
Chat::White, Chat::White,
fmt::format( fmt::format(
"Inventory cleared for {}, {} item{} deleted.", "Inventory cleared for {}, {} item{} deleted.",
c->GetTargetDescription(target), c->GetTargetDescription(t),
removed_count, removed_count,
removed_count != 1 ? "s" : "" removed_count != 1 ? "s" : ""
).c_str() ).c_str()
+13
View File
@@ -1,6 +1,7 @@
#include "../client.h" #include "../client.h"
#include "find/aa.cpp" #include "find/aa.cpp"
#include "find/body_type.cpp" #include "find/body_type.cpp"
#include "find/bot.cpp"
#include "find/bug_category.cpp" #include "find/bug_category.cpp"
#include "find/character.cpp" #include "find/character.cpp"
#include "find/class.cpp" #include "find/class.cpp"
@@ -11,6 +12,7 @@
#include "find/faction.cpp" #include "find/faction.cpp"
#include "find/item.cpp" #include "find/item.cpp"
#include "find/language.cpp" #include "find/language.cpp"
#include "find/ldon_theme.cpp"
#include "find/npctype.cpp" #include "find/npctype.cpp"
#include "find/object_type.cpp" #include "find/object_type.cpp"
#include "find/race.cpp" #include "find/race.cpp"
@@ -47,6 +49,7 @@ void command_find(Client *c, const Seperator *sep)
Cmd{.cmd = "faction", .u = "faction [Search Criteria]", .fn = FindFaction, .a = {"#findfaction"}}, Cmd{.cmd = "faction", .u = "faction [Search Criteria]", .fn = FindFaction, .a = {"#findfaction"}},
Cmd{.cmd = "item", .u = "item [Search Criteria]", .fn = FindItem, .a = {"#fi", "#finditem"}}, Cmd{.cmd = "item", .u = "item [Search Criteria]", .fn = FindItem, .a = {"#fi", "#finditem"}},
Cmd{.cmd = "language", .u = "language [Search Criteria]", .fn = FindLanguage, .a = {"#findlanguage"}}, Cmd{.cmd = "language", .u = "language [Search Criteria]", .fn = FindLanguage, .a = {"#findlanguage"}},
Cmd{.cmd = "ldon_theme", .u = "ldon_theme [Search Criteria]", .fn = FindLDoNTheme, .a = {"#findldontheme"}},
Cmd{ Cmd{
.cmd = "npctype", .u = "npctype [Search Criteria]", .fn = FindNPCType, .a = { .cmd = "npctype", .u = "npctype [Search Criteria]", .fn = FindNPCType, .a = {
"#fn", "#fn",
@@ -65,6 +68,16 @@ void command_find(Client *c, const Seperator *sep)
Cmd{.cmd = "zone", .u = "zone [Search Criteria]", .fn = FindZone, .a = {"#fz", "#findzone"}}, Cmd{.cmd = "zone", .u = "zone [Search Criteria]", .fn = FindZone, .a = {"#fz", "#findzone"}},
}; };
if (RuleB(Bots, Enabled)) {
commands.emplace_back(
Cmd{.cmd = "bot", .u = "bot [Search Criteria]", .fn = FindBot, .a = {"#findbot"}}
);
std::sort(commands.begin(), commands.end(), [](const Cmd& a, const Cmd& b) {
return a.cmd < b.cmd;
});
}
// Check for arguments // Check for arguments
const auto arguments = sep->argnum; const auto arguments = sep->argnum;
if (!arguments) { if (!arguments) {
+95
View File
@@ -0,0 +1,95 @@
#include "../../client.h"
#include "../../common/repositories/bot_data_repository.h"
void FindBot(Client *c, const Seperator *sep)
{
if (sep->IsNumber(2)) {
const auto bot_id = Strings::ToUnsignedInt(sep->arg[2]);
const auto& e = BotDataRepository::FindOne(content_db, bot_id);
if (!e.bot_id) {
c->Message(
Chat::White,
fmt::format(
"Bot ID {} does not exist or is invalid.",
bot_id
).c_str()
);
return;
}
c->Message(
Chat::White,
fmt::format(
"Bot ID {} | {}",
bot_id,
e.name
).c_str()
);
return;
}
const auto search_criteria = Strings::ToLower(sep->argplus[2]);
const auto& l = BotDataRepository::GetWhere(
content_db,
fmt::format(
"LOWER(`name`) LIKE '%%{}%%' AND `name` NOT LIKE '%-deleted-%' ORDER BY `bot_id` ASC LIMIT 50",
search_criteria
)
);
if (l.empty()) {
c->Message(
Chat::White,
fmt::format(
"No bots found matching '{}'.",
sep->argplus[2]
).c_str()
);
}
auto found_count = 0;
for (const auto& e : l) {
c->Message(
Chat::White,
fmt::format(
"Bot ID {} | {}",
Strings::Commify(e.bot_id),
e.name
).c_str()
);
found_count++;
if (found_count == 50) {
break;
}
}
if (found_count == 50) {
c->Message(
Chat::White,
fmt::format(
"50 Bots found matching '{}', max reached.",
sep->argplus[2]
).c_str()
);
return;
}
c->Message(
Chat::White,
fmt::format(
"{} Bot{} found matching '{}'.",
found_count,
found_count != 1 ? "s" : "",
sep->argplus[2]
).c_str()
);
}
+1 -1
View File
@@ -36,7 +36,7 @@ void FindCharacter(Client *c, const Seperator *sep)
const auto& l = CharacterDataRepository::GetWhere( const auto& l = CharacterDataRepository::GetWhere(
content_db, content_db,
fmt::format( fmt::format(
"LOWER(`name`) LIKE '%%{}%%' ORDER BY `id` ASC LIMIT 50", "LOWER(`name`) LIKE '%%{}%%' AND `name` NOT LIKE '%-deleted-%' ORDER BY `id` ASC LIMIT 50",
search_criteria search_criteria
) )
); );
+1 -1
View File
@@ -57,7 +57,7 @@ void FindClass(Client *c, const Seperator *sep)
( (
IsPlayerClass(class_id) ? IsPlayerClass(class_id) ?
fmt::format( fmt::format(
" | ({})", " ({})",
Strings::Commify(GetPlayerClassBit(class_id)) Strings::Commify(GetPlayerClassBit(class_id))
) : ) :
"" ""
+65
View File
@@ -0,0 +1,65 @@
#include "../../client.h"
void FindLDoNTheme(Client *c, const Seperator *sep)
{
if (sep->IsNumber(2)) {
const uint32 theme_id = Strings::ToUnsignedInt(sep->arg[2]);
if (LDoNTheme::IsValid(theme_id)) {
c->Message(
Chat::White,
fmt::format(
"Theme {} | {} ({})",
theme_id,
LDoNTheme::GetName(theme_id),
LDoNTheme::GetBitmask(theme_id)
).c_str()
);
return;
}
c->Message(
Chat::White,
fmt::format(
"Theme ID {} was not found.",
theme_id
).c_str()
);
return;
}
const std::string& search_criteria = Strings::ToLower(sep->argplus[2]);
uint32 found_count = 0;
for (const auto& l : ldon_theme_names) {
const std::string& ldon_theme_name_lower = Strings::ToLower(l.second.first);
if (!Strings::Contains(ldon_theme_name_lower, search_criteria)) {
continue;
}
c->Message(
Chat::White,
fmt::format(
"Theme {} | {} ({})",
l.first,
l.second.first,
l.second.second
).c_str()
);
found_count++;
}
c->Message(
Chat::White,
fmt::format(
"{} Theme{} found matching '{}'.",
found_count,
found_count != 1 ? "s" : "",
sep->argplus[2]
).c_str()
);
}
+14 -12
View File
@@ -3,20 +3,21 @@
void SetAdventurePoints(Client *c, const Seperator *sep) void SetAdventurePoints(Client *c, const Seperator *sep)
{ {
const auto arguments = sep->argnum; const uint16 arguments = sep->argnum;
if (arguments < 3 || !sep->IsNumber(2) || !sep->IsNumber(3)) { if (arguments < 3 || !sep->IsNumber(2) || !sep->IsNumber(3)) {
c->Message(Chat::White, "Usage: #set adventure_points [Theme] [Points]"); c->Message(Chat::White, "Usage: #set adventure_points [Theme] [Points]");
c->Message(Chat::White, "Valid themes are as follows:"); c->Message(Chat::White, "Valid themes are as follows:");
for (const auto& e : EQ::constants::GetLDoNThemeMap()) { for (const auto& e : ldon_theme_names) {
if (e.first != LDoNThemes::Unused) { if (e.first != LDoNTheme::Unused) {
c->Message( c->Message(
Chat::White, Chat::White,
fmt::format( fmt::format(
"Theme {} | {}", "Theme {} | {} ({})",
e.first, e.first,
e.second e.second.first,
e.second.second
).c_str() ).c_str()
); );
} }
@@ -25,7 +26,7 @@ void SetAdventurePoints(Client *c, const Seperator *sep)
return; return;
} }
auto t = c; Client* t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) { if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient(); t = c->GetTarget()->CastToClient();
} }
@@ -33,17 +34,18 @@ void SetAdventurePoints(Client *c, const Seperator *sep)
const uint32 theme_id = Strings::ToUnsignedInt(sep->arg[2]); const uint32 theme_id = Strings::ToUnsignedInt(sep->arg[2]);
const uint32 points = Strings::ToUnsignedInt(sep->arg[3]); const uint32 points = Strings::ToUnsignedInt(sep->arg[3]);
if (!EQ::ValueWithin(theme_id, LDoNThemes::GUK, LDoNThemes::TAK)) { if (!LDoNTheme::IsValid(theme_id)) {
c->Message(Chat::White, "Valid themes are as follows:"); c->Message(Chat::White, "Valid themes are as follows:");
for (const auto& e : EQ::constants::GetLDoNThemeMap()) { for (const auto& e : ldon_theme_names) {
if (e.first != LDoNThemes::Unused) { if (e.first != LDoNTheme::Unused) {
c->Message( c->Message(
Chat::White, Chat::White,
fmt::format( fmt::format(
"Theme {} | {}", "Theme {} | {} ({})",
e.first, e.first,
e.second e.second.first,
e.second.second
).c_str() ).c_str()
); );
} }
@@ -56,7 +58,7 @@ void SetAdventurePoints(Client *c, const Seperator *sep)
Chat::White, Chat::White,
fmt::format( fmt::format(
"Set {} Points to {} for {}.", "Set {} Points to {} for {}.",
EQ::constants::GetLDoNThemeName(theme_id), LDoNTheme::GetName(theme_id),
Strings::Commify(points), Strings::Commify(points),
c->GetTargetDescription(t) c->GetTargetDescription(t)
).c_str() ).c_str()
+2 -2
View File
@@ -89,11 +89,11 @@ void ShowCurrencies(Client *c, const Seperator *sep)
} }
} }
for (const auto& l : EQ::constants::GetLDoNThemeMap()) { for (const auto& l : ldon_theme_names) {
const uint32 ldon_currency_value = t->GetLDoNPointsTheme(l.first); const uint32 ldon_currency_value = t->GetLDoNPointsTheme(l.first);
if (ldon_currency_value) { if (ldon_currency_value) {
currency_table += DialogueWindow::TableRow( currency_table += DialogueWindow::TableRow(
DialogueWindow::TableCell(l.second) + DialogueWindow::TableCell(l.second.first) +
DialogueWindow::TableCell(Strings::Commify(ldon_currency_value)) DialogueWindow::TableCell(Strings::Commify(ldon_currency_value))
); );
+1 -1
View File
@@ -2419,7 +2419,7 @@ bool Group::AmIMainAssist(const char *mob_name)
if (!mob_name) if (!mob_name)
return false; return false;
return !((bool)MainTankName.compare(mob_name)); return !((bool)MainAssistName.compare(mob_name));
} }
bool Group::AmIPuller(const char *mob_name) bool Group::AmIPuller(const char *mob_name)
-2
View File
@@ -63,7 +63,6 @@ public:
void AddMember(const std::string& new_member_name); void AddMember(const std::string& new_member_name);
void SendUpdate(uint32 type,Mob* member); void SendUpdate(uint32 type,Mob* member);
void SendLeadershipAAUpdate(); void SendLeadershipAAUpdate();
void SendWorldGroup(uint32 zone_id,Mob* zoningmember);
bool DelMemberOOZ(const char *Name); bool DelMemberOOZ(const char *Name);
bool DelMember(Mob* oldmember,bool ignoresender = false); bool DelMember(Mob* oldmember,bool ignoresender = false);
void DisbandGroup(bool joinraid = false); void DisbandGroup(bool joinraid = false);
@@ -73,7 +72,6 @@ public:
bool IsGroupMember(Mob* c); bool IsGroupMember(Mob* c);
bool IsGroupMember(const char* name); bool IsGroupMember(const char* name);
bool Process(); bool Process();
bool IsGroup() { return true; }
void SendGroupJoinOOZ(Mob* NewMember); void SendGroupJoinOOZ(Mob* NewMember);
void CastGroupSpell(Mob* caster,uint16 spellid); void CastGroupSpell(Mob* caster,uint16 spellid);
void SplitExp(ExpSource exp_source, const uint64 exp, Mob* other); void SplitExp(ExpSource exp_source, const uint64 exp, Mob* other);
+1 -1
View File
@@ -83,9 +83,9 @@ public:
void SendRankName(uint32 guild_id, uint32 rank, std::string rank_name); void SendRankName(uint32 guild_id, uint32 rank, std::string rank_name);
void SendAllRankNames(uint32 guild_id, uint32 char_id); void SendAllRankNames(uint32 guild_id, uint32 char_id);
BaseGuildManager::GuildInfo* GetGuildByGuildID(uint32 guild_id); BaseGuildManager::GuildInfo* GetGuildByGuildID(uint32 guild_id);
virtual void SendGuildRefresh(uint32 guild_id, bool name, bool motd, bool rank, bool relation);
protected: protected:
virtual void SendGuildRefresh(uint32 guild_id, bool name, bool motd, bool rank, bool relation);
virtual void SendCharRefresh(uint32 old_guild_id, uint32 guild_id, uint32 charid); virtual void SendCharRefresh(uint32 old_guild_id, uint32 guild_id, uint32 charid);
virtual void SendRankUpdate(uint32 CharID); virtual void SendRankUpdate(uint32 CharID);
virtual void SendGuildDelete(uint32 guild_id); virtual void SendGuildDelete(uint32 guild_id);
+2 -2
View File
@@ -859,9 +859,9 @@ bool NPC::HasItem(uint32 item_id)
return false; return false;
} }
uint16 NPC::CountItem(uint32 item_id) uint32 NPC::CountItem(uint32 item_id)
{ {
uint16 item_count = 0; uint32 item_count = 0;
if (!database.GetItem(item_id)) { if (!database.GetItem(item_id)) {
return item_count; return item_count;
} }
+4 -3
View File
@@ -274,7 +274,7 @@ void Lua_Bot::SetSpellDurationRaid(int spell_id, int duration, int level, bool a
self->SetSpellDuration(spell_id, duration, level, ApplySpellType::Raid, allow_pets, is_raid_group_only); self->SetSpellDuration(spell_id, duration, level, ApplySpellType::Raid, allow_pets, is_raid_group_only);
} }
int Lua_Bot::CountAugmentEquippedByID(uint32 item_id) { uint32 Lua_Bot::CountAugmentEquippedByID(uint32 item_id) {
Lua_Safe_Call_Int(); Lua_Safe_Call_Int();
return self->GetInv().CountAugmentEquippedByID(item_id); return self->GetInv().CountAugmentEquippedByID(item_id);
} }
@@ -284,7 +284,7 @@ bool Lua_Bot::HasAugmentEquippedByID(uint32 item_id) {
return self->GetInv().HasAugmentEquippedByID(item_id); return self->GetInv().HasAugmentEquippedByID(item_id);
} }
int Lua_Bot::CountItemEquippedByID(uint32 item_id) { uint32 Lua_Bot::CountItemEquippedByID(uint32 item_id) {
Lua_Safe_Call_Int(); Lua_Safe_Call_Int();
return self->GetInv().CountItemEquippedByID(item_id); return self->GetInv().CountItemEquippedByID(item_id);
} }
@@ -701,8 +701,9 @@ luabind::scope lua_register_bot() {
.def("ClearItemReuseTimer", (void(Lua_Bot::*)(uint32))&Lua_Bot::ClearItemReuseTimer) .def("ClearItemReuseTimer", (void(Lua_Bot::*)(uint32))&Lua_Bot::ClearItemReuseTimer)
.def("ClearSpellRecastTimer", (void(Lua_Bot::*)())&Lua_Bot::ClearSpellRecastTimer) .def("ClearSpellRecastTimer", (void(Lua_Bot::*)())&Lua_Bot::ClearSpellRecastTimer)
.def("ClearSpellRecastTimer", (void(Lua_Bot::*)(uint16))&Lua_Bot::ClearSpellRecastTimer) .def("ClearSpellRecastTimer", (void(Lua_Bot::*)(uint16))&Lua_Bot::ClearSpellRecastTimer)
.def("CountAugmentEquippedByID", (uint32(Lua_Bot::*)(uint32))&Lua_Bot::CountAugmentEquippedByID)
.def("CountBotItem", (uint32(Lua_Bot::*)(uint32))&Lua_Bot::CountBotItem) .def("CountBotItem", (uint32(Lua_Bot::*)(uint32))&Lua_Bot::CountBotItem)
.def("CountItemEquippedByID", (int(Lua_Bot::*)(uint32))&Lua_Bot::CountItemEquippedByID) .def("CountItemEquippedByID", (uint32(Lua_Bot::*)(uint32))&Lua_Bot::CountItemEquippedByID)
.def("DeleteBot", (void(Lua_Bot::*)(void))&Lua_Bot::DeleteBot) .def("DeleteBot", (void(Lua_Bot::*)(void))&Lua_Bot::DeleteBot)
.def("DeleteBucket", (void(Lua_Bot::*)(std::string))&Lua_Bot::DeleteBucket) .def("DeleteBucket", (void(Lua_Bot::*)(std::string))&Lua_Bot::DeleteBucket)
.def("Escape", (void(Lua_Bot::*)(void))&Lua_Bot::Escape) .def("Escape", (void(Lua_Bot::*)(void))&Lua_Bot::Escape)
+2 -2
View File
@@ -127,8 +127,8 @@ public:
void SetSpellRecastTimer(uint16 spell_id); void SetSpellRecastTimer(uint16 spell_id);
void SetSpellRecastTimer(uint16 spell_id, uint32 reuse_timer); void SetSpellRecastTimer(uint16 spell_id, uint32 reuse_timer);
int CountAugmentEquippedByID(uint32 item_id); uint32 CountAugmentEquippedByID(uint32 item_id);
int CountItemEquippedByID(uint32 item_id); uint32 CountItemEquippedByID(uint32 item_id);
bool HasAugmentEquippedByID(uint32 item_id); bool HasAugmentEquippedByID(uint32 item_id);
bool HasItemEquippedByID(uint32 item_id); bool HasItemEquippedByID(uint32 item_id);
int GetHealAmount(); int GetHealAmount();
+22 -6
View File
@@ -2287,7 +2287,7 @@ void Lua_Client::SendToInstance(std::string instance_type, std::string zone_shor
self->SendToInstance(instance_type, zone_short_name, instance_version, x, y, z, heading, instance_identifier, duration); self->SendToInstance(instance_type, zone_short_name, instance_version, x, y, z, heading, instance_identifier, duration);
} }
int Lua_Client::CountItem(uint32 item_id) { uint32 Lua_Client::CountItem(uint32 item_id) {
Lua_Safe_Call_Int(); Lua_Safe_Call_Int();
return self->CountItem(item_id); return self->CountItem(item_id);
} }
@@ -2480,7 +2480,7 @@ void Lua_Client::AddItem(luabind::object item_table) {
); );
} }
int Lua_Client::CountAugmentEquippedByID(uint32 item_id) { uint32 Lua_Client::CountAugmentEquippedByID(uint32 item_id) {
Lua_Safe_Call_Int(); Lua_Safe_Call_Int();
return self->GetInv().CountAugmentEquippedByID(item_id); return self->GetInv().CountAugmentEquippedByID(item_id);
} }
@@ -2490,7 +2490,7 @@ bool Lua_Client::HasAugmentEquippedByID(uint32 item_id) {
return self->GetInv().HasAugmentEquippedByID(item_id); return self->GetInv().HasAugmentEquippedByID(item_id);
} }
int Lua_Client::CountItemEquippedByID(uint32 item_id) { uint32 Lua_Client::CountItemEquippedByID(uint32 item_id) {
Lua_Safe_Call_Int(); Lua_Safe_Call_Int();
return self->GetInv().CountItemEquippedByID(item_id); return self->GetInv().CountItemEquippedByID(item_id);
} }
@@ -3436,6 +3436,21 @@ void Lua_Client::AreaTaunt(float range, int bonus_hate)
entity_list.AETaunt(self, range, bonus_hate); entity_list.AETaunt(self, range, bonus_hate);
} }
luabind::object Lua_Client::GetInventorySlots(lua_State* L) {
auto lua_table = luabind::newtable(L);
if (d_) {
auto self = reinterpret_cast<NativeType*>(d_);
int index = 1;
for (const int16& slot_id : self->GetInventorySlots()) {
lua_table[index] = slot_id;
index++;
}
}
return lua_table;
}
luabind::scope lua_register_client() { luabind::scope lua_register_client() {
return luabind::class_<Lua_Client, Lua_Mob>("Client") return luabind::class_<Lua_Client, Lua_Mob>("Client")
.def(luabind::constructor<>()) .def(luabind::constructor<>())
@@ -3514,9 +3529,9 @@ luabind::scope lua_register_client() {
.def("ClearXTargets", (void(Lua_Client::*)(void))&Lua_Client::ClearXTargets) .def("ClearXTargets", (void(Lua_Client::*)(void))&Lua_Client::ClearXTargets)
.def("ClearZoneFlag", (void(Lua_Client::*)(uint32))&Lua_Client::ClearZoneFlag) .def("ClearZoneFlag", (void(Lua_Client::*)(uint32))&Lua_Client::ClearZoneFlag)
.def("Connected", (bool(Lua_Client::*)(void))&Lua_Client::Connected) .def("Connected", (bool(Lua_Client::*)(void))&Lua_Client::Connected)
.def("CountAugmentEquippedByID", (int(Lua_Client::*)(uint32))&Lua_Client::CountAugmentEquippedByID) .def("CountAugmentEquippedByID", (uint32(Lua_Client::*)(uint32))&Lua_Client::CountAugmentEquippedByID)
.def("CountItem", (int(Lua_Client::*)(uint32))&Lua_Client::CountItem) .def("CountItem", (uint32(Lua_Client::*)(uint32))&Lua_Client::CountItem)
.def("CountItemEquippedByID", (int(Lua_Client::*)(uint32))&Lua_Client::CountItemEquippedByID) .def("CountItemEquippedByID", (uint32(Lua_Client::*)(uint32))&Lua_Client::CountItemEquippedByID)
.def("CreateExpedition", (Lua_Expedition(Lua_Client::*)(luabind::object))&Lua_Client::CreateExpedition) .def("CreateExpedition", (Lua_Expedition(Lua_Client::*)(luabind::object))&Lua_Client::CreateExpedition)
.def("CreateExpedition", (Lua_Expedition(Lua_Client::*)(std::string, uint32, uint32, std::string, uint32, uint32))&Lua_Client::CreateExpedition) .def("CreateExpedition", (Lua_Expedition(Lua_Client::*)(std::string, uint32, uint32, std::string, uint32, uint32))&Lua_Client::CreateExpedition)
.def("CreateExpedition", (Lua_Expedition(Lua_Client::*)(std::string, uint32, uint32, std::string, uint32, uint32, bool))&Lua_Client::CreateExpedition) .def("CreateExpedition", (Lua_Expedition(Lua_Client::*)(std::string, uint32, uint32, std::string, uint32, uint32, bool))&Lua_Client::CreateExpedition)
@@ -3650,6 +3665,7 @@ luabind::scope lua_register_client() {
.def("GetInstrumentMod", (int(Lua_Client::*)(int))&Lua_Client::GetInstrumentMod) .def("GetInstrumentMod", (int(Lua_Client::*)(int))&Lua_Client::GetInstrumentMod)
.def("GetIntoxication", (int(Lua_Client::*)(void))&Lua_Client::GetIntoxication) .def("GetIntoxication", (int(Lua_Client::*)(void))&Lua_Client::GetIntoxication)
.def("GetInventory", (Lua_Inventory(Lua_Client::*)(void))&Lua_Client::GetInventory) .def("GetInventory", (Lua_Inventory(Lua_Client::*)(void))&Lua_Client::GetInventory)
.def("GetInventorySlots", (luabind::object(Lua_Client::*)(lua_State* L))&Lua_Client::GetInventorySlots)
.def("GetInvulnerableEnvironmentDamage", (bool(Lua_Client::*)(void))&Lua_Client::GetInvulnerableEnvironmentDamage) .def("GetInvulnerableEnvironmentDamage", (bool(Lua_Client::*)(void))&Lua_Client::GetInvulnerableEnvironmentDamage)
.def("GetItemIDAt", (int(Lua_Client::*)(int))&Lua_Client::GetItemIDAt) .def("GetItemIDAt", (int(Lua_Client::*)(int))&Lua_Client::GetItemIDAt)
.def("GetItemCooldown", (uint32(Lua_Client::*)(uint32))&Lua_Client::GetItemCooldown) .def("GetItemCooldown", (uint32(Lua_Client::*)(uint32))&Lua_Client::GetItemCooldown)
+4 -3
View File
@@ -441,14 +441,14 @@ public:
void Popup(const char* title, const char* text, uint32 popup_id, uint32 negative_id, uint32 button_type, uint32 duration); void Popup(const char* title, const char* text, uint32 popup_id, uint32 negative_id, uint32 button_type, uint32 duration);
void Popup(const char* title, const char* text, uint32 popup_id, uint32 negative_id, uint32 button_type, uint32 duration, const char* button_name_one, const char* button_name_two); void Popup(const char* title, const char* text, uint32 popup_id, uint32 negative_id, uint32 button_type, uint32 duration, const char* button_name_one, const char* button_name_two);
void Popup(const char* title, const char* text, uint32 popup_id, uint32 negative_id, uint32 button_type, uint32 duration, const char* button_name_one, const char* button_name_two, uint32 sound_controls); void Popup(const char* title, const char* text, uint32 popup_id, uint32 negative_id, uint32 button_type, uint32 duration, const char* button_name_one, const char* button_name_two, uint32 sound_controls);
int CountItem(uint32 item_id); uint32 CountItem(uint32 item_id);
void RemoveItem(uint32 item_id); void RemoveItem(uint32 item_id);
void RemoveItem(uint32 item_id, uint32 quantity); void RemoveItem(uint32 item_id, uint32 quantity);
void SetGMStatus(int new_status); void SetGMStatus(int new_status);
int16 GetGMStatus(); int16 GetGMStatus();
void AddItem(luabind::object item_table); void AddItem(luabind::object item_table);
int CountAugmentEquippedByID(uint32 item_id); uint32 CountAugmentEquippedByID(uint32 item_id);
int CountItemEquippedByID(uint32 item_id); uint32 CountItemEquippedByID(uint32 item_id);
bool HasAugmentEquippedByID(uint32 item_id); bool HasAugmentEquippedByID(uint32 item_id);
bool HasItemEquippedByID(uint32 item_id); bool HasItemEquippedByID(uint32 item_id);
int GetHealAmount(); int GetHealAmount();
@@ -509,6 +509,7 @@ public:
void AreaTaunt(); void AreaTaunt();
void AreaTaunt(float range); void AreaTaunt(float range);
void AreaTaunt(float range, int bonus_hate); void AreaTaunt(float range, int bonus_hate);
luabind::object GetInventorySlots(lua_State* L);
void ApplySpell(int spell_id); void ApplySpell(int spell_id);
void ApplySpell(int spell_id, int duration); void ApplySpell(int spell_id, int duration);
+2 -2
View File
@@ -177,7 +177,7 @@ bool Lua_Corpse::HasItem(uint32 item_id) {
return self->HasItem(item_id); return self->HasItem(item_id);
} }
uint16 Lua_Corpse::CountItem(uint32 item_id) { uint32 Lua_Corpse::CountItem(uint32 item_id) {
Lua_Safe_Call_Int(); Lua_Safe_Call_Int();
return self->CountItem(item_id); return self->CountItem(item_id);
} }
@@ -226,7 +226,7 @@ luabind::scope lua_register_corpse() {
.def("AllowMobLoot", (void(Lua_Corpse::*)(Lua_Mob, uint8))&Lua_Corpse::AllowMobLoot) .def("AllowMobLoot", (void(Lua_Corpse::*)(Lua_Mob, uint8))&Lua_Corpse::AllowMobLoot)
.def("Bury", (void(Lua_Corpse::*)(void))&Lua_Corpse::Bury) .def("Bury", (void(Lua_Corpse::*)(void))&Lua_Corpse::Bury)
.def("CanMobLoot", (bool(Lua_Corpse::*)(int))&Lua_Corpse::CanMobLoot) .def("CanMobLoot", (bool(Lua_Corpse::*)(int))&Lua_Corpse::CanMobLoot)
.def("CountItem", (uint16(Lua_Corpse::*)(uint32))&Lua_Corpse::CountItem) .def("CountItem", (uint32(Lua_Corpse::*)(uint32))&Lua_Corpse::CountItem)
.def("CountItems", (uint32(Lua_Corpse::*)(void))&Lua_Corpse::CountItems) .def("CountItems", (uint32(Lua_Corpse::*)(void))&Lua_Corpse::CountItems)
.def("Delete", (void(Lua_Corpse::*)(void))&Lua_Corpse::Delete) .def("Delete", (void(Lua_Corpse::*)(void))&Lua_Corpse::Delete)
.def("Depop", (void(Lua_Corpse::*)(void))&Lua_Corpse::Depop) .def("Depop", (void(Lua_Corpse::*)(void))&Lua_Corpse::Depop)
+1 -1
View File
@@ -62,7 +62,7 @@ public:
uint32 GetPlatinum(); uint32 GetPlatinum();
void AddLooter(Lua_Mob who); void AddLooter(Lua_Mob who);
bool HasItem(uint32 item_id); bool HasItem(uint32 item_id);
uint16 CountItem(uint32 item_id); uint32 CountItem(uint32 item_id);
uint32 GetItemIDBySlot(uint16 loot_slot); uint32 GetItemIDBySlot(uint16 loot_slot);
uint16 GetFirstLootSlotByItemID(uint32 item_id); uint16 GetFirstLootSlotByItemID(uint32 item_id);
Lua_Corpse_Loot_List GetLootList(lua_State* L); Lua_Corpse_Loot_List GetLootList(lua_State* L);
+4 -4
View File
@@ -164,7 +164,7 @@ int Lua_Inventory::GetSlotByItemInst(Lua_ItemInst inst) {
return self->GetSlotByItemInst(inst); return self->GetSlotByItemInst(inst);
} }
int Lua_Inventory::CountAugmentEquippedByID(uint32 item_id) { uint32 Lua_Inventory::CountAugmentEquippedByID(uint32 item_id) {
Lua_Safe_Call_Int(); Lua_Safe_Call_Int();
return self->CountAugmentEquippedByID(item_id); return self->CountAugmentEquippedByID(item_id);
} }
@@ -174,7 +174,7 @@ bool Lua_Inventory::HasAugmentEquippedByID(uint32 item_id) {
return self->HasAugmentEquippedByID(item_id); return self->HasAugmentEquippedByID(item_id);
} }
int Lua_Inventory::CountItemEquippedByID(uint32 item_id) { uint32 Lua_Inventory::CountItemEquippedByID(uint32 item_id) {
Lua_Safe_Call_Int(); Lua_Safe_Call_Int();
return self->CountItemEquippedByID(item_id); return self->CountItemEquippedByID(item_id);
} }
@@ -208,8 +208,8 @@ luabind::scope lua_register_inventory() {
.def("CalcSlotId", (int(Lua_Inventory::*)(int,int))&Lua_Inventory::CalcSlotId) .def("CalcSlotId", (int(Lua_Inventory::*)(int,int))&Lua_Inventory::CalcSlotId)
.def("CanItemFitInContainer", (bool(Lua_Inventory::*)(Lua_Item,Lua_Item))&Lua_Inventory::CanItemFitInContainer) .def("CanItemFitInContainer", (bool(Lua_Inventory::*)(Lua_Item,Lua_Item))&Lua_Inventory::CanItemFitInContainer)
.def("CheckNoDrop", (bool(Lua_Inventory::*)(int))&Lua_Inventory::CheckNoDrop) .def("CheckNoDrop", (bool(Lua_Inventory::*)(int))&Lua_Inventory::CheckNoDrop)
.def("CountAugmentEquippedByID", (int(Lua_Inventory::*)(uint32))&Lua_Inventory::CountAugmentEquippedByID) .def("CountAugmentEquippedByID", (uint32(Lua_Inventory::*)(uint32))&Lua_Inventory::CountAugmentEquippedByID)
.def("CountItemEquippedByID", (int(Lua_Inventory::*)(uint32))&Lua_Inventory::CountItemEquippedByID) .def("CountItemEquippedByID", (uint32(Lua_Inventory::*)(uint32))&Lua_Inventory::CountItemEquippedByID)
.def("DeleteItem", (bool(Lua_Inventory::*)(int))&Lua_Inventory::DeleteItem) .def("DeleteItem", (bool(Lua_Inventory::*)(int))&Lua_Inventory::DeleteItem)
.def("DeleteItem", (bool(Lua_Inventory::*)(int,int))&Lua_Inventory::DeleteItem) .def("DeleteItem", (bool(Lua_Inventory::*)(int,int))&Lua_Inventory::DeleteItem)
.def("FindFreeSlot", (int(Lua_Inventory::*)(bool,bool))&Lua_Inventory::FindFreeSlot) .def("FindFreeSlot", (int(Lua_Inventory::*)(bool,bool))&Lua_Inventory::FindFreeSlot)
+2 -2
View File
@@ -43,8 +43,8 @@ public:
bool DeleteItem(int slot_id); bool DeleteItem(int slot_id);
bool DeleteItem(int slot_id, int quantity); bool DeleteItem(int slot_id, int quantity);
bool CheckNoDrop(int slot_id); bool CheckNoDrop(int slot_id);
int CountAugmentEquippedByID(uint32 item_id); uint32 CountAugmentEquippedByID(uint32 item_id);
int CountItemEquippedByID(uint32 item_id); uint32 CountItemEquippedByID(uint32 item_id);
Lua_ItemInst PopItem(int slot_id); Lua_ItemInst PopItem(int slot_id);
bool HasAugmentEquippedByID(uint32 item_id); bool HasAugmentEquippedByID(uint32 item_id);
bool HasItemEquippedByID(uint32 item_id); bool HasItemEquippedByID(uint32 item_id);
+2 -2
View File
@@ -597,7 +597,7 @@ bool Lua_NPC::HasItem(uint32 item_id)
return self->HasItem(item_id); return self->HasItem(item_id);
} }
uint16 Lua_NPC::CountItem(uint32 item_id) uint32 Lua_NPC::CountItem(uint32 item_id)
{ {
Lua_Safe_Call_Int(); Lua_Safe_Call_Int();
return self->CountItem(item_id); return self->CountItem(item_id);
@@ -862,7 +862,7 @@ luabind::scope lua_register_npc() {
.def("CheckNPCFactionAlly", (int(Lua_NPC::*)(int))&Lua_NPC::CheckNPCFactionAlly) .def("CheckNPCFactionAlly", (int(Lua_NPC::*)(int))&Lua_NPC::CheckNPCFactionAlly)
.def("ClearItemList", (void(Lua_NPC::*)(void))&Lua_NPC::ClearLootItems) .def("ClearItemList", (void(Lua_NPC::*)(void))&Lua_NPC::ClearLootItems)
.def("ClearLastName", (void(Lua_NPC::*)(void))&Lua_NPC::ClearLastName) .def("ClearLastName", (void(Lua_NPC::*)(void))&Lua_NPC::ClearLastName)
.def("CountItem", (uint16(Lua_NPC::*)(uint32))&Lua_NPC::CountItem) .def("CountItem", (uint32(Lua_NPC::*)(uint32))&Lua_NPC::CountItem)
.def("CountLoot", (int(Lua_NPC::*)(void))&Lua_NPC::CountLoot) .def("CountLoot", (int(Lua_NPC::*)(void))&Lua_NPC::CountLoot)
.def("DeleteBucket", (void(Lua_NPC::*)(std::string))&Lua_NPC::DeleteBucket) .def("DeleteBucket", (void(Lua_NPC::*)(std::string))&Lua_NPC::DeleteBucket)
.def("DescribeSpecialAbilities", (void(Lua_NPC::*)(Lua_Client))&Lua_NPC::DescribeSpecialAbilities) .def("DescribeSpecialAbilities", (void(Lua_NPC::*)(Lua_Client))&Lua_NPC::DescribeSpecialAbilities)
+1 -1
View File
@@ -146,7 +146,7 @@ public:
void ChangeLastName(std::string last_name); void ChangeLastName(std::string last_name);
void ClearLastName(); void ClearLastName();
bool HasItem(uint32 item_id); bool HasItem(uint32 item_id);
uint16 CountItem(uint32 item_id); uint32 CountItem(uint32 item_id);
uint32 GetLootItemIDBySlot(uint16 loot_slot); uint32 GetLootItemIDBySlot(uint16 loot_slot);
uint16 GetFirstLootSlotByItemID(uint32 item_id); uint16 GetFirstLootSlotByItemID(uint32 item_id);
float GetHealScale(); float GetHealScale();
+5 -5
View File
@@ -320,7 +320,7 @@ bool Map::Load(const std::string &filename)
} }
#ifdef USE_MAP_MMFS #ifdef USE_MAP_MMFS
if (v) if (loaded_map_file)
return SaveMMF(filename, force_mmf_overwrite); return SaveMMF(filename, force_mmf_overwrite);
#endif /*USE_MAP_MMFS*/ #endif /*USE_MAP_MMFS*/
@@ -338,7 +338,7 @@ bool Map::Load(const std::string &filename)
} }
#ifdef USE_MAP_MMFS #ifdef USE_MAP_MMFS
if (v) if (loaded_map_file)
return SaveMMF(filename, force_mmf_overwrite); return SaveMMF(filename, force_mmf_overwrite);
#endif /*USE_MAP_MMFS*/ #endif /*USE_MAP_MMFS*/
@@ -1064,7 +1064,7 @@ bool Map::LoadMMF(const std::string& map_file_name, bool force_mmf_overwrite)
fclose(f); fclose(f);
std::vector<char> rm_buffer(rm_buffer_size); std::vector<char> rm_buffer(rm_buffer_size);
uint32 v = InflateData(mmf_buffer.data(), mmf_buffer_size, rm_buffer.data(), rm_buffer_size); uint32 v = EQ::InflateData(mmf_buffer.data(), mmf_buffer_size, rm_buffer.data(), rm_buffer_size);
if (imp) { if (imp) {
imp->rm->release(); imp->rm->release();
@@ -1120,11 +1120,11 @@ bool Map::SaveMMF(const std::string& map_file_name, bool force_mmf_overwrite)
} }
uint32 rm_buffer_size = rm_buffer.size(); uint32 rm_buffer_size = rm_buffer.size();
uint32 mmf_buffer_size = EstimateDeflateBuffer(rm_buffer.size()); uint32 mmf_buffer_size = EQ::EstimateDeflateBuffer(rm_buffer.size());
std::vector<char> mmf_buffer(mmf_buffer_size); std::vector<char> mmf_buffer(mmf_buffer_size);
mmf_buffer_size = DeflateData(rm_buffer.data(), rm_buffer.size(), mmf_buffer.data(), mmf_buffer.size()); mmf_buffer_size = EQ::DeflateData(rm_buffer.data(), rm_buffer.size(), mmf_buffer.data(), mmf_buffer.size());
if (!mmf_buffer_size) { if (!mmf_buffer_size) {
LogInfo("Failed to save Map MMF file: [{}] - null MMF buffer size", mmf_file_name.c_str()); LogInfo("Failed to save Map MMF file: [{}] - null MMF buffer size", mmf_file_name.c_str());
return false; return false;
+21 -8
View File
@@ -572,6 +572,8 @@ Mob::~Mob()
m_close_mobs.clear(); m_close_mobs.clear();
ClearDataBucketCache();
LeaveHealRotationTargetPool(); LeaveHealRotationTargetPool();
} }
@@ -5325,14 +5327,7 @@ void Mob::ExecWeaponProc(const EQ::ItemInstance* inst, uint16 spell_id, Mob* on,
//It should be safe as we don't have any truly const EQ::ItemInstance floating around anywhere. //It should be safe as we don't have any truly const EQ::ItemInstance floating around anywhere.
//So we'll live with it for now //So we'll live with it for now
if (parse->ItemHasQuestSub(const_cast<EQ::ItemInstance*>(inst), EVENT_WEAPON_PROC)) { if (parse->ItemHasQuestSub(const_cast<EQ::ItemInstance*>(inst), EVENT_WEAPON_PROC)) {
int i = parse->EventItem( int i = parse->EventItem(EVENT_WEAPON_PROC, CastToClient(), const_cast<EQ::ItemInstance*>(inst), on, "", spell_id);
EVENT_WEAPON_PROC,
CastToClient(),
const_cast<EQ::ItemInstance*>(inst),
on,
"",
spell_id
);
if (i != 0) { if (i != 0) {
return; return;
@@ -8613,3 +8608,21 @@ std::unordered_map<uint16, Mob *> &Mob::GetCloseMobList(float distance)
{ {
return entity_list.GetCloseMobList(this, distance); return entity_list.GetCloseMobList(this, distance);
} }
void Mob::ClearDataBucketCache()
{
if (IsOfClientBot()) {
uint64 id = 0;
DataBucketLoadType::Type t{};
if (IsBot()) {
id = CastToBot()->GetBotID();
t = DataBucketLoadType::Bot;
}
else if (IsClient()) {
id = CastToClient()->CharacterID();
t = DataBucketLoadType::Client;
}
DataBucket::DeleteFromCache(id, t);
}
}
+2
View File
@@ -1491,6 +1491,8 @@ public:
std::unordered_map<uint16, Mob *> &GetCloseMobList(float distance = 0.0f); std::unordered_map<uint16, Mob *> &GetCloseMobList(float distance = 0.0f);
void CheckScanCloseMobsMovingTimer(); void CheckScanCloseMobsMovingTimer();
void ClearDataBucketCache();
protected: protected:
void CommonDamage(Mob* other, int64 &damage, const uint16 spell_id, const EQ::skills::SkillType attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic, eSpecialAttacks specal = eSpecialAttacks::None); void CommonDamage(Mob* other, int64 &damage, const uint16 spell_id, const EQ::skills::SkillType attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic, eSpecialAttacks specal = eSpecialAttacks::None);
static uint16 GetProcID(uint16 spell_id, uint8 effect_index); static uint16 GetProcID(uint16 spell_id, uint8 effect_index);
+1 -1
View File
@@ -222,7 +222,7 @@ public:
void RemoveLootCash(); void RemoveLootCash();
void QueryLoot(Client *to, bool is_pet_query = false); void QueryLoot(Client *to, bool is_pet_query = false);
bool HasItem(uint32 item_id); bool HasItem(uint32 item_id);
uint16 CountItem(uint32 item_id); uint32 CountItem(uint32 item_id);
uint32 GetLootItemIDBySlot(uint16 loot_slot); uint32 GetLootItemIDBySlot(uint16 loot_slot);
uint16 GetFirstLootSlotByItemID(uint32 item_id); uint16 GetFirstLootSlotByItemID(uint32 item_id);
std::vector<int> GetLootList(); std::vector<int> GetLootList();
+2 -2
View File
@@ -145,7 +145,7 @@ EQ::ItemInstance* Perl_Bot_GetAugmentAt(Bot* self, int16 slot_id, uint8 augment_
return nullptr; return nullptr;
} }
int Perl_Bot_CountAugmentEquippedByID(Bot* self, uint32 item_id) uint32 Perl_Bot_CountAugmentEquippedByID(Bot* self, uint32 item_id)
{ {
return self->GetInv().CountAugmentEquippedByID(item_id); return self->GetInv().CountAugmentEquippedByID(item_id);
} }
@@ -155,7 +155,7 @@ bool Perl_Bot_HasAugmentEquippedByID(Bot* self, uint32 item_id)
return self->GetInv().HasAugmentEquippedByID(item_id); return self->GetInv().HasAugmentEquippedByID(item_id);
} }
int Perl_Bot_CountItemEquippedByID(Bot* self, uint32 item_id) uint32 Perl_Bot_CountItemEquippedByID(Bot* self, uint32 item_id)
{ {
return self->GetInv().CountItemEquippedByID(item_id); return self->GetInv().CountItemEquippedByID(item_id);
} }
+16 -3
View File
@@ -2209,7 +2209,7 @@ void Perl_Client_SendToInstance(Client* self, std::string instance_type, std::st
self->SendToInstance(instance_type, zone_short_name, instance_version, x, y, z, heading, instance_identifier, duration); self->SendToInstance(instance_type, zone_short_name, instance_version, x, y, z, heading, instance_identifier, duration);
} }
int Perl_Client_CountItem(Client* self, uint32 item_id) uint32 Perl_Client_CountItem(Client* self, uint32 item_id)
{ {
return self->CountItem(item_id); return self->CountItem(item_id);
} }
@@ -2388,7 +2388,7 @@ void Perl_Client_AddItem(Client* self, perl::reference table_ref)
augment_four, augment_five, augment_six, attuned, slot_id); augment_four, augment_five, augment_six, attuned, slot_id);
} }
int Perl_Client_CountAugmentEquippedByID(Client* self, uint32 item_id) uint32 Perl_Client_CountAugmentEquippedByID(Client* self, uint32 item_id)
{ {
return self->GetInv().CountAugmentEquippedByID(item_id); return self->GetInv().CountAugmentEquippedByID(item_id);
} }
@@ -2398,7 +2398,7 @@ bool Perl_Client_HasAugmentEquippedByID(Client* self, uint32 item_id)
return self->GetInv().HasAugmentEquippedByID(item_id); return self->GetInv().HasAugmentEquippedByID(item_id);
} }
int Perl_Client_CountItemEquippedByID(Client* self, uint32 item_id) uint32 Perl_Client_CountItemEquippedByID(Client* self, uint32 item_id)
{ {
return self->GetInv().CountItemEquippedByID(item_id); return self->GetInv().CountItemEquippedByID(item_id);
} }
@@ -3212,6 +3212,18 @@ Merc* Perl_Client_GetMerc(Client* self)
return self->GetMerc(); return self->GetMerc();
} }
perl::array Perl_Client_GetInventorySlots(Client* self)
{
perl::array result;
const auto& v = self->GetInventorySlots();
for (int i = 0; i < v.size(); ++i) {
result.push_back(v[i]);
}
return result;
}
void perl_register_client() void perl_register_client()
{ {
perl::interpreter perl(PERL_GET_THX); perl::interpreter perl(PERL_GET_THX);
@@ -3426,6 +3438,7 @@ void perl_register_client()
package.add("GetInstanceID", &Perl_Client_GetInstanceID); package.add("GetInstanceID", &Perl_Client_GetInstanceID);
package.add("GetInstrumentMod", &Perl_Client_GetInstrumentMod); package.add("GetInstrumentMod", &Perl_Client_GetInstrumentMod);
package.add("GetInventory", &Perl_Client_GetInventory); package.add("GetInventory", &Perl_Client_GetInventory);
package.add("GetInventorySlots", &Perl_Client_GetInventorySlots);
package.add("GetInvulnerableEnvironmentDamage", &Perl_Client_GetInvulnerableEnvironmentDamage); package.add("GetInvulnerableEnvironmentDamage", &Perl_Client_GetInvulnerableEnvironmentDamage);
package.add("GetItemAt", &Perl_Client_GetItemAt); package.add("GetItemAt", &Perl_Client_GetItemAt);
package.add("GetItemCooldown", &Perl_Client_GetItemCooldown); package.add("GetItemCooldown", &Perl_Client_GetItemCooldown);
+2 -2
View File
@@ -150,7 +150,7 @@ bool Perl_Inventory_HasAugmentEquippedByID(EQ::InventoryProfile* self, uint32_t
return self->HasAugmentEquippedByID(item_id); return self->HasAugmentEquippedByID(item_id);
} }
int Perl_Inventory_CountAugmentEquippedByID(EQ::InventoryProfile* self, uint32_t item_id) uint32 Perl_Inventory_CountAugmentEquippedByID(EQ::InventoryProfile* self, uint32_t item_id)
{ {
return self->CountAugmentEquippedByID(item_id); return self->CountAugmentEquippedByID(item_id);
} }
@@ -160,7 +160,7 @@ bool Perl_Inventory_HasItemEquippedByID(EQ::InventoryProfile* self, uint32_t ite
return self->HasItemEquippedByID(item_id); return self->HasItemEquippedByID(item_id);
} }
int Perl_Inventory_CountItemEquippedByID(EQ::InventoryProfile* self, uint32_t item_id) uint32 Perl_Inventory_CountItemEquippedByID(EQ::InventoryProfile* self, uint32_t item_id)
{ {
return self->CountItemEquippedByID(item_id); return self->CountItemEquippedByID(item_id);
} }
+1 -1
View File
@@ -615,7 +615,7 @@ bool Perl_NPC_HasItem(NPC* self, uint32 item_id) // @categories Script Utility
return self->HasItem(item_id); return self->HasItem(item_id);
} }
int Perl_NPC_CountItem(NPC* self, uint32 item_id) uint32 Perl_NPC_CountItem(NPC* self, uint32 item_id)
{ {
return self->CountItem(item_id); return self->CountItem(item_id);
} }
+1 -1
View File
@@ -161,7 +161,7 @@ bool Perl_Corpse_HasItem(Corpse* self, uint32_t item_id) // @categories Script U
return self->HasItem(item_id); return self->HasItem(item_id);
} }
int Perl_Corpse_CountItem(Corpse* self, uint32_t item_id) // @categories Script Utility uint32 Perl_Corpse_CountItem(Corpse* self, uint32_t item_id) // @categories Script Utility
{ {
return self->CountItem(item_id); return self->CountItem(item_id);
} }
+9 -48
View File
@@ -91,13 +91,7 @@ void QuestManager::Process() {
if (cur->Timer_.Enabled() && cur->Timer_.Check()) { if (cur->Timer_.Enabled() && cur->Timer_.Check()) {
if (cur->mob) { if (cur->mob) {
if (cur->mob->IsEncounter()) { if (cur->mob->IsEncounter()) {
parse->EventEncounter( parse->EventEncounter(EVENT_TIMER, cur->mob->CastToEncounter()->GetEncounterName(), cur->name, 0, nullptr);
EVENT_TIMER,
cur->mob->CastToEncounter()->GetEncounterName(),
cur->name,
0,
nullptr
);
} else { } else {
parse->EventMob(EVENT_TIMER, cur->mob, nullptr, [&]() { return cur->name; }, 0); parse->EventMob(EVENT_TIMER, cur->mob, nullptr, [&]() { return cur->name; }, 0);
} }
@@ -661,14 +655,7 @@ void QuestManager::stoptimer(const std::string& timer_name)
for (auto e = QTimerList.begin(); e != QTimerList.end(); ++e) { for (auto e = QTimerList.begin(); e != QTimerList.end(); ++e) {
if (e->mob && e->mob == owner && e->name == timer_name) { if (e->mob && e->mob == owner && e->name == timer_name) {
parse->EventMob( parse->EventMob(EVENT_TIMER_STOP, owner, nullptr, [&]() { return timer_name; });
EVENT_TIMER_STOP,
owner,
nullptr,
[&]() {
return timer_name;
}
);
QTimerList.erase(e); QTimerList.erase(e);
break; break;
@@ -695,14 +682,7 @@ void QuestManager::stoptimer(const std::string& timer_name, Mob* m)
for (auto e = QTimerList.begin(); e != QTimerList.end();) { for (auto e = QTimerList.begin(); e != QTimerList.end();) {
if (e->mob && e->mob == m) { if (e->mob && e->mob == m) {
parse->EventMob( parse->EventMob(EVENT_TIMER_STOP, m, nullptr, [&]() { return timer_name; });
EVENT_TIMER_STOP,
m,
nullptr,
[&]() {
return timer_name;
}
);
QTimerList.erase(e); QTimerList.erase(e);
break; break;
@@ -743,14 +723,7 @@ void QuestManager::stopalltimers()
for (auto e = QTimerList.begin(); e != QTimerList.end();) { for (auto e = QTimerList.begin(); e != QTimerList.end();) {
if (e->mob && e->mob == owner) { if (e->mob && e->mob == owner) {
parse->EventMob( parse->EventMob(EVENT_TIMER_STOP, owner, nullptr, [&]() { return e->name; });
EVENT_TIMER_STOP,
owner,
nullptr,
[&]() {
return e->name;
}
);
e = QTimerList.erase(e); e = QTimerList.erase(e);
} else { } else {
@@ -792,14 +765,7 @@ void QuestManager::stopalltimers(Mob* m)
for (auto e = QTimerList.begin(); e != QTimerList.end();) { for (auto e = QTimerList.begin(); e != QTimerList.end();) {
if (e->mob && e->mob == m) { if (e->mob && e->mob == m) {
parse->EventMob( parse->EventMob(EVENT_TIMER_STOP, m, nullptr, [&]() { return e->name; });
EVENT_TIMER_STOP,
m,
nullptr,
[&]() {
return e->name;
}
);
e = QTimerList.erase(e); e = QTimerList.erase(e);
} else { } else {
@@ -853,18 +819,13 @@ void QuestManager::pausetimer(const std::string& timer_name, Mob* m)
} }
); );
parse->EventMob( parse->EventMob(EVENT_TIMER_PAUSE, mob, nullptr, [&]() {
EVENT_TIMER_PAUSE,
mob,
nullptr,
[&]() {
return fmt::format( return fmt::format(
"{} {}", "{} {}",
timer_name, timer_name,
milliseconds milliseconds
); );
} });
);
LogQuests("Pausing timer [{}] for [{}] with [{}] ms remaining", timer_name, owner->GetName(), milliseconds); LogQuests("Pausing timer [{}] for [{}] with [{}] ms remaining", timer_name, owner->GetName(), milliseconds);
} }
@@ -1326,7 +1287,7 @@ std::string QuestManager::getskillname(int skill_id) {
} }
std::string QuestManager::getldonthemename(uint32 theme_id) { std::string QuestManager::getldonthemename(uint32 theme_id) {
return EQ::constants::GetLDoNThemeName(theme_id); return LDoNTheme::GetName(theme_id);
} }
std::string QuestManager::getfactionname(int faction_id) { std::string QuestManager::getfactionname(int faction_id) {
@@ -3343,7 +3304,7 @@ int QuestManager::collectitems(uint32 item_id, bool remove)
return quantity; return quantity;
} }
int QuestManager::countitem(uint32 item_id) { uint32 QuestManager::countitem(uint32 item_id) {
QuestManagerCurrentQuestVars(); QuestManagerCurrentQuestVars();
if (!initiator) { if (!initiator) {
+1 -1
View File
@@ -249,7 +249,7 @@ public:
int getlevel(uint8 type); int getlevel(uint8 type);
int collectitems(uint32 item_id, bool remove); int collectitems(uint32 item_id, bool remove);
int collectitems_processSlot(int16 slot_id, uint32 item_id, bool remove); int collectitems_processSlot(int16 slot_id, uint32 item_id, bool remove);
int countitem(uint32 item_id); uint32 countitem(uint32 item_id);
void removeitem(uint32 item_id, uint32 quantity = 1); void removeitem(uint32 item_id, uint32 quantity = 1);
std::string getitemcomment(uint32 item_id); std::string getitemcomment(uint32 item_id);
std::string getitemlore(uint32 item_id); std::string getitemlore(uint32 item_id);
+66 -101
View File
@@ -256,11 +256,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
Mob* spell_target = entity_list.GetMobID(target_id); Mob* spell_target = entity_list.GetMobID(target_id);
std::vector<std::any> args = { spell_target }; std::vector<std::any> args = { spell_target };
int return_value = parse->EventMob( int return_value = parse->EventMob(EVENT_CAST_BEGIN, this, nullptr, [&]() {
EVENT_CAST_BEGIN,
this,
nullptr,
[&]() {
return fmt::format( return fmt::format(
"{} {} {} {}", "{} {} {} {}",
spell_id, spell_id,
@@ -268,10 +264,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
GetCasterLevel(spell_id), GetCasterLevel(spell_id),
target_id target_id
); );
}, }, 0, &args);
0,
&args
);
if (IsClient() && return_value != 0) { if (IsClient() && return_value != 0) {
if (IsDiscipline(spell_id)) { if (IsDiscipline(spell_id)) {
@@ -652,6 +645,11 @@ bool Mob::DoCastingChecksOnCaster(int32 spell_id, CastingSlot slot) {
return true; return true;
} }
struct SpellCheck {
std::function<bool()> condition; // The condition to check
std::function<bool()> action; // The action if the condition fails
};
bool Mob::DoCastingChecksZoneRestrictions(bool check_on_casting, int32 spell_id) { bool Mob::DoCastingChecksZoneRestrictions(bool check_on_casting, int32 spell_id) {
/* /*
@@ -659,114 +657,92 @@ bool Mob::DoCastingChecksZoneRestrictions(bool check_on_casting, int32 spell_id)
- levitate zone restriction (client blocks) [cancel before begin cast message] - levitate zone restriction (client blocks) [cancel before begin cast message]
- can not cast outdoor [cancels after spell finishes channeling] - can not cast outdoor [cancels after spell finishes channeling]
If the spell is a casted spell, check on CastSpell and ignore on SpellFinished. If the spell is a cast spell, check on CastSpell and ignore on SpellFinished.
If the spell is a initiated from SpellFinished, then check at start of SpellFinished. If the spell is initiated from SpellFinished, then check at start of SpellFinished.
*/ */
bool bypass_casting_restrictions = false; bool bypass_casting_restrictions = !IsClient();
glm::vec3 position = glm::vec3(GetPosition());
if (!IsClient()) { auto gm_bypass_message = [&](const std::string& restriction) {
bypass_casting_restrictions = true; if (CastToClient()->GetGM()) {
}
if (IsClient() && CastToClient()->GetGM()) {
bypass_casting_restrictions = true;
Message( Message(
Chat::White, Chat::White,
fmt::format( fmt::format(
"Your GM flag allows you to bypass zone casting restrictions and cast {} in this zone.", "Your GM flag allows you to bypass {} and cast {}.",
restriction,
Saylink::Silent( Saylink::Silent(
fmt::format( fmt::format("#castspell {}", spell_id),
"#castspell {}",
spell_id
),
GetSpellName(spell_id) GetSpellName(spell_id)
) )
).c_str() ).c_str()
); );
return true;
} }
return false;
};
/* std::vector<SpellCheck> spell_checks = {
Zone ares that prevent blocked spells from being cast. // Blocked spells
If on cast iniated then check any mob casting, if on spellfinished only check if is from client. {
*/ [&]() { return !bypass_casting_restrictions && zone->IsSpellBlocked(spell_id, position); },
if ((check_on_casting && !bypass_casting_restrictions) || (!check_on_casting && IsClient())) { [&]() {
if (zone->IsSpellBlocked(spell_id, glm::vec3(GetPosition()))) { if (gm_bypass_message("zone blocked spells")) { return true; }
if (IsClient()) { const char* msg = zone->GetSpellBlockedMessage(spell_id, position);
if (!CastToClient()->GetGM()) { Message(Chat::Red, msg ? msg : "You can't cast this spell here.");
const char *msg = zone->GetSpellBlockedMessage(spell_id, glm::vec3(GetPosition()));
if (msg) {
Message(Chat::Red, msg);
return false; return false;
} }
else { },
Message(Chat::Red, "You can't cast this spell here."); // Levitation restriction
return false; {
} [&]() { return !bypass_casting_restrictions && !zone->CanLevitate() && IsEffectInSpell(spell_id, SE_Levitate); },
LogSpells("Spell casting canceled [{}] : can not cast in this zone location blocked spell.", spell_id); [&]() {
} if (gm_bypass_message("zone levitation restrictions")) { return true; }
else {
Message(
Chat::White,
fmt::format(
"Your GM flag allows you to bypass zone blocked spells and cast {} in this zone.",
Saylink::Silent(
fmt::format(
"#castspell {}",
spell_id
),
GetSpellName(spell_id)
)
).c_str()
);
LogSpells("GM Cast Blocked Spell: [{}] (ID [{}])", GetSpellName(spell_id), spell_id);
}
}
return false;
}
}
/*
Zones where you can not use levitate spells.
*/
if (!bypass_casting_restrictions && !zone->CanLevitate() && IsEffectInSpell(spell_id, SE_Levitate)) { //check on spellfinished.
Message(Chat::Red, "You have entered an area where levitation effects do not function."); Message(Chat::Red, "You have entered an area where levitation effects do not function.");
LogSpells("Spell casting canceled [{}] : can not cast levitation in this zone.", spell_id);
return false; return false;
} }
/* },
Zones where you can not use detrimental spells. // Detrimental spells restriction
*/ {
if (IsDetrimentalSpell(spell_id) && !zone->CanDoCombat()) { [&]() { return !bypass_casting_restrictions && IsDetrimentalSpell(spell_id) && !zone->CanDoCombat(); },
[&]() {
if (gm_bypass_message("no combat zone restrictions")) { return true; }
Message(Chat::Red, "You cannot cast detrimental spells here."); Message(Chat::Red, "You cannot cast detrimental spells here.");
return false; return false;
} }
/* },
Zones where you can not cast a spell that is for daytime or nighttime only // Daytime-only spells
*/ {
if (spells[spell_id].time_of_day == SpellTimeRestrictions::Day && !zone->zone_time.IsDayTime()) { [&]() { return !bypass_casting_restrictions && spells[spell_id].time_of_day == SpellTimeRestrictions::Day && !zone->zone_time.IsDayTime(); },
[&]() {
if (gm_bypass_message("spell daytime restrictions")) { return true; }
MessageString(Chat::Red, CAST_DAYTIME); MessageString(Chat::Red, CAST_DAYTIME);
return false; return false;
} }
},
if (spells[spell_id].time_of_day == SpellTimeRestrictions::Night && !zone->zone_time.IsNightTime()) { // Nighttime-only spells
{
[&]() { return !bypass_casting_restrictions && spells[spell_id].time_of_day == SpellTimeRestrictions::Night && !zone->zone_time.IsNightTime(); },
[&]() {
if (gm_bypass_message("spell nighttime restrictions")) return true;
MessageString(Chat::Red, CAST_NIGHTTIME); MessageString(Chat::Red, CAST_NIGHTTIME);
return false; return false;
} }
},
if (check_on_casting) { // Outdoor-only spells
/* {
Zones where you can not cast out door only spells. This is only checked when casting is completed. [&]() { return check_on_casting && !bypass_casting_restrictions && spells[spell_id].zone_type == 1 && !zone->CanCastOutdoor(); },
*/ [&]() {
if (!bypass_casting_restrictions && spells[spell_id].zone_type == 1 && !zone->CanCastOutdoor()) { if (gm_bypass_message("zone outdoor restrictions")) return true;
if (IsClient()) {
if (!CastToClient()->GetGM()) {
MessageString(Chat::Red, CAST_OUTDOORS); MessageString(Chat::Red, CAST_OUTDOORS);
LogSpells("Spell casting canceled [{}] : can not cast outdoors.", spell_id);
return false; return false;
} else {
Message(Chat::White, "Your GM flag allows you to cast outdoor spells when indoors.");
} }
} }
};
for (const auto& check : spell_checks) {
if (check.condition() && !check.action()) {
return false;
} }
} }
@@ -1804,11 +1780,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo
std::vector<std::any> args = { spell_target }; std::vector<std::any> args = { spell_target };
parse->EventMob( parse->EventMob(EVENT_CAST, this, nullptr, [&]() {
EVENT_CAST,
this,
nullptr,
[&]() {
return fmt::format( return fmt::format(
"{} {} {} {}", "{} {} {} {}",
spell_id, spell_id,
@@ -1816,10 +1788,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo
GetCasterLevel(spell_id), GetCasterLevel(spell_id),
target_id target_id
); );
}, }, 0, &args);
0,
&args
);
if(bard_song_mode) if(bard_song_mode)
{ {
@@ -3965,10 +3934,7 @@ bool Mob::SpellOnTarget(
std::vector<std::any> args = { spelltar }; std::vector<std::any> args = { spelltar };
parse->EventMob( parse->EventMob(EVENT_CAST_ON, spelltar, this,
EVENT_CAST_ON,
spelltar,
this,
[&]() { [&]() {
return fmt::format( return fmt::format(
"{} {} {} {}", "{} {} {} {}",
@@ -3978,8 +3944,7 @@ bool Mob::SpellOnTarget(
target_id target_id
); );
}, },
0, 0, &args
&args
); );
if (!DoCastingChecksOnTarget(false, spell_id, spelltar)) { if (!DoCastingChecksOnTarget(false, spell_id, spelltar)) {
+7 -2
View File
@@ -1097,6 +1097,7 @@ void Client::TraderStartTrader(const EQApplicationPacket *app)
trader_item.char_entity_id = GetID(); trader_item.char_entity_id = GetID();
trader_item.char_id = CharacterID(); trader_item.char_id = CharacterID();
trader_item.char_zone_id = GetZoneID(); trader_item.char_zone_id = GetZoneID();
trader_item.char_zone_instance_id = GetInstanceID();
trader_item.item_charges = inst->GetCharges() == 0 ? 1 : inst->GetCharges(); trader_item.item_charges = inst->GetCharges() == 0 ? 1 : inst->GetCharges();
trader_item.item_cost = inst->GetPrice(); trader_item.item_cost = inst->GetPrice();
trader_item.item_id = inst->GetID(); trader_item.item_id = inst->GetID();
@@ -1796,7 +1797,7 @@ void Client::SendBarterWelcome()
void Client::DoBazaarSearch(BazaarSearchCriteria_Struct search_criteria) void Client::DoBazaarSearch(BazaarSearchCriteria_Struct search_criteria)
{ {
auto results = Bazaar::GetSearchResults(database, search_criteria, GetZoneID()); auto results = Bazaar::GetSearchResults(database, search_criteria, GetZoneID(), GetInstanceID());
if (results.empty()) { if (results.empty()) {
SendBazaarDone(GetID()); SendBazaarDone(GetID());
return; return;
@@ -2943,6 +2944,8 @@ void Client::SendBecomeTrader(BazaarTraderBarterActions action, uint32 entity_id
data->action = action; data->action = action;
data->entity_id = trader->GetID(); data->entity_id = trader->GetID();
data->trader_id = trader->CharacterID(); data->trader_id = trader->CharacterID();
data->zone_id = trader->GetZoneID();
data->zone_instance_id = trader->GetInstanceID();
strn0cpy(data->trader_name, trader->GetCleanName(), sizeof(data->trader_name)); strn0cpy(data->trader_name, trader->GetCleanName(), sizeof(data->trader_name));
QueuePacket(outapp); QueuePacket(outapp);
@@ -3092,6 +3095,7 @@ void Client::TraderPriceUpdate(const EQApplicationPacket *app)
trader_item.char_entity_id = GetID(); trader_item.char_entity_id = GetID();
trader_item.char_id = CharacterID(); trader_item.char_id = CharacterID();
trader_item.char_zone_id = GetZoneID(); trader_item.char_zone_id = GetZoneID();
trader_item.char_zone_instance_id = GetInstanceID();
trader_item.item_charges = newgis->charges[i]; trader_item.item_charges = newgis->charges[i];
trader_item.item_cost = tpus->NewPrice; trader_item.item_cost = tpus->NewPrice;
trader_item.item_id = newgis->items[i]; trader_item.item_id = newgis->items[i];
@@ -3224,7 +3228,8 @@ void Client::SendBulkBazaarTraders()
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, results.count); VARSTRUCT_ENCODE_TYPE(uint32, bufptr, results.count);
for (auto t : results.traders) { for (auto t : results.traders) {
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, t.zone_id); VARSTRUCT_ENCODE_TYPE(uint16, bufptr, t.zone_id);
VARSTRUCT_ENCODE_TYPE(uint16, bufptr, t.zone_instance_id);
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, t.trader_id); VARSTRUCT_ENCODE_TYPE(uint32, bufptr, t.trader_id);
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, t.entity_id); VARSTRUCT_ENCODE_TYPE(uint32, bufptr, t.entity_id);
VARSTRUCT_ENCODE_STRING(bufptr, t.trader_name.c_str()); VARSTRUCT_ENCODE_STRING(bufptr, t.trader_name.c_str());
+3 -14
View File
@@ -91,8 +91,6 @@ void WorldServer::Connect()
}); });
m_connection->OnMessage(std::bind(&WorldServer::HandleMessage, this, std::placeholders::_1, std::placeholders::_2)); m_connection->OnMessage(std::bind(&WorldServer::HandleMessage, this, std::placeholders::_1, std::placeholders::_2));
m_keepalive = std::make_unique<EQ::Timer>(1000, true, std::bind(&WorldServer::OnKeepAlive, this, std::placeholders::_1));
} }
bool WorldServer::SendPacket(ServerPacket *pack) bool WorldServer::SendPacket(ServerPacket *pack)
@@ -3644,11 +3642,6 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
SharedTaskZoneMessaging::HandleWorldMessage(pack); SharedTaskZoneMessaging::HandleWorldMessage(pack);
break; break;
} }
case ServerOP_DataBucketCacheUpdate:
{
DataBucket::HandleWorldMessage(pack);
break;
}
case ServerOP_GuildTributeUpdate: { case ServerOP_GuildTributeUpdate: {
GuildTributeUpdate* in = (GuildTributeUpdate*)pack->pBuffer; GuildTributeUpdate* in = (GuildTributeUpdate*)pack->pBuffer;
@@ -3934,12 +3927,14 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
out->action = 0; out->action = 0;
} }
} }
out->entity_id = in->entity_id; out->entity_id = in->entity_id;
out->zone_id = in->zone_id; out->zone_id = in->zone_id;
out->zone_instance_id = in->instance_id;
out->trader_id = in->trader_id; out->trader_id = in->trader_id;
strn0cpy(out->trader_name, in->trader_name, sizeof(out->trader_name)); strn0cpy(out->trader_name, in->trader_name, sizeof(out->trader_name));
c.second->QueuePacket(outapp); c.second->QueuePacket(outapp, true, Mob::CLIENT_CONNECTED);
safe_delete(outapp); safe_delete(outapp);
} }
if (zone && zone->GetZoneID() == Zones::BAZAAR && in->instance_id == zone->GetInstanceID()) { if (zone && zone->GetZoneID() == Zones::BAZAAR && in->instance_id == zone->GetInstanceID()) {
@@ -4693,12 +4688,6 @@ void WorldServer::RequestTellQueue(const char *who)
return; return;
} }
void WorldServer::OnKeepAlive(EQ::Timer *t)
{
ServerPacket pack(ServerOP_KeepAlive, 0);
SendPacket(&pack);
}
ZoneEventScheduler *WorldServer::GetScheduler() const ZoneEventScheduler *WorldServer::GetScheduler() const
{ {
return m_zone_scheduler; return m_zone_scheduler;
-2
View File
@@ -73,8 +73,6 @@ private:
uint32 cur_groupid; uint32 cur_groupid;
uint32 last_groupid; uint32 last_groupid;
void OnKeepAlive(EQ::Timer *t);
std::unique_ptr<EQ::Net::ServertalkClient> m_connection; std::unique_ptr<EQ::Net::ServertalkClient> m_connection;
std::unique_ptr<EQ::Timer> m_keepalive; std::unique_ptr<EQ::Timer> m_keepalive;
+9 -1
View File
@@ -1100,7 +1100,12 @@ Zone::~Zone() {
if (worldserver.Connected()) { if (worldserver.Connected()) {
worldserver.SetZoneData(0); worldserver.SetZoneData(0);
} }
for (auto &e: npc_emote_list) {
safe_delete(e);
}
npc_emote_list.clear(); npc_emote_list.clear();
zone_point_list.Clear(); zone_point_list.Clear();
entity_list.Clear(); entity_list.Clear();
parse->ReloadQuests(); parse->ReloadQuests();
@@ -1257,7 +1262,6 @@ void Zone::ReloadStaticData() {
LoadVeteranRewards(); LoadVeteranRewards();
LoadAlternateCurrencies(); LoadAlternateCurrencies();
npc_emote_list.clear();
LoadNPCEmotes(&npc_emote_list); LoadNPCEmotes(&npc_emote_list);
//load the zone config file. //load the zone config file.
@@ -2575,6 +2579,10 @@ void Zone::DoAdventureActions()
void Zone::LoadNPCEmotes(std::vector<NPC_Emote_Struct*>* v) void Zone::LoadNPCEmotes(std::vector<NPC_Emote_Struct*>* v)
{ {
for (auto &e: *v) {
safe_delete(e);
}
v->clear(); v->clear();
const auto& l = NpcEmotesRepository::All(content_db); const auto& l = NpcEmotesRepository::All(content_db);
+5 -3
View File
@@ -43,9 +43,11 @@ class ZoneConfig : public EQEmuConfig {
} }
// Load the config // Load the config
static bool LoadConfig(const std::string& path = "") { static bool LoadConfig(const std::string &path = "")
if (_zone_config != nullptr) {
delete _zone_config; safe_delete(_zone_config);
safe_delete(_config);
_zone_config = new ZoneConfig; _zone_config = new ZoneConfig;
_config = _zone_config; _config = _zone_config;
-2
View File
@@ -1923,8 +1923,6 @@ const NPCType *ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load
} }
} }
DataBucket::BulkLoadEntities(DataBucketLoadType::NPC, npc_ids);
if (!npc_faction_ids.empty()) { if (!npc_faction_ids.empty()) {
zone->LoadNPCFactions(npc_faction_ids); zone->LoadNPCFactions(npc_faction_ids);
zone->LoadNPCFactionAssociations(npc_faction_ids); zone->LoadNPCFactionAssociations(npc_faction_ids);