mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-22 20:33:01 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e25ff70de9 | |||
| 3c02b3e60f |
-671
@@ -1,674 +1,3 @@
|
||||
## [23.8.1] 6/28/2025
|
||||
|
||||
### Crash Fix
|
||||
|
||||
* Fix Possible Crashes with Raid Methods ([#4955](https://github.com/EQEmu/Server/pull/4955)) @Kinglykrab 2025-06-26
|
||||
|
||||
### Databuckets
|
||||
|
||||
* Revert Caching Changes of #4917 ([#4957](https://github.com/EQEmu/Server/pull/4957)) @Akkadius 2025-06-28
|
||||
|
||||
### Fixes
|
||||
|
||||
* Fix FindCharacter Using content_db ([#4956](https://github.com/EQEmu/Server/pull/4956)) @Kinglykrab 2025-06-26
|
||||
* Fix Hero Forge on Character Select ([#4954](https://github.com/EQEmu/Server/pull/4954)) @Kinglykrab 2025-06-26
|
||||
|
||||
## [23.8.0] 6/25/2025
|
||||
|
||||
### API
|
||||
|
||||
* Add wwmarquee <type> <message> ([#4919](https://github.com/EQEmu/Server/pull/4919)) @Akkadius 2025-06-23
|
||||
|
||||
### Build
|
||||
|
||||
* Significantly Improve Build Times Using Unity Builds ([#4948](https://github.com/EQEmu/Server/pull/4948)) @Akkadius 2025-06-22
|
||||
|
||||
### Code
|
||||
|
||||
* AdventureManager Global to Singleton Cleanup ([#4931](https://github.com/EQEmu/Server/pull/4931)) @Kinglykrab 2025-06-25
|
||||
* Cleanup Strings Header ([#4950](https://github.com/EQEmu/Server/pull/4950)) @Akkadius 2025-06-22
|
||||
* ClientList Global to Singleton Cleanup ([#4942](https://github.com/EQEmu/Server/pull/4942)) @Kinglykrab 2025-06-25
|
||||
* DatabaseUpdate Global to Singleton Cleanup ([#4943](https://github.com/EQEmu/Server/pull/4943)) @Kinglykrab 2025-06-25
|
||||
* DiscordManager Global to Singleton Cleanup ([#4926](https://github.com/EQEmu/Server/pull/4926)) @Kinglykrab 2025-06-25
|
||||
* EQ::Random Global to Singleton Cleanup ([#4936](https://github.com/EQEmu/Server/pull/4936)) @Kinglykrab 2025-06-22
|
||||
* EQEmuLogSys Global to Singleton Cleanup ([#4925](https://github.com/EQEmu/Server/pull/4925)) @Akkadius 2025-06-25
|
||||
* EvolvingItemsManager Global to Singleton Cleanup ([#4929](https://github.com/EQEmu/Server/pull/4929)) @Kinglykrab 2025-06-25
|
||||
* LFGuildManager Global to Singleton Cleanup ([#4927](https://github.com/EQEmu/Server/pull/4927)) @Kinglykrab 2025-06-25
|
||||
* LoginServerList Global to Singleton Cleanup ([#4941](https://github.com/EQEmu/Server/pull/4941)) @Kinglykrab 2025-06-25
|
||||
* Optimize PCH Config (Faster Builds) ([#4951](https://github.com/EQEmu/Server/pull/4951)) @Akkadius 2025-06-22
|
||||
* PCH Cleanup ([#4952](https://github.com/EQEmu/Server/pull/4952)) @Akkadius 2025-06-25
|
||||
* PathManager Global to Singleton Cleanup ([#4924](https://github.com/EQEmu/Server/pull/4924)) @Akkadius 2025-06-22
|
||||
* PetitionList Global to Singleton Cleanup ([#4944](https://github.com/EQEmu/Server/pull/4944)) @Kinglykrab 2025-06-25
|
||||
* PlayerEventLogs Global to Singleton Cleanup ([#4928](https://github.com/EQEmu/Server/pull/4928)) @Kinglykrab 2025-06-25
|
||||
* QueryServConnection Global to Singleton Cleanup ([#4938](https://github.com/EQEmu/Server/pull/4938)) @Kinglykrab 2025-06-25
|
||||
* Remove Lua Rule Constants ([#4949](https://github.com/EQEmu/Server/pull/4949)) @Akkadius 2025-06-22
|
||||
* Remove Regex Compile Bloat ([#4947](https://github.com/EQEmu/Server/pull/4947)) @Akkadius 2025-06-22
|
||||
* Remove Unused MZoneShutdown Mutex ([#4946](https://github.com/EQEmu/Server/pull/4946)) @Kinglykrab 2025-06-22
|
||||
* SharedTaskManager Global to Singleton Cleanup ([#4930](https://github.com/EQEmu/Server/pull/4930)) @Kinglykrab 2025-06-25
|
||||
* SkillCaps Global to Singleton Cleanup ([#4933](https://github.com/EQEmu/Server/pull/4933)) @Kinglykrab 2025-06-22
|
||||
* TaskManager Global to Singleton Cleanup ([#4945](https://github.com/EQEmu/Server/pull/4945)) @Kinglykrab 2025-06-22
|
||||
* UCSConnection Global to Singleton Cleanup ([#4937](https://github.com/EQEmu/Server/pull/4937)) @Kinglykrab 2025-06-25
|
||||
* WebInterfaceList Global to Singleton Cleanup ([#4935](https://github.com/EQEmu/Server/pull/4935)) @Kinglykrab 2025-06-25
|
||||
* WorldContentServer Global to Singleton Cleanup ([#4939](https://github.com/EQEmu/Server/pull/4939)) @Kinglykrab 2025-06-25
|
||||
* WorldEventScheduler and ZoneEventScheduler Global to Singleton Cleanup ([#4932](https://github.com/EQEmu/Server/pull/4932)) @Kinglykrab 2025-06-25
|
||||
* ZSList Global to Singleton Cleanup ([#4940](https://github.com/EQEmu/Server/pull/4940)) @Kinglykrab 2025-06-25
|
||||
* ZoneStore Global to Singleton Cleanup ([#4934](https://github.com/EQEmu/Server/pull/4934)) @Kinglykrab 2025-06-23
|
||||
|
||||
### Corpses
|
||||
|
||||
* Add corpse entity variables to DB ([#4911](https://github.com/EQEmu/Server/pull/4911)) @fryguy503 2025-06-25
|
||||
|
||||
### Databuckets
|
||||
|
||||
* Move Databuckets to Common ([#4918](https://github.com/EQEmu/Server/pull/4918)) @Akkadius 2025-06-16
|
||||
* Nested Caching ([#4917](https://github.com/EQEmu/Server/pull/4917)) @Akkadius 2025-06-25
|
||||
|
||||
### Doors
|
||||
|
||||
* Fix door saving for versions ([#4905](https://github.com/EQEmu/Server/pull/4905)) @nytmyr 2025-06-09
|
||||
|
||||
### Fixes
|
||||
|
||||
* Bulk Send Corpses after Idle State ([#4910](https://github.com/EQEmu/Server/pull/4910)) @Akkadius 2025-06-09
|
||||
* Fix ClientList Singleton Shortcomings of #4942 @Akkadius 2025-06-25
|
||||
* Fix breaking changes to Titanium, SoF, SoD patches causes by big bags update ([#4922](https://github.com/EQEmu/Server/pull/4922)) @regneq 2025-06-25
|
||||
|
||||
### Logs
|
||||
|
||||
* Fix output for tasks in logs ([#4907](https://github.com/EQEmu/Server/pull/4907)) @joligario 2025-06-09
|
||||
|
||||
### Performance
|
||||
|
||||
* Auto Idle / AFK ([#4903](https://github.com/EQEmu/Server/pull/4903)) @Akkadius 2025-05-22
|
||||
* Wearchange Packet Send Deduplication ([#4916](https://github.com/EQEmu/Server/pull/4916)) @Akkadius 2025-06-25
|
||||
|
||||
### Player Event Logs
|
||||
|
||||
* Don't Clear Event Data on ETL Events ([#4913](https://github.com/EQEmu/Server/pull/4913)) @Akkadius 2025-06-25
|
||||
|
||||
### Player Events
|
||||
|
||||
* Don't Write Empty Data ([#4912](https://github.com/EQEmu/Server/pull/4912)) @Akkadius 2025-06-25
|
||||
* Zone Fetch Settings from QS if Enabled ([#4915](https://github.com/EQEmu/Server/pull/4915)) @Akkadius 2025-06-25
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add CompleteTask and UncompleteTask methods to Perl/Lua ([#4921](https://github.com/EQEmu/Server/pull/4921)) @Barathos 2025-06-25
|
||||
* Lua Client Scoped EnableTitleSets ([#4914](https://github.com/EQEmu/Server/pull/4914)) @fryguy503 2025-06-25
|
||||
|
||||
### Quests
|
||||
|
||||
* Support Multiple Quest, Plugin, and Lua Module Paths ([#4906](https://github.com/EQEmu/Server/pull/4906)) @Akkadius 2025-06-09
|
||||
|
||||
### World API
|
||||
|
||||
* Input Validation ([#4904](https://github.com/EQEmu/Server/pull/4904)) @Akkadius 2025-05-22
|
||||
|
||||
## [23.7.0] 5/19/2025
|
||||
|
||||
### CLI
|
||||
|
||||
* Add custom database version output ([#4901](https://github.com/EQEmu/Server/pull/4901)) @joligario 2025-05-18
|
||||
* Fix MySQL check in database dumper ([#4897](https://github.com/EQEmu/Server/pull/4897)) @joligario 2025-05-16
|
||||
|
||||
### Commands
|
||||
|
||||
* Add #zonevariable Command ([#4882](https://github.com/EQEmu/Server/pull/4882)) @Kinglykrab 2025-05-15
|
||||
|
||||
### Database
|
||||
|
||||
* Add Custom Database Migrations for Operators ([#4892](https://github.com/EQEmu/Server/pull/4892)) @Akkadius 2025-05-16
|
||||
* Remove Transaction Wrapped Character Save ([#4894](https://github.com/EQEmu/Server/pull/4894)) @Akkadius 2025-05-16
|
||||
|
||||
### Fixes
|
||||
|
||||
* Deadlock on failed #copycharacter commands ([#4887](https://github.com/EQEmu/Server/pull/4887)) @Akkadius 2025-05-16
|
||||
|
||||
### Logging
|
||||
|
||||
* Auto Update Log Category Names ([#4890](https://github.com/EQEmu/Server/pull/4890)) @Akkadius 2025-05-16
|
||||
|
||||
### Netcode
|
||||
|
||||
* Resend Logic Adjustments ([#4900](https://github.com/EQEmu/Server/pull/4900)) @Akkadius 2025-05-18
|
||||
|
||||
### Player Events
|
||||
|
||||
* Add rule to ignore configured GM commands ([#4888](https://github.com/EQEmu/Server/pull/4888)) @Akkadius 2025-05-16
|
||||
|
||||
### Rules
|
||||
|
||||
* Auto Update Rule Notes from Source ([#4891](https://github.com/EQEmu/Server/pull/4891)) @Akkadius 2025-05-16
|
||||
|
||||
### World
|
||||
|
||||
* Fix Rarer Reload Deadlock ([#4893](https://github.com/EQEmu/Server/pull/4893)) @Akkadius 2025-05-16
|
||||
|
||||
### Zone State
|
||||
|
||||
* Load New Spawn2 Data When Present ([#4889](https://github.com/EQEmu/Server/pull/4889)) @Akkadius 2025-05-16
|
||||
|
||||
## [23.6.0] 5/14/2025
|
||||
|
||||
### Bots
|
||||
|
||||
* Correct ^pull logic and add checks for Enchanter pets ([#4827](https://github.com/EQEmu/Server/pull/4827)) @nytmyr 2025-05-15
|
||||
* Fix creation limit, spawn limit, level requirement checks ([#4868](https://github.com/EQEmu/Server/pull/4868)) @nytmyr 2025-05-15
|
||||
* Move all spell_id instances to uint16 ([#4876](https://github.com/EQEmu/Server/pull/4876)) @nytmyr 2025-05-15
|
||||
* Prevent non-taunters from potentially fleeing mob on TargetReflection ([#4859](https://github.com/EQEmu/Server/pull/4859)) @nytmyr 2025-04-28
|
||||
|
||||
### CLI
|
||||
|
||||
* ETL Settings Output ([#4873](https://github.com/EQEmu/Server/pull/4873)) @joligario 2025-05-15
|
||||
|
||||
### Code
|
||||
|
||||
* Fix typo in QueryNameAvailablity ([#4869](https://github.com/EQEmu/Server/pull/4869)) @nytmyr 2025-04-28
|
||||
|
||||
### Crash
|
||||
|
||||
* Fix crash bug with pbae and quest scripts spawning mobs ([#4884](https://github.com/EQEmu/Server/pull/4884)) @carolus21rex 2025-05-15
|
||||
|
||||
### Feature
|
||||
|
||||
* Add Character:TradeskillUpMinChance rule ([#4867](https://github.com/EQEmu/Server/pull/4867)) @zrix-eq 2025-05-15
|
||||
* Enable spawn attribute for NPCTintID ([#4871](https://github.com/EQEmu/Server/pull/4871)) @neckkola 2025-05-15
|
||||
|
||||
### Fixes
|
||||
|
||||
* Add trader/buyer cleanup actions ([#4843](https://github.com/EQEmu/Server/pull/4843)) @neckkola 2025-05-15
|
||||
* Fix #copycharacter command ([#4860](https://github.com/EQEmu/Server/pull/4860)) @nytmyr 2025-04-28
|
||||
* Fix Crash with #task ([#4874](https://github.com/EQEmu/Server/pull/4874)) @Kinglykrab 2025-04-30
|
||||
* Fix Object Name Init, User Refs, and Client Sync on Close ([#4861](https://github.com/EQEmu/Server/pull/4861)) @zimp-wow 2025-05-15
|
||||
* Fix breaking change to UF patches caused by Big Bags update ([#4883](https://github.com/EQEmu/Server/pull/4883)) @hbingram 2025-05-15
|
||||
* Prevent Ranged Attack from being triggered at arbitrary rate ([#4879](https://github.com/EQEmu/Server/pull/4879)) @catapultam-habeo 2025-05-15
|
||||
|
||||
### Performance
|
||||
|
||||
* Store Player Title Sets in Client Memory ([#4836](https://github.com/EQEmu/Server/pull/4836)) @Kinglykrab 2025-05-15
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add Last Login and First Login Flags to EVENT_CONNECT ([#4866](https://github.com/EQEmu/Server/pull/4866)) @Kinglykrab 2025-05-15
|
||||
|
||||
## [23.5.0] 4/10/2025
|
||||
|
||||
### API
|
||||
|
||||
* World API Optimizations ([#4850](https://github.com/EQEmu/Server/pull/4850)) @Akkadius 2025-04-10
|
||||
|
||||
### Bots
|
||||
|
||||
* Add valid state checks to ^clickitem ([#4830](https://github.com/EQEmu/Server/pull/4830)) @nytmyr 2025-04-10
|
||||
* Flag all buffs with SE_DamageShield as Damage Shield ([#4833](https://github.com/EQEmu/Server/pull/4833)) @nytmyr 2025-04-10
|
||||
* Positioning rewrite ([#4856](https://github.com/EQEmu/Server/pull/4856)) @nytmyr 2025-04-10
|
||||
* Restore old buff overwrite blocking ([#4832](https://github.com/EQEmu/Server/pull/4832)) @nytmyr 2025-04-10
|
||||
|
||||
### Bugfix
|
||||
|
||||
* Load zone variables before encounter_load. ([#4846](https://github.com/EQEmu/Server/pull/4846)) @zimp-wow 2025-04-10
|
||||
* Prevent depops from blocking new spawns. ([#4841](https://github.com/EQEmu/Server/pull/4841)) @zimp-wow 2025-04-10
|
||||
* Prevent final shutdown from persisting incomplete state. ([#4849](https://github.com/EQEmu/Server/pull/4849)) @zimp-wow 2025-04-10
|
||||
|
||||
### Code
|
||||
|
||||
* Remove queryserv dump flag ([#4842](https://github.com/EQEmu/Server/pull/4842)) @joligario 2025-04-10
|
||||
* Update link for legacy EQEmu loginserver account setup ([#4826](https://github.com/EQEmu/Server/pull/4826)) @joligario 2025-04-10
|
||||
|
||||
### Crash
|
||||
|
||||
* Fix rarer exception crash issue in PlayerEventLogs::ProcessBatchQueue ([#4835](https://github.com/EQEmu/Server/pull/4835)) @Akkadius 2025-04-03
|
||||
|
||||
### Database
|
||||
|
||||
* Fix manifest for `helmtexture` in `horses` table ([#4852](https://github.com/EQEmu/Server/pull/4852)) @joligario 2025-04-10
|
||||
|
||||
### Feature
|
||||
|
||||
* Add rule to consume command text from any channel ([#4839](https://github.com/EQEmu/Server/pull/4839)) @catapultam-habeo 2025-04-10
|
||||
|
||||
### Fixes
|
||||
|
||||
* Add the bazaar search limit to query ([#4829](https://github.com/EQEmu/Server/pull/4829)) @neckkola 2025-04-10
|
||||
* Backfill expire_at (not sure why this didn't make it in there to begin with) @Akkadius 2025-03-31
|
||||
* Bazaar Search window not working in a DZ ([#4828](https://github.com/EQEmu/Server/pull/4828)) @neckkola 2025-04-10
|
||||
* Databuckets Account Cache Loading ([#4855](https://github.com/EQEmu/Server/pull/4855)) @Akkadius 2025-04-10
|
||||
* Fix missing timer_name check on Mob::StopTimer ([#4840](https://github.com/EQEmu/Server/pull/4840)) @zimp-wow 2025-04-04
|
||||
* FixHeading Infinite Loop Fix ([#4854](https://github.com/EQEmu/Server/pull/4854)) @KimLS 2025-04-10
|
||||
* Make sure we don't expire default value instances @Akkadius 2025-03-31
|
||||
* Regression in World SendEmoteMessageRaw ([#4837](https://github.com/EQEmu/Server/pull/4837)) @Akkadius 2025-04-03
|
||||
* Remove QS Tables From Export @Akkadius 2025-04-10
|
||||
* Zone State Spawn2 Location Restore ([#4844](https://github.com/EQEmu/Server/pull/4844)) @Akkadius 2025-04-10
|
||||
|
||||
### Netcode
|
||||
|
||||
* Fix Stale Client Edge Case ([#4853](https://github.com/EQEmu/Server/pull/4853)) @Akkadius 2025-04-10
|
||||
|
||||
### Performance
|
||||
|
||||
* Character Save Optimizations ([#4851](https://github.com/EQEmu/Server/pull/4851)) @Akkadius 2025-04-10
|
||||
* Network Ring Buffers ([#4857](https://github.com/EQEmu/Server/pull/4857)) @Akkadius 2025-04-10
|
||||
* Pre-Compute CLE Server Lists ([#4838](https://github.com/EQEmu/Server/pull/4838)) @Akkadius 2025-04-10
|
||||
|
||||
### Spells
|
||||
|
||||
* Fear resistance effects edge case fixes and support for SPA 102 as an AA ([#4848](https://github.com/EQEmu/Server/pull/4848)) @KayenEQ 2025-04-10
|
||||
* Update to SPA 180 SE_ResistSpellChance to not block unresistable spells. ([#4847](https://github.com/EQEmu/Server/pull/4847)) @KayenEQ 2025-04-10
|
||||
* Update to SPA 378 SE_SpellEffectResistChance ([#4845](https://github.com/EQEmu/Server/pull/4845)) @KayenEQ 2025-04-10
|
||||
|
||||
## [23.4.0] 3/30/2025
|
||||
|
||||
### API
|
||||
|
||||
* Expose Zoneserver Compile Metadata ([#4815](https://github.com/EQEmu/Server/pull/4815)) @Akkadius 2025-03-29
|
||||
|
||||
### Bots
|
||||
|
||||
* Charmed Pets were breaking Mob respawns ([#4780](https://github.com/EQEmu/Server/pull/4780)) @nytmyr 2025-03-16
|
||||
* Enraged positioning ([#4789](https://github.com/EQEmu/Server/pull/4789)) @nytmyr 2025-03-29
|
||||
* Fix IsValidSpellTypeBySpellID to account for all types ([#4764](https://github.com/EQEmu/Server/pull/4764)) @nytmyr 2025-03-19
|
||||
* Fix Rule ZonesWithSpawnLimits/ZonesWithForcedSpawnLimits errors ([#4791](https://github.com/EQEmu/Server/pull/4791)) @nytmyr 2025-03-29
|
||||
* Fix rule Bots:FinishBuffing ([#4788](https://github.com/EQEmu/Server/pull/4788)) @nytmyr 2025-03-29
|
||||
* Line of Sight and Mez optimizations and cleanup ([#4746](https://github.com/EQEmu/Server/pull/4746)) @nytmyr 2025-03-29
|
||||
* Prevent bot pets from despawning on #repop ([#4790](https://github.com/EQEmu/Server/pull/4790)) @nytmyr 2025-03-29
|
||||
|
||||
### Code
|
||||
|
||||
* Control flow defaults missed in recent bot updates ([#4817](https://github.com/EQEmu/Server/pull/4817)) @joligario 2025-03-30
|
||||
* Remove Extraneous Time Type in ShowZoneData ([#4806](https://github.com/EQEmu/Server/pull/4806)) @Kinglykrab 2025-03-29
|
||||
* Remove Unused Command Methods ([#4805](https://github.com/EQEmu/Server/pull/4805)) @Kinglykrab 2025-03-29
|
||||
* UCS Member Count ([#4819](https://github.com/EQEmu/Server/pull/4819)) @joligario 2025-03-30
|
||||
|
||||
### Commands
|
||||
|
||||
* Add #show zone_variables ([#4812](https://github.com/EQEmu/Server/pull/4812)) @Akkadius 2025-03-29
|
||||
* Add Instance Support to #zoneshutdown ([#4807](https://github.com/EQEmu/Server/pull/4807)) @Kinglykrab 2025-03-29
|
||||
|
||||
### Crash
|
||||
|
||||
* Fix Rarer World Crash with Player Event Thread Processor ([#4800](https://github.com/EQEmu/Server/pull/4800)) @Akkadius 2025-03-29
|
||||
* Fix Repop Race Condition Crash ([#4814](https://github.com/EQEmu/Server/pull/4814)) @Akkadius 2025-03-29
|
||||
|
||||
### Database
|
||||
|
||||
* Fix Respawn Times Table ([#4802](https://github.com/EQEmu/Server/pull/4802)) @Akkadius 2025-03-29
|
||||
* Wrap PurgeExpiredInstances in a Transaction ([#4824](https://github.com/EQEmu/Server/pull/4824)) @Akkadius 2025-03-30
|
||||
|
||||
### Feature
|
||||
|
||||
* Implement /changename & related script bindings. Clean up #set name ([#4770](https://github.com/EQEmu/Server/pull/4770)) @catapultam-habeo 2025-03-20
|
||||
|
||||
### Fixes
|
||||
|
||||
* AllowFVNoDrop Flag trades ([#4809](https://github.com/EQEmu/Server/pull/4809)) @neckkola 2025-03-27
|
||||
* Fix Instance Creation Race Condition ([#4803](https://github.com/EQEmu/Server/pull/4803)) @Akkadius 2025-03-29
|
||||
* Fix zone crash when attempting to add a disappearing client to hate list. ([#4782](https://github.com/EQEmu/Server/pull/4782)) @zimp-wow 2025-03-19
|
||||
* Globally Reloading Quests when not loaded ([#4813](https://github.com/EQEmu/Server/pull/4813)) @Akkadius 2025-03-29
|
||||
* Instance DZ Creation ([#4823](https://github.com/EQEmu/Server/pull/4823)) @Akkadius 2025-03-30
|
||||
* Zone State Entity Variable Load Pre-Spawn ([#4785](https://github.com/EQEmu/Server/pull/4785)) @Akkadius 2025-03-19
|
||||
* Zone State Position Fix ([#4784](https://github.com/EQEmu/Server/pull/4784)) @Akkadius 2025-03-19
|
||||
* Zone State Variables Load First ([#4798](https://github.com/EQEmu/Server/pull/4798)) @Akkadius 2025-03-29
|
||||
* Zone state edge case with 0 hp ([#4787](https://github.com/EQEmu/Server/pull/4787)) @Akkadius 2025-03-29
|
||||
|
||||
### Instance
|
||||
|
||||
* Clear Respawn Timers on Creation ([#4801](https://github.com/EQEmu/Server/pull/4801)) @Akkadius 2025-03-29
|
||||
|
||||
### Instances
|
||||
|
||||
* Add `expire_at` Column ([#4820](https://github.com/EQEmu/Server/pull/4820)) @Akkadius 2025-03-30
|
||||
|
||||
### Performance
|
||||
|
||||
* Add several database indexes ([#4811](https://github.com/EQEmu/Server/pull/4811)) @Akkadius 2025-03-29
|
||||
* Have World Send Smarter Guild Updates ([#4796](https://github.com/EQEmu/Server/pull/4796)) @Akkadius 2025-03-29
|
||||
* Improve Character Select DB Performance ([#4799](https://github.com/EQEmu/Server/pull/4799)) @Akkadius 2025-03-29
|
||||
* Reduce Adventure S2S chatter ([#4793](https://github.com/EQEmu/Server/pull/4793)) @Akkadius 2025-03-29
|
||||
* Reduce CorpseOwnerOnline S2S Chatter to World ([#4795](https://github.com/EQEmu/Server/pull/4795)) @Akkadius 2025-03-29
|
||||
* Reduce LFGuild Chatter ([#4794](https://github.com/EQEmu/Server/pull/4794)) @Akkadius 2025-03-29
|
||||
* Reduce UpdateWho S2S Chatter to World ([#4792](https://github.com/EQEmu/Server/pull/4792)) @Akkadius 2025-03-29
|
||||
* Send Smarter Emote Packets ([#4818](https://github.com/EQEmu/Server/pull/4818)) @Akkadius 2025-03-30
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add Support for NPC ID and NPC Name Specificity ([#4781](https://github.com/EQEmu/Server/pull/4781)) @Kinglykrab 2025-03-19
|
||||
|
||||
### Reload
|
||||
|
||||
* Add Reload for Maps / Navs ([#4816](https://github.com/EQEmu/Server/pull/4816)) @Akkadius 2025-03-29
|
||||
|
||||
### Zone
|
||||
|
||||
* Zone State Automated Testing and Improvements ([#4808](https://github.com/EQEmu/Server/pull/4808)) @Akkadius 2025-03-30
|
||||
* Zone State Improvements Part 3 ([#4773](https://github.com/EQEmu/Server/pull/4773)) @Akkadius 2025-03-13
|
||||
|
||||
## [23.3.4] 3/14/2025
|
||||
|
||||
### Fixes
|
||||
|
||||
* Add check for simultaneous direct vendor and parcel Trader/Buyer Purchase ([#4778](https://github.com/EQEmu/Server/pull/4778)) @neckkola 2025-03-14
|
||||
* Fix for rare circumstance where NPC's would have 0 health on restore @Akkadius
|
||||
|
||||
## [23.3.3] 3/13/2025
|
||||
|
||||
### Database
|
||||
|
||||
* Add indexes for data_buckets and zone_state_spawns ([#4771](https://github.com/EQEmu/Server/pull/4771)) @Akkadius 2025-03-11
|
||||
|
||||
### Fixes
|
||||
|
||||
* Update GuildBank to correctly handle items with charges equal to zero ([#4774](https://github.com/EQEmu/Server/pull/4774)) @neckkola 2025-03-13
|
||||
|
||||
### Networking
|
||||
|
||||
* Fix "port in use" error ([#4772](https://github.com/EQEmu/Server/pull/4772)) @Akkadius 2025-03-12
|
||||
|
||||
### Zone
|
||||
|
||||
* Zone State Improvements Part 3 ([#4773](https://github.com/EQEmu/Server/pull/4773)) @Akkadius 2025-03-13
|
||||
|
||||
## [23.3.2] 3/11/2025
|
||||
|
||||
### DynamicZones
|
||||
|
||||
* Bulk request dz member statuses on zone boot ([#4769](https://github.com/EQEmu/Server/pull/4769)) @hgtw 2025-03-11
|
||||
|
||||
### Zone
|
||||
|
||||
* Zone State Improvements (Continued) ([#4768](https://github.com/EQEmu/Server/pull/4768)) @Akkadius 2025-03-11
|
||||
|
||||
## [23.3.0] 3/8/2025
|
||||
|
||||
### Bots
|
||||
|
||||
* Fix buffs not overwriting lesser buffs ([#4756](https://github.com/EQEmu/Server/pull/4756)) @nytmyr 2025-03-06
|
||||
* Fix taunting bots positioning ([#4754](https://github.com/EQEmu/Server/pull/4754)) @nytmyr 2025-03-06
|
||||
* Move commanded spell map to zone ([#4755](https://github.com/EQEmu/Server/pull/4755)) @nytmyr 2025-03-06
|
||||
|
||||
### Code
|
||||
|
||||
* Fix typo in GM tradeskill combine message ([#4762](https://github.com/EQEmu/Server/pull/4762)) @nytmyr 2025-03-08
|
||||
|
||||
### Crash
|
||||
|
||||
* Bot aura crash fix ([#4752](https://github.com/EQEmu/Server/pull/4752)) @nytmyr 2025-03-06
|
||||
|
||||
### Databuckets
|
||||
|
||||
* Nested Databuckets Protections and Improvements ([#4748](https://github.com/EQEmu/Server/pull/4748)) @Akkadius 2025-03-04
|
||||
|
||||
### Feature
|
||||
|
||||
* Add Rule for dealing with augments when an item evolves ([#4758](https://github.com/EQEmu/Server/pull/4758)) @neckkola 2025-03-08
|
||||
* Allow assigning Helm Texture independently of Body Texture for Horses ([#4759](https://github.com/EQEmu/Server/pull/4759)) @catapultam-habeo 2025-03-08
|
||||
|
||||
### Fixes
|
||||
|
||||
* Add crash checks for certain PlayerEventLogs ([#4761](https://github.com/EQEmu/Server/pull/4761)) @neckkola 2025-03-07
|
||||
* Correct incorrectly calculated stat caps with Heroic Stats ([#4760](https://github.com/EQEmu/Server/pull/4760)) @catapultam-habeo 2025-03-08
|
||||
* Fix sigabort crash from invalid JSON @Akkadius 2025-03-03
|
||||
* Forgot to push up some changes for test output @Akkadius 2025-03-04
|
||||
* Parcel Delivery Updates for two edge cases ([#4753](https://github.com/EQEmu/Server/pull/4753)) @neckkola 2025-03-06
|
||||
* Remove one port check in world @Akkadius 2025-03-03
|
||||
* Zero out currentnpcid whenever spawn is reset. ([#4763](https://github.com/EQEmu/Server/pull/4763)) @zimp-wow 2025-03-08
|
||||
|
||||
### Logging
|
||||
|
||||
* Convert JSON Error to Data Buckets Logging Category ([#4747](https://github.com/EQEmu/Server/pull/4747)) @Kinglykrab 2025-03-04
|
||||
|
||||
### Pets
|
||||
|
||||
* Fix renamed pets loading as blank names ([#4751](https://github.com/EQEmu/Server/pull/4751)) @nytmyr 2025-03-05
|
||||
|
||||
### Rules
|
||||
|
||||
* Fix EvolvingItems:PercentOfRaidExperience Description ([#4757](https://github.com/EQEmu/Server/pull/4757)) @Kinglykrab 2025-03-07
|
||||
|
||||
### Tests
|
||||
|
||||
* Cleanup Hand-in Tests ([#4749](https://github.com/EQEmu/Server/pull/4749)) @Akkadius 2025-03-04
|
||||
|
||||
### Zone
|
||||
|
||||
* Make zone controller less likely to be visible, immune to all forms of combat ([#4750](https://github.com/EQEmu/Server/pull/4750)) @Akkadius 2025-03-06
|
||||
* State Save Improvements ([#4765](https://github.com/EQEmu/Server/pull/4765)) @Akkadius 2025-03-08
|
||||
|
||||
## [23.2.0] 3/3/2025
|
||||
|
||||
### Crash
|
||||
|
||||
* Database SetMutex crash fix ([#4741](https://github.com/EQEmu/Server/pull/4741)) @Akkadius 2025-03-03
|
||||
* Fix Aura process crash with bots ([#4743](https://github.com/EQEmu/Server/pull/4743)) @Akkadius 2025-03-03
|
||||
* Fix crash in add loot code path ([#4745](https://github.com/EQEmu/Server/pull/4745)) @Akkadius 2025-03-03
|
||||
* Fix world repop crash ([#4742](https://github.com/EQEmu/Server/pull/4742)) @Akkadius 2025-03-03
|
||||
* Potential crash fix in scan close mobs ([#4744](https://github.com/EQEmu/Server/pull/4744)) @Akkadius 2025-03-03
|
||||
|
||||
### Fixes
|
||||
|
||||
* Cleanup zone buckets on instance purge. ([#4739](https://github.com/EQEmu/Server/pull/4739)) @zimp-wow 2025-03-02
|
||||
* Fix an error causing Endurance Regen to not be applied by items. ([#4738](https://github.com/EQEmu/Server/pull/4738)) @catapultam-habeo 2025-03-02
|
||||
|
||||
### World
|
||||
|
||||
* Check if port in use to avoid double booting mistakes ([#4740](https://github.com/EQEmu/Server/pull/4740)) @Akkadius 2025-03-03
|
||||
|
||||
## [23.1.0] 3/1/2025
|
||||
|
||||
### Bots
|
||||
|
||||
* Fix unresponsive bots in groups upon group wipe ([#4712](https://github.com/EQEmu/Server/pull/4712)) @nytmyr 2025-02-28
|
||||
|
||||
### Code
|
||||
|
||||
* More login <-> world code cleanup ([#4724](https://github.com/EQEmu/Server/pull/4724)) @Akkadius 2025-02-28
|
||||
|
||||
### Crash
|
||||
|
||||
* Check for directory existence before traversing in CheckForCompatibleQuestPlugins ([#4730](https://github.com/EQEmu/Server/pull/4730)) @Akkadius 2025-03-02
|
||||
* Fix filesystem crash / exception in DatabaseDumpService::RemoveCredentialsFile() ([#4731](https://github.com/EQEmu/Server/pull/4731)) @Akkadius 2025-03-01
|
||||
* Fix large file size crash in File::GetContents for windows ([#4735](https://github.com/EQEmu/Server/pull/4735)) @Akkadius 2025-03-02
|
||||
* Fix reload concurrency crash when ran from Spire ([#4733](https://github.com/EQEmu/Server/pull/4733)) @Akkadius 2025-03-02
|
||||
* Validate item in SE_SummonItemIntoBag ([#4734](https://github.com/EQEmu/Server/pull/4734)) @Akkadius 2025-03-02
|
||||
* World CLI validation ([#4728](https://github.com/EQEmu/Server/pull/4728)) @Akkadius 2025-03-01
|
||||
|
||||
### Database
|
||||
|
||||
* Remove force_interactive from big bag updates ([#4727](https://github.com/EQEmu/Server/pull/4727)) @Akkadius 2025-03-01
|
||||
|
||||
### Feature
|
||||
|
||||
* Add a rule for spells to bypass stacking rules ([#4716](https://github.com/EQEmu/Server/pull/4716)) @catapultam-habeo 2025-02-28
|
||||
* Evolving items Additions ([#4725](https://github.com/EQEmu/Server/pull/4725)) @neckkola 2025-03-01
|
||||
|
||||
### Fixes
|
||||
|
||||
* Add character_pet_name to player tables schema @Akkadius 2025-03-02
|
||||
* Add client packets to questmanager:setguild ([#4732](https://github.com/EQEmu/Server/pull/4732)) @neckkola 2025-03-01
|
||||
* Clear m_completed_shared_tasks before reloading @Akkadius 2025-02-24
|
||||
* Fix AA Reset Error Message ([#4720](https://github.com/EQEmu/Server/pull/4720)) @Kinglykrab 2025-02-28
|
||||
* Fix Issue with Suffixes/Prefixes ([#4723](https://github.com/EQEmu/Server/pull/4723)) @Kinglykrab 2025-02-28
|
||||
* Fix Trading Items to Bot Pets ([#4721](https://github.com/EQEmu/Server/pull/4721)) @MortimerGreenwald 2025-02-28
|
||||
* Refactor ApplyItemBonuses to fix double-counting of ATK and recommended levels not correctly applying ([#4713](https://github.com/EQEmu/Server/pull/4713)) @catapultam-habeo 2025-03-01
|
||||
|
||||
### Loginserver
|
||||
|
||||
* Minor cleanup ([#4729](https://github.com/EQEmu/Server/pull/4729)) @Akkadius 2025-03-01
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add Key Ring Methods to Perl and Lua ([#4719](https://github.com/EQEmu/Server/pull/4719)) @Kinglykrab 2025-02-28
|
||||
* Implement eq.handin() and quest::handin() ([#4718](https://github.com/EQEmu/Server/pull/4718)) @Akkadius 2025-02-28
|
||||
|
||||
### Tasks
|
||||
|
||||
* Extend IsTaskCompleted to also be aware of shared task completion ([#4714](https://github.com/EQEmu/Server/pull/4714)) @Akkadius 2025-02-24
|
||||
|
||||
### Zone
|
||||
|
||||
* Implement Zone State Saving on Shutdown ([#4715](https://github.com/EQEmu/Server/pull/4715)) @Akkadius 2025-02-28
|
||||
|
||||
### Zone State
|
||||
|
||||
* Wrap all serialization/deserialization in try/catch ([#4726](https://github.com/EQEmu/Server/pull/4726)) @Akkadius 2025-03-01
|
||||
|
||||
## [23.0.2] 2/21/2025
|
||||
|
||||
### Bots
|
||||
|
||||
* Add checks to ensure bots and pets do not engage on ^pull ([#4708](https://github.com/EQEmu/Server/pull/4708)) @nytmyr 2025-02-22
|
||||
* Improve positioning ([#4709](https://github.com/EQEmu/Server/pull/4709)) @nytmyr 2025-02-22
|
||||
* Prevent medding in combat if any mob has bot targeted ([#4707](https://github.com/EQEmu/Server/pull/4707)) @nytmyr 2025-02-22
|
||||
|
||||
### Client Mod
|
||||
|
||||
* Adds a hacked fast camp rule for GMs ([#4697](https://github.com/EQEmu/Server/pull/4697)) @KimLS 2025-02-20
|
||||
|
||||
### Fixes
|
||||
|
||||
* Fix Lua Zone ID Exports ([#4700](https://github.com/EQEmu/Server/pull/4700)) @Kinglykrab 2025-02-22
|
||||
* Fix bad Mob reference in QuestManager::resumetimer() ([#4710](https://github.com/EQEmu/Server/pull/4710)) @zimp-wow 2025-02-22
|
||||
* Fix cursor load on zone ([#4704](https://github.com/EQEmu/Server/pull/4704)) @nytmyr 2025-02-22
|
||||
* Fix infinite loop in QuestManager::stoptimer() ([#4703](https://github.com/EQEmu/Server/pull/4703)) @zimp-wow 2025-02-21
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add GetSpawn() to Perl and Lua ([#4702](https://github.com/EQEmu/Server/pull/4702)) @Kinglykrab 2025-02-22
|
||||
|
||||
## [23.0.1] 2/20/2025
|
||||
|
||||
### Fixes
|
||||
|
||||
* Player event ordering merge fix ([#4699](https://github.com/EQEmu/Server/pull/4699)) @Akkadius 2025-02-20
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add DisableRespawnTimers to Perl and Lua ([#4691](https://github.com/EQEmu/Server/pull/4691)) @Kinglykrab 2025-02-20
|
||||
|
||||
## [23.0.0] 2/19/2025
|
||||
|
||||
### Bots
|
||||
|
||||
* Add AEHateLine to HateLine ParentType ([#4678](https://github.com/EQEmu/Server/pull/4678)) @nytmyr 2025-02-15
|
||||
* Add IsInRaidOrGroup checks to ^attack and ^pull ([#4654](https://github.com/EQEmu/Server/pull/4654)) @nytmyr 2025-02-07
|
||||
* Add missing stance options ([#4681](https://github.com/EQEmu/Server/pull/4681)) @nytmyr 2025-02-15
|
||||
* Bot Overhaul ([#4580](https://github.com/EQEmu/Server/pull/4580)) @nytmyr 2025-02-03
|
||||
* Command Cleanup ([#4676](https://github.com/EQEmu/Server/pull/4676)) @nytmyr 2025-02-15
|
||||
* Correct camp count on ^camp ([#4650](https://github.com/EQEmu/Server/pull/4650)) @nytmyr 2025-02-06
|
||||
* Correct helper message for forced casts ([#4656](https://github.com/EQEmu/Server/pull/4656)) @nytmyr 2025-02-07
|
||||
* Crash fixes related to GetNumberNeedingHealedInGroup ([#4684](https://github.com/EQEmu/Server/pull/4684)) @nytmyr 2025-02-15
|
||||
* Fix AE range calculation ([#4683](https://github.com/EQEmu/Server/pull/4683)) @nytmyr 2025-02-15
|
||||
* Fix Bards not casting ([#4638](https://github.com/EQEmu/Server/pull/4638)) @nytmyr 2025-02-03
|
||||
* Fix a couple potential crashes with GetNumberNeedingHealedInGroup ([#4652](https://github.com/EQEmu/Server/pull/4652)) @nytmyr 2025-02-07
|
||||
* Fix crash related to GetTempSpellType() ([#4649](https://github.com/EQEmu/Server/pull/4649)) @nytmyr 2025-02-06
|
||||
* Fix pets causing aggro ([#4677](https://github.com/EQEmu/Server/pull/4677)) @nytmyr 2025-02-15
|
||||
* Fix spell priority commands ([#4660](https://github.com/EQEmu/Server/pull/4660)) @nytmyr 2025-02-08
|
||||
* Fix typo in positioning ([#4659](https://github.com/EQEmu/Server/pull/4659)) @nytmyr 2025-02-08
|
||||
* Move BotGetSpellsByType to cache ([#4655](https://github.com/EQEmu/Server/pull/4655)) @nytmyr 2025-02-07
|
||||
* Prevents casting on ineligible targets due to target type, stacking, etc. ([#4680](https://github.com/EQEmu/Server/pull/4680)) @nytmyr 2025-02-15
|
||||
* Sanity checks for spell type updates ([#4641](https://github.com/EQEmu/Server/pull/4641)) @nytmyr 2025-02-05
|
||||
|
||||
### Bug
|
||||
|
||||
* Item Purchase Offset when multiple buyers are buying at the same time. ([#4628](https://github.com/EQEmu/Server/pull/4628)) @fryguy503 2025-02-06
|
||||
|
||||
### CI
|
||||
|
||||
* Fix database race condition ([#4646](https://github.com/EQEmu/Server/pull/4646)) @Akkadius 2025-02-06
|
||||
|
||||
### Client Mod
|
||||
|
||||
* Adds a hacked fast camp rule for GMs ([#4697](https://github.com/EQEmu/Server/pull/4697)) @KimLS 2025-02-20
|
||||
|
||||
### Code
|
||||
|
||||
* Bot RaidGroupSay ([#4653](https://github.com/EQEmu/Server/pull/4653)) @nytmyr 2025-02-07
|
||||
* Cleanup logic in cursor bag check ([#4642](https://github.com/EQEmu/Server/pull/4642)) @nytmyr 2025-02-04
|
||||
* Use Repositories for Titles ([#4608](https://github.com/EQEmu/Server/pull/4608)) @Kinglykrab 2025-02-07
|
||||
|
||||
### Commands
|
||||
|
||||
* Fix #goto not accepting proper heading ([#4685](https://github.com/EQEmu/Server/pull/4685)) @nytmyr 2025-02-15
|
||||
* Fix Illusion Block ([#4666](https://github.com/EQEmu/Server/pull/4666)) @nytmyr 2025-02-12
|
||||
|
||||
### Crash
|
||||
|
||||
* Fix raid/group crash regression ([#4671](https://github.com/EQEmu/Server/pull/4671)) @Akkadius 2025-02-12
|
||||
* Fix zone crash caused by NPC::MoveTo ([#4639](https://github.com/EQEmu/Server/pull/4639)) @catapultam-habeo 2025-02-03
|
||||
|
||||
### Databuckets
|
||||
|
||||
* Add Zone Scoped Databuckets ([#4690](https://github.com/EQEmu/Server/pull/4690)) @Akkadius 2025-02-18
|
||||
|
||||
### Expeditions
|
||||
|
||||
* Move expedition code into DynamicZone ([#4672](https://github.com/EQEmu/Server/pull/4672)) @hgtw 2025-02-16
|
||||
|
||||
### Feature
|
||||
|
||||
* Add Support for Tradeskill Recipe Inspect ([#4648](https://github.com/EQEmu/Server/pull/4648)) @Kinglykrab 2025-02-06
|
||||
* Add rule to allow /changepetname to function without being enabled by scripts. @catapultam-habeo 2025-02-05
|
||||
* GuildBank Updates ([#4674](https://github.com/EQEmu/Server/pull/4674)) @neckkola 2025-02-15
|
||||
* Implement Big Bags ([#4606](https://github.com/EQEmu/Server/pull/4606)) @Kinglykrab 2025-02-03
|
||||
|
||||
### Fixes
|
||||
|
||||
* #rq and #reload quest alias ([#4694](https://github.com/EQEmu/Server/pull/4694)) @Akkadius 2025-02-18
|
||||
* Always spawn zone controller first ([#4669](https://github.com/EQEmu/Server/pull/4669)) @Akkadius 2025-02-12
|
||||
* Big Bag Cleanup ([#4643](https://github.com/EQEmu/Server/pull/4643)) @fryguy503 2025-02-05
|
||||
* Big Bag additional fixes ([#4644](https://github.com/EQEmu/Server/pull/4644)) @fryguy503 2025-02-05
|
||||
* Change logging level for no items found in a bazaar search to reduce spam logs. ([#4675](https://github.com/EQEmu/Server/pull/4675)) @neckkola 2025-02-13
|
||||
* Find Zone - Expansion Settings ([#4692](https://github.com/EQEmu/Server/pull/4692)) @MortimerGreenwald 2025-02-18
|
||||
* Fix Beastlord Warder Size Modifier ([#4665](https://github.com/EQEmu/Server/pull/4665)) @Kinglykrab 2025-02-12
|
||||
* Fix CI since hand-ins are merged @Akkadius 2025-02-03
|
||||
* Fix Illusion Fade Texture Bug ([#4673](https://github.com/EQEmu/Server/pull/4673)) @Kinglykrab 2025-02-14
|
||||
* Fix Item Discovery ([#4663](https://github.com/EQEmu/Server/pull/4663)) @Kinglykrab 2025-02-10
|
||||
* Fix ST_GroupNoPets and ST_GroupClientAndPet ([#4667](https://github.com/EQEmu/Server/pull/4667)) @nytmyr 2025-02-10
|
||||
* Fix SendStatsWindow Mod2 Value Display ([#4658](https://github.com/EQEmu/Server/pull/4658)) @Kinglykrab 2025-02-07
|
||||
* Fix Tradeskill Queries ([#4661](https://github.com/EQEmu/Server/pull/4661)) @Kinglykrab 2025-02-09
|
||||
* Fix error in update manifest ([#4637](https://github.com/EQEmu/Server/pull/4637)) @nytmyr 2025-02-03
|
||||
* Fix issue with getting an unset nested databucket ([#4693](https://github.com/EQEmu/Server/pull/4693)) @Akkadius 2025-02-19
|
||||
* Fix non-error in player_event_logs ([#4695](https://github.com/EQEmu/Server/pull/4695)) @Akkadius 2025-02-18
|
||||
* GMMove Update Edge Case With Clients ([#4686](https://github.com/EQEmu/Server/pull/4686)) @Akkadius 2025-02-15
|
||||
* Item Handins to Pets ([#4687](https://github.com/EQEmu/Server/pull/4687)) @Akkadius 2025-02-15
|
||||
* Parcel Delivery Updates ([#4688](https://github.com/EQEmu/Server/pull/4688)) @neckkola 2025-02-16
|
||||
* Prevent zone from loading ETL ID's on bootup ([#4696](https://github.com/EQEmu/Server/pull/4696)) @Akkadius 2025-02-18
|
||||
* Update pre big bag corpse slot_id's to support big bags ([#4679](https://github.com/EQEmu/Server/pull/4679)) @nytmyr 2025-02-15
|
||||
|
||||
### Inventory
|
||||
|
||||
* Fix cursor bag saving to invalid slot_ids ([#4640](https://github.com/EQEmu/Server/pull/4640)) @nytmyr 2025-02-04
|
||||
|
||||
### Items
|
||||
|
||||
* Overhaul Item Hand-in System ([#4593](https://github.com/EQEmu/Server/pull/4593)) @Akkadius 2025-02-03
|
||||
|
||||
### Loginserver
|
||||
|
||||
* Fix iterator crash ([#4670](https://github.com/EQEmu/Server/pull/4670)) @Akkadius 2025-02-12
|
||||
* Modernize codebase ([#4647](https://github.com/EQEmu/Server/pull/4647)) @Akkadius 2025-02-06
|
||||
|
||||
### NPC Handins
|
||||
|
||||
* Fix MultiQuest Handins ([#4651](https://github.com/EQEmu/Server/pull/4651)) @Akkadius 2025-02-07
|
||||
|
||||
### Performance
|
||||
|
||||
* Server Reload Overhaul ([#4689](https://github.com/EQEmu/Server/pull/4689)) @Akkadius 2025-02-18
|
||||
|
||||
### Player Event Logs
|
||||
|
||||
* Migrate and Deprecate QS Legacy Logging ([#4542](https://github.com/EQEmu/Server/pull/4542)) @neckkola 2025-02-05
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add Bandolier Methods ([#4635](https://github.com/EQEmu/Server/pull/4635)) @Kinglykrab 2025-02-03
|
||||
* Add Potion Belt Methods ([#4634](https://github.com/EQEmu/Server/pull/4634)) @Kinglykrab 2025-02-04
|
||||
* Add Zone Support to Perl and Lua ([#4662](https://github.com/EQEmu/Server/pull/4662)) @Kinglykrab 2025-02-09
|
||||
|
||||
### Spells
|
||||
|
||||
* Add all types to checks for max_targets_allowed rule for AEs ([#4682](https://github.com/EQEmu/Server/pull/4682)) @nytmyr 2025-02-15
|
||||
|
||||
## [22.62.2] 2/1/2025
|
||||
|
||||
### Fixes
|
||||
|
||||
@@ -42,7 +42,6 @@ IF(USE_MAP_MMFS)
|
||||
ENDIF (USE_MAP_MMFS)
|
||||
|
||||
IF(MSVC)
|
||||
add_compile_options(/bigobj)
|
||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
|
||||
ADD_DEFINITIONS(-DNOMINMAX)
|
||||
ADD_DEFINITIONS(-DCRASH_LOGGING)
|
||||
|
||||
@@ -1,150 +1,83 @@
|
||||
<h1 align="center">EQEmulator Server Platform</h1>
|
||||
|
||||
<p align="center">
|
||||
<img src="https://github.com/user-attachments/assets/11942e15-b512-402d-a619-0543c7f1151e" style="border-radius: 10px">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<b>EQEmulator - A Fan-Made Project Honoring a Legendary MMORPG</b>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/eqemu/server/graphs/contributors"><img src="https://img.shields.io/github/contributors/eqemu/server" alt="Contributors"></a>
|
||||
<a href="https://discord.gg/QHsm7CD"><img src="https://img.shields.io/discord/212663220849213441?label=Discord&logo=discord&color=7289DA" alt="Discord"></a>
|
||||
<a href="https://docs.eqemu.io"><img src="https://img.shields.io/badge/docs-MkDocs%20Powered-blueviolet" alt="Docs"></a>
|
||||
<a href="./LICENSE"><img src="https://img.shields.io/github/license/EQEmu/Server" alt="License"></a>
|
||||
<a href="https://github.com/eqemu/server/releases"><img src="https://img.shields.io/github/v/release/eqemu/server" alt="Latest Release"></a>
|
||||
<a href="https://github.com/EQEmu/Server/releases"><img src="https://img.shields.io/github/release-date/EQEmu/Server" alt="Release Date"></a>
|
||||
<img src="https://img.shields.io/github/downloads/eqemu/server/total.svg" alt="Github All Releases"></a>
|
||||
<a href="http://drone.akkadius.com/EQEmu/Server"><img src="http://drone.akkadius.com/api/badges/EQEmu/Server/status.svg" alt="Build Status"></a>
|
||||
<img src="https://img.shields.io/github/issues-pr-closed/eqemu/server" alt="GitHub Issues or Pull Requests">
|
||||
<img src="https://img.shields.io/docker/pulls/akkadius/eqemu-server" alt="Docker Pulls">
|
||||
<a href="http://drone.akkadius.com/EQEmu/Server"><img src="http://drone.akkadius.com/api/badges/EQEmu/Server/status.svg" alt="Build Status"></a> <img src="https://jb.gg/badges/official-plastic.svg" alt="Official">
|
||||
|
||||
</p>
|
||||
# EQEmulator Core Server
|
||||
| Drone (Linux x64) | Drone (Windows x64) |
|
||||
|:---:|:---:|
|
||||
|[](http://drone.akkadius.com/EQEmu/Server) |[](http://drone.akkadius.com/EQEmu/Server) |
|
||||
|
||||
***
|
||||
|
||||
<p align="center">
|
||||
EQEmulator is a <b>passion-driven</b>, <b>open source server emulator</b> project dedicated to preserving and celebrating the legacy of a groundbreaking classic MMORPG.
|
||||
</p>
|
||||
**EQEmulator is a custom completely from-scratch open source server implementation for EverQuest built mostly on C++**
|
||||
* MySQL/MariaDB is used as the database engine (over 200+ tables)
|
||||
* Perl and LUA are both supported scripting languages for NPC/Player/Quest oriented events
|
||||
* Open source database (Project EQ) has content up to expansion OoW (included in server installs)
|
||||
* Game server environments and databases can be heavily customized to create all new experiences
|
||||
* Hundreds of Quests/events created and maintained by Project EQ
|
||||
|
||||
<p align="center">
|
||||
For over two decades and continuing, EQEmulator has served as a <strong>fan tribute</strong>, providing tools and technology that allow players to explore, customize, and experience the legendary game's iconic gameplay in new ways. This project exists solely out of <strong>deep admiration</strong> for the original developers, artists, designers, and visionaries who created one of the most influential online worlds of all time.
|
||||
</p>
|
||||
## Server Installs
|
||||
| |Windows|Linux|
|
||||
|:---:|:---:|:---:|
|
||||
|**Install Count**|||
|
||||
### > Windows
|
||||
|
||||
<p align="center">
|
||||
We do not claim ownership of the original game or its assets. <strong>All credit and respect belong to the original creators and Daybreak Game Company</strong>, whose work continues to inspire generations of players and developers alike.
|
||||
</p>
|
||||
* [Install Guide](https://docs.eqemu.io/server/installation/server-installation-windows/)
|
||||
|
||||
<p align="center">
|
||||
EQEmulator has for over 20 years and always will be a <strong>fan-based, non-commercial open-source effort</strong> made by players, for players—preserving the legacy of the game while empowering community-driven creativity, learning and joy that the game and its creators has so strongly inspired in us all.
|
||||
</p>
|
||||
### > Debian/Ubuntu/CentOS/Fedora
|
||||
|
||||
***
|
||||
* [Install Guide](https://docs.eqemu.io/server/installation/server-installation-linux/)
|
||||
|
||||
<h3 align="center">
|
||||
Technical Overview & Reverse Engineering Effort
|
||||
</h1>
|
||||
* You can use curl or wget to kick off the installer (whichever your OS has)
|
||||
> curl -O https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/linux_installer/install.sh install.sh && chmod 755 install.sh && ./install.sh
|
||||
|
||||
<p align="center">EQEmulator represents <strong>over two decades of collaborative reverse engineering</strong>, building the server from the ground up without access to the original source code. This effort was achieved entirely through <strong>community-driven analysis, network protocol decoding, and in-game behavioral research</strong>.</p>
|
||||
> wget --no-check-certificate https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/linux_installer/install.sh -O install.sh && chmod 755 install.sh && ./install.sh
|
||||
|
||||
<h1 align="center">
|
||||
💡 How We Did It
|
||||
</h1>
|
||||
|
||||
<p align="center">
|
||||
<img src="https://github.com/user-attachments/assets/b6b48cf7-f64a-4497-9750-71f442a3d132" height="300px">
|
||||
</p>
|
||||
|
||||
|
||||
<p align="center">
|
||||
<strong>Reverse Engineering</strong>
|
||||
Every system, packet, opcode, and game mechanic has been reconstructed through countless hours of live packet sniffing, client disassembly, and in-game experimentation by dedicated contributors over the years.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
No proprietary code or server sources were ever used.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
All implementations are the result of clean-room engineering.
|
||||
</p>
|
||||
|
||||
|
||||
<h1 align="center">
|
||||
🛠️ Technology Stack
|
||||
</h1>
|
||||
|
||||
<p align="center">
|
||||
<img src="https://github.com/user-attachments/assets/df5ea809-86c5-439d-a8fa-651fb04ba477" style="border-radius: 10px">
|
||||
</p>
|
||||
|
||||
**C++ Core Engine**
|
||||
|
||||
* High-performance networking and gameplay logic built in C++
|
||||
* Cross-platform support for Linux and Windows
|
||||
|
||||
**MySQL / MariaDB Backend**
|
||||
|
||||
* Fully structured schema with over 200+ tables
|
||||
* Supports content customization, expansions, and custom worlds
|
||||
|
||||
**Scripting Engine**
|
||||
|
||||
* Native support for **Perl** and **Lua** scripting
|
||||
* Powerfully extendable for quests, NPC behaviors, and custom events
|
||||
|
||||
**Open Source Content Database**
|
||||
|
||||
* Includes ProjectEQ’s world data up through *Dragons of Norrath*
|
||||
* 100% customizable to create entirely new game worlds
|
||||
|
||||
<h1 align="center">
|
||||
🚀 Why It Matters
|
||||
</h1>
|
||||
|
||||
<p align="center">🧬 EQEmulator stands as a <strong>technical preservation project</strong>, ensuring that the magic of classic and custom servers lives on for future generations of players, tinkerers, and game designers.
|
||||
</p>
|
||||
|
||||
> We humbly acknowledge and thank the original developers for creating one of the most influential online experiences in gaming history.
|
||||
|
||||
<h1 align="center">
|
||||
🧑💻🖥️ Supported Clients
|
||||
</h1>
|
||||
## Supported Clients
|
||||
|
||||
|Titanium Edition|Secrets of Faydwer|Seeds of Destruction|Underfoot|Rain of Fear|
|
||||
|:---:|:---:|:---:|:---:|:---:|
|
||||
|<img src="http://i.imgur.com/hrwDxoM.jpg" height="150">|<img src="http://i.imgur.com/cRDW5tn.png" height="150">|<img src="http://i.imgur.com/V48kuVn.jpg" height="150">|<img src="http://i.imgur.com/IJQ0XMa.jpg" height="150">|<img src="http://i.imgur.com/OMpHkKa.png" height="100">|
|
||||
|
||||
## 📚 Resources
|
||||
## Bug Reports <img src="http://i.imgur.com/daf1Vjw.png" height="20">
|
||||
* Please use the [issue tracker](https://github.com/EQEmu/Server/issues) provided by GitHub to send us bug
|
||||
reports or feature requests.
|
||||
* The [EQEmu Forums](http://www.eqemulator.org/forums/) are also a place to submit and get help with bugs.
|
||||
|
||||
| Resource | Badges | Link |
|
||||
|---------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------|
|
||||
| **EQEmulator Docs** | [](https://docs.eqemu.io) | [docs.eqemu.io](https://docs.eqemu.io/) |
|
||||
| **Discord Community**| [](https://discord.gg/QHsm7CD) | [Join Discord](https://discord.gg/QHsm7CD) |
|
||||
| **Latest Release** | [](https://github.com/eqemu/server/releases) <br> [](https://github.com/EQEmu/Server/releases) <br> [](https://github.com/eqemu/server/releases) | [View Releases](https://github.com/eqemu/server/releases) |
|
||||
| **License** | [](./LICENSE) | [View License](./LICENSE) |
|
||||
| **Build Status** | [](http://drone.akkadius.com/EQEmu/Server) | [View Build Status](http://drone.akkadius.com/EQEmu/Server) |
|
||||
| **Docker Pulls** | [](https://hub.docker.com/r/akkadius/eqemu-server) | [Docker Hub](https://hub.docker.com/r/akkadius/eqemu-server) |
|
||||
| **Contributions** | [](https://github.com/eqemu/server/pulls?q=is%3Apr+is%3Aclosed) | [Closed PRs & Issues](https://github.com/eqemu/server/pulls?q=is%3Apr+is%3Aclosed) |
|
||||
## Contributions <img src="http://image.flaticon.com/icons/png/512/25/25231.png" width="20">
|
||||
|
||||
## 🛠️ Getting Started
|
||||
* The preferred way to contribute is to fork the repo and submit a pull request on
|
||||
GitHub. If you need help with your changes, you can always post on the forums or
|
||||
try Discord. You can also post unified diffs (`git diff` should do the trick) on the
|
||||
[Server Code Submissions](http://www.eqemulator.org/forums/forumdisplay.php?f=669)
|
||||
forum, although pull requests will be much quicker and easier on all parties.
|
||||
|
||||
If you want to set up your own EQEmulator server, please refer to the current [server installation guides](https://docs.eqemu.io/#server-installation). We've had 100,000s of players and developers use our guides to set up their own servers, and we hope you will too!
|
||||
## Contact <img src="http://gamerescape.com/wp-content/uploads/2015/06/discord.png" height="20">
|
||||
|
||||
## 🗂️ Related Repositories
|
||||
- Discord Channel: https://discord.gg/QHsm7CD
|
||||
- **User Discord Channel**: `#general`
|
||||
- **Developer Discord Channel**: `#eqemucoders`
|
||||
|
||||
| Repository | Description |
|
||||
|--------------------|----------------------------------------------------------------------------------|
|
||||
| [ProjectEQ Quests](https://github.com/ProjectEQ/projecteqquests) | Official quests and event scripts for ProjectEQ |
|
||||
| [Maps](https://github.com/Akkadius/EQEmuMaps) | EQEmu-compatible zone maps |
|
||||
| [Installer Resources](https://github.com/Akkadius/EQEmuInstall) | Scripts and assets for setting up EQEmu servers |
|
||||
| [Zone Utilities](https://github.com/EQEmu/zone-utilities) | Utilities for parsing, rendering, and manipulating EQ zone files |
|
||||
## Resources
|
||||
- [EQEmulator Forums](http://www.eqemulator.org/forums)
|
||||
- [EQEmulator Wiki](https://docs.eqemu.io/)
|
||||
|
||||
## Related Repositories
|
||||
* [ProjectEQ Quests](https://github.com/ProjectEQ/projecteqquests)
|
||||
* [Maps](https://github.com/Akkadius/EQEmuMaps)
|
||||
* [Installer Resources](https://github.com/Akkadius/EQEmuInstall)
|
||||
* [Zone Utilities](https://github.com/EQEmu/zone-utilities) - Various utilities and libraries for parsing, rendering and manipulating EQ Zone files.
|
||||
|
||||
## Other License Info
|
||||
|
||||
* The server code and utilities are released under **GPLv3**
|
||||
* We also include some small libraries for convienence that may be under different licensing
|
||||
* SocketLib - GPL LibXML
|
||||
* zlib - zlib license
|
||||
* MariaDB/MySQL - GPL
|
||||
* GPL Perl - GPL / ActiveState (under the assumption that this is a free project)
|
||||
* CPPUnit - GLP StringUtilities - Apache
|
||||
* LUA - MIT
|
||||
|
||||
## Contributors
|
||||
|
||||
<a href="https://github.com/EQEmu/server/graphs/contributors">
|
||||
<img src="https://contributors-img.firebaseapp.com/image?repo=EQEmu/server" />
|
||||
</a>
|
||||
|
||||
|
||||
@@ -38,6 +38,13 @@
|
||||
#include "../../common/skill_caps.h"
|
||||
#include "../../common/evolving_items.h"
|
||||
|
||||
EQEmuLogSys LogSys;
|
||||
WorldContentService content_service;
|
||||
ZoneStore zone_store;
|
||||
PathManager path;
|
||||
PlayerEventLogs player_event_logs;
|
||||
EvolvingItemsManager evolving_items_manager;
|
||||
|
||||
void ExportSpells(SharedDatabase *db);
|
||||
void ExportSkillCaps(SharedDatabase *db);
|
||||
void ExportBaseData(SharedDatabase *db);
|
||||
@@ -46,10 +53,10 @@ void ExportDBStrings(SharedDatabase *db);
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
RegisterExecutablePlatform(ExePlatformClientExport);
|
||||
EQEmuLogSys::Instance()->LoadLogSettingsDefaults();
|
||||
LogSys.LoadLogSettingsDefaults();
|
||||
set_exception_handler();
|
||||
|
||||
PathManager::Instance()->Init();
|
||||
path.LoadPaths();
|
||||
|
||||
LogInfo("Client Files Export Utility");
|
||||
if (!EQEmuConfig::LoadConfig()) {
|
||||
@@ -92,8 +99,8 @@ int main(int argc, char **argv)
|
||||
content_db.SetMySQL(database);
|
||||
}
|
||||
|
||||
EQEmuLogSys::Instance()->SetDatabase(&database)
|
||||
->SetLogPath(PathManager::Instance()->GetLogPath())
|
||||
LogSys.SetDatabase(&database)
|
||||
->SetLogPath(path.GetLogPath())
|
||||
->LoadLogDatabaseSettings()
|
||||
->StartFileLogs();
|
||||
|
||||
@@ -122,14 +129,14 @@ int main(int argc, char **argv)
|
||||
ExportBaseData(&content_db);
|
||||
ExportDBStrings(&database);
|
||||
|
||||
EQEmuLogSys::Instance()->CloseFileLogs();
|
||||
LogSys.CloseFileLogs();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ExportSpells(SharedDatabase* db)
|
||||
{
|
||||
std::ofstream file(fmt::format("{}/export/spells_us.txt", PathManager::Instance()->GetServerPath()));
|
||||
std::ofstream file(fmt::format("{}/export/spells_us.txt", path.GetServerPath()));
|
||||
if (!file || !file.is_open()) {
|
||||
LogError("Unable to open export/spells_us.txt to write, skipping.");
|
||||
return;
|
||||
@@ -148,7 +155,7 @@ void ExportSpells(SharedDatabase* db)
|
||||
|
||||
void ExportSkillCaps(SharedDatabase* db)
|
||||
{
|
||||
std::ofstream file(fmt::format("{}/export/SkillCaps.txt", PathManager::Instance()->GetServerPath()));
|
||||
std::ofstream file(fmt::format("{}/export/SkillCaps.txt", path.GetServerPath()));
|
||||
if (!file || !file.is_open()) {
|
||||
LogError("Unable to open export/SkillCaps.txt to write, skipping.");
|
||||
return;
|
||||
@@ -167,7 +174,7 @@ void ExportSkillCaps(SharedDatabase* db)
|
||||
|
||||
void ExportBaseData(SharedDatabase *db)
|
||||
{
|
||||
std::ofstream file(fmt::format("{}/export/BaseData.txt", PathManager::Instance()->GetServerPath()));
|
||||
std::ofstream file(fmt::format("{}/export/BaseData.txt", path.GetServerPath()));
|
||||
if (!file || !file.is_open()) {
|
||||
LogError("Unable to open export/BaseData.txt to write, skipping.");
|
||||
return;
|
||||
@@ -186,7 +193,7 @@ void ExportBaseData(SharedDatabase *db)
|
||||
|
||||
void ExportDBStrings(SharedDatabase *db)
|
||||
{
|
||||
std::ofstream file(fmt::format("{}/export/dbstr_us.txt", PathManager::Instance()->GetServerPath()));
|
||||
std::ofstream file(fmt::format("{}/export/dbstr_us.txt", path.GetServerPath()));
|
||||
if (!file || !file.is_open()) {
|
||||
LogError("Unable to open export/dbstr_us.txt to write, skipping.");
|
||||
return;
|
||||
|
||||
@@ -32,6 +32,13 @@
|
||||
#include "../../common/events/player_event_logs.h"
|
||||
#include "../../common/evolving_items.h"
|
||||
|
||||
EQEmuLogSys LogSys;
|
||||
WorldContentService content_service;
|
||||
ZoneStore zone_store;
|
||||
PathManager path;
|
||||
PlayerEventLogs player_event_logs;
|
||||
EvolvingItemsManager evolving_items_manager;
|
||||
|
||||
void ImportSpells(SharedDatabase *db);
|
||||
void ImportSkillCaps(SharedDatabase *db);
|
||||
void ImportBaseData(SharedDatabase *db);
|
||||
@@ -39,10 +46,10 @@ void ImportDBStrings(SharedDatabase *db);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
RegisterExecutablePlatform(ExePlatformClientImport);
|
||||
EQEmuLogSys::Instance()->LoadLogSettingsDefaults();
|
||||
LogSys.LoadLogSettingsDefaults();
|
||||
set_exception_handler();
|
||||
|
||||
PathManager::Instance()->Init();
|
||||
path.LoadPaths();
|
||||
|
||||
LogInfo("Client Files Import Utility");
|
||||
if(!EQEmuConfig::LoadConfig()) {
|
||||
@@ -85,8 +92,8 @@ int main(int argc, char **argv) {
|
||||
content_db.SetMySQL(database);
|
||||
}
|
||||
|
||||
EQEmuLogSys::Instance()->SetDatabase(&database)
|
||||
->SetLogPath(PathManager::Instance()->GetLogPath())
|
||||
LogSys.SetDatabase(&database)
|
||||
->SetLogPath(path.GetLogPath())
|
||||
->LoadLogDatabaseSettings()
|
||||
->StartFileLogs();
|
||||
|
||||
@@ -95,7 +102,7 @@ int main(int argc, char **argv) {
|
||||
ImportBaseData(&content_db);
|
||||
ImportDBStrings(&database);
|
||||
|
||||
EQEmuLogSys::Instance()->CloseFileLogs();
|
||||
LogSys.CloseFileLogs();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -131,7 +138,7 @@ bool IsStringField(int i) {
|
||||
|
||||
void ImportSpells(SharedDatabase *db) {
|
||||
LogInfo("Importing Spells");
|
||||
std::string file = fmt::format("{}/import/spells_us.txt", PathManager::Instance()->GetServerPath());
|
||||
std::string file = fmt::format("{}/import/spells_us.txt", path.GetServerPath());
|
||||
FILE *f = fopen(file.c_str(), "r");
|
||||
if(!f) {
|
||||
LogError("Unable to open {} to read, skipping.", file);
|
||||
@@ -221,7 +228,7 @@ void ImportSpells(SharedDatabase *db) {
|
||||
void ImportSkillCaps(SharedDatabase *db) {
|
||||
LogInfo("Importing Skill Caps");
|
||||
|
||||
std::string file = fmt::format("{}/import/SkillCaps.txt", PathManager::Instance()->GetServerPath());
|
||||
std::string file = fmt::format("{}/import/SkillCaps.txt", path.GetServerPath());
|
||||
FILE *f = fopen(file.c_str(), "r");
|
||||
if(!f) {
|
||||
LogError("Unable to open {} to read, skipping.", file);
|
||||
@@ -258,7 +265,7 @@ void ImportBaseData(SharedDatabase *db)
|
||||
{
|
||||
LogInfo("Importing Base Data");
|
||||
|
||||
const std::string& file_name = fmt::format("{}/import/BaseData.txt", PathManager::Instance()->GetServerPath());
|
||||
const std::string& file_name = fmt::format("{}/import/BaseData.txt", path.GetServerPath());
|
||||
|
||||
const auto& file_contents = File::GetContents(file_name);
|
||||
if (!file_contents.error.empty()) {
|
||||
@@ -298,7 +305,7 @@ void ImportBaseData(SharedDatabase *db)
|
||||
void ImportDBStrings(SharedDatabase *db) {
|
||||
LogInfo("Importing DB Strings");
|
||||
|
||||
std::string file = fmt::format("{}/import/dbstr_us.txt", PathManager::Instance()->GetServerPath());
|
||||
std::string file = fmt::format("{}/import/dbstr_us.txt", path.GetServerPath());
|
||||
FILE *f = fopen(file.c_str(), "r");
|
||||
if(!f) {
|
||||
LogError("Unable to open {} to read, skipping.", file);
|
||||
|
||||
+7
-11
@@ -17,13 +17,11 @@ SET(common_sources
|
||||
database.cpp
|
||||
database_instances.cpp
|
||||
database/database_update_manifest.cpp
|
||||
database/database_update_manifest_custom.cpp
|
||||
database/database_update_manifest_bots.cpp
|
||||
database/database_update.cpp
|
||||
dbcore.cpp
|
||||
deity.cpp
|
||||
dynamic_zone_base.cpp
|
||||
dynamic_zone_lockout.cpp
|
||||
emu_constants.cpp
|
||||
emu_limits.cpp
|
||||
emu_opcodes.cpp
|
||||
@@ -42,6 +40,7 @@ SET(common_sources
|
||||
events/player_event_logs.cpp
|
||||
events/player_event_discord_formatter.cpp
|
||||
evolving_items.cpp
|
||||
expedition_lockout_timer.cpp
|
||||
extprofile.cpp
|
||||
discord/discord_manager.cpp
|
||||
faction.cpp
|
||||
@@ -214,9 +213,10 @@ SET(repositories
|
||||
repositories/base/base_discovered_items_repository.h
|
||||
repositories/base/base_doors_repository.h
|
||||
repositories/base/base_dynamic_zones_repository.h
|
||||
repositories/base/base_dynamic_zone_lockouts_repository.h
|
||||
repositories/base/base_dynamic_zone_members_repository.h
|
||||
repositories/base/base_dynamic_zone_templates_repository.h
|
||||
repositories/base/base_expeditions_repository.h
|
||||
repositories/base/base_expedition_lockouts_repository.h
|
||||
repositories/base/base_faction_association_repository.h
|
||||
repositories/base/base_faction_base_data_repository.h
|
||||
repositories/base/base_faction_list_repository.h
|
||||
@@ -410,9 +410,10 @@ SET(repositories
|
||||
repositories/discovered_items_repository.h
|
||||
repositories/doors_repository.h
|
||||
repositories/dynamic_zones_repository.h
|
||||
repositories/dynamic_zone_lockouts_repository.h
|
||||
repositories/dynamic_zone_members_repository.h
|
||||
repositories/dynamic_zone_templates_repository.h
|
||||
repositories/expeditions_repository.h
|
||||
repositories/expedition_lockouts_repository.h
|
||||
repositories/faction_association_repository.h
|
||||
repositories/faction_base_data_repository.h
|
||||
repositories/faction_list_repository.h
|
||||
@@ -560,7 +561,6 @@ SET(common_headers
|
||||
discord/discord.h
|
||||
discord/discord_manager.h
|
||||
dynamic_zone_base.h
|
||||
dynamic_zone_lockout.h
|
||||
emu_constants.h
|
||||
emu_limits.h
|
||||
emu_opcodes.h
|
||||
@@ -587,6 +587,7 @@ SET(common_headers
|
||||
events/player_events.h
|
||||
event_sub.h
|
||||
evolving_items.h
|
||||
expedition_lockout_timer.h
|
||||
extprofile.h
|
||||
faction.h
|
||||
file.h
|
||||
@@ -646,7 +647,6 @@ SET(common_headers
|
||||
server_event_scheduler.h
|
||||
serverinfo.h
|
||||
servertalk.h
|
||||
server_reload_types.h
|
||||
shared_tasks.h
|
||||
shareddb.h
|
||||
skills.h
|
||||
@@ -672,7 +672,6 @@ SET(common_headers
|
||||
net/console_server_connection.h
|
||||
net/crc32.h
|
||||
net/daybreak_connection.h
|
||||
net/daybreak_pooling.h
|
||||
net/daybreak_structs.h
|
||||
net/dns.h
|
||||
net/endian.h
|
||||
@@ -684,7 +683,6 @@ SET(common_headers
|
||||
net/servertalk_server.h
|
||||
net/servertalk_server_connection.h
|
||||
net/tcp_connection.h
|
||||
net/tcp_connection_pooling.h
|
||||
net/tcp_server.h
|
||||
net/websocket_server.h
|
||||
net/websocket_server_connection.h
|
||||
@@ -745,7 +743,6 @@ SOURCE_GROUP(Net FILES
|
||||
net/crc32.h
|
||||
net/daybreak_connection.cpp
|
||||
net/daybreak_connection.h
|
||||
net/daybreak_pooling.h
|
||||
net/daybreak_structs.h
|
||||
net/dns.h
|
||||
net/endian.h
|
||||
@@ -766,7 +763,6 @@ SOURCE_GROUP(Net FILES
|
||||
net/servertalk_server_connection.h
|
||||
net/tcp_connection.cpp
|
||||
net/tcp_connection.h
|
||||
net/tcp_connection_pooling.h
|
||||
net/tcp_server.cpp
|
||||
net/tcp_server.h
|
||||
net/websocket_server.cpp
|
||||
@@ -842,7 +838,7 @@ IF (UNIX)
|
||||
ENDIF (UNIX)
|
||||
|
||||
IF (WIN32 AND EQEMU_BUILD_PCH)
|
||||
TARGET_PRECOMPILE_HEADERS(common PRIVATE pch/std-pch.h)
|
||||
TARGET_PRECOMPILE_HEADERS(common PRIVATE pch/pch.h)
|
||||
ENDIF ()
|
||||
|
||||
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
|
||||
|
||||
+1
-2
@@ -279,8 +279,7 @@ Bazaar::GetSearchResults(
|
||||
trader_items_ids,
|
||||
std::string(search.item_name),
|
||||
field_criteria_items,
|
||||
where_criteria_items,
|
||||
search.max_results
|
||||
where_criteria_items
|
||||
);
|
||||
|
||||
if (item_results.empty()) {
|
||||
|
||||
@@ -27,7 +27,7 @@ WorldContentService *WorldContentService::SetExpansionContext()
|
||||
// pull expansion from rules
|
||||
int expansion = RuleI(Expansion, CurrentExpansion);
|
||||
if (expansion >= Expansion::Classic && expansion <= Expansion::MaxId) {
|
||||
WorldContentService::Instance()->SetCurrentExpansion(expansion);
|
||||
content_service.SetCurrentExpansion(expansion);
|
||||
}
|
||||
|
||||
LogInfo(
|
||||
@@ -41,12 +41,12 @@ WorldContentService *WorldContentService::SetExpansionContext()
|
||||
|
||||
std::string WorldContentService::GetCurrentExpansionName()
|
||||
{
|
||||
if (WorldContentService::Instance()->GetCurrentExpansion() == Expansion::EXPANSION_ALL) {
|
||||
if (content_service.GetCurrentExpansion() == Expansion::EXPANSION_ALL) {
|
||||
return "All Expansions";
|
||||
}
|
||||
|
||||
if (current_expansion >= Expansion::Classic && current_expansion <= Expansion::MaxId) {
|
||||
return Expansion::ExpansionName[WorldContentService::Instance()->GetCurrentExpansion()];
|
||||
return Expansion::ExpansionName[content_service.GetCurrentExpansion()];
|
||||
}
|
||||
|
||||
return "Unknown Expansion";
|
||||
@@ -185,7 +185,7 @@ void WorldContentService::ReloadContentFlags()
|
||||
|
||||
SetContentFlags(set_content_flags);
|
||||
LoadStaticGlobalZoneInstances();
|
||||
ZoneStore::Instance()->LoadZones(*m_content_database);
|
||||
zone_store.LoadZones(*m_content_database);
|
||||
}
|
||||
|
||||
Database *WorldContentService::GetDatabase() const
|
||||
@@ -291,7 +291,7 @@ WorldContentService *WorldContentService::LoadStaticGlobalZoneInstances()
|
||||
// instance_list table entry for lavastorm has version = 1, is_global = 1, never_expires = 1
|
||||
WorldContentService::FindZoneResult WorldContentService::FindZone(uint32 zone_id, uint32 instance_id)
|
||||
{
|
||||
for (const auto &z: ZoneStore::Instance()->GetZones()) {
|
||||
for (const auto &z: zone_store.GetZones()) {
|
||||
for (auto &i: m_zone_static_instances) {
|
||||
if (
|
||||
z.zoneidnumber == zone_id &&
|
||||
|
||||
@@ -181,12 +181,6 @@ public:
|
||||
FindZoneResult FindZone(uint32 zone_id, uint32 instance_id);
|
||||
bool IsInPublicStaticInstance(uint32 instance_id);
|
||||
|
||||
static WorldContentService* Instance()
|
||||
{
|
||||
static WorldContentService instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
private:
|
||||
int current_expansion{};
|
||||
std::vector<ContentFlagsRepository::ContentFlags> content_flags;
|
||||
@@ -200,4 +194,6 @@ private:
|
||||
std::vector<InstanceListRepository::InstanceList> m_zone_static_instances;
|
||||
};
|
||||
|
||||
extern WorldContentService content_service;
|
||||
|
||||
#endif //EQEMU_WORLD_CONTENT_SERVICE_H
|
||||
|
||||
+5
-7
@@ -27,8 +27,6 @@ void SendCrashReport(const std::string &crash_report)
|
||||
// "http://localhost:3010/api/v1/analytics/server-crash-report", // development
|
||||
};
|
||||
|
||||
EQEmuLogSys* log = EQEmuLogSys::Instance();
|
||||
|
||||
auto config = EQEmuConfig::get();
|
||||
for (auto &e: endpoints) {
|
||||
uri u(e);
|
||||
@@ -70,12 +68,12 @@ void SendCrashReport(const std::string &crash_report)
|
||||
p["cpus"] = cpus.size();
|
||||
p["origination_info"] = "";
|
||||
|
||||
if (!log->origination_info.zone_short_name.empty()) {
|
||||
if (!LogSys.origination_info.zone_short_name.empty()) {
|
||||
p["origination_info"] = fmt::format(
|
||||
"{} ({}) instance_id [{}]",
|
||||
log->origination_info.zone_short_name,
|
||||
log->origination_info.zone_long_name,
|
||||
log->origination_info.instance_id
|
||||
LogSys.origination_info.zone_short_name,
|
||||
LogSys.origination_info.zone_long_name,
|
||||
LogSys.origination_info.instance_id
|
||||
);
|
||||
}
|
||||
|
||||
@@ -296,7 +294,7 @@ void print_trace()
|
||||
SendCrashReport(crash_report);
|
||||
}
|
||||
|
||||
EQEmuLogSys::Instance()->CloseFileLogs();
|
||||
LogSys.CloseFileLogs();
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
+9
-78
@@ -245,7 +245,7 @@ uint32 Database::CreateAccount(
|
||||
e.password = password;
|
||||
}
|
||||
|
||||
LogInfo("Account attempting to be created loginserver [{}] name [{}] status [{}]", loginserver, name, status);
|
||||
LogInfo("Account Attempting to be created: [{}:{}] status: {}", loginserver, name, status);
|
||||
|
||||
e = AccountRepository::InsertOne(*this, e);
|
||||
|
||||
@@ -708,20 +708,6 @@ const std::string Database::GetNPCNameByID(uint32 npc_id)
|
||||
return e.id ? e.name : std::string();
|
||||
}
|
||||
|
||||
template<typename InputIterator, typename OutputIterator>
|
||||
inline auto CleanMobName(InputIterator first, InputIterator last, OutputIterator result)
|
||||
{
|
||||
for (; first != last; ++first) {
|
||||
if (*first == '_') {
|
||||
*result = ' ';
|
||||
}
|
||||
else if (isalpha(*first) || *first == '`') {
|
||||
*result = *first;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const std::string Database::GetCleanNPCNameByID(uint32 npc_id)
|
||||
{
|
||||
const auto& e = NpcTypesRepository::FindOne(*this, npc_id);
|
||||
@@ -969,29 +955,6 @@ bool Database::UpdateName(const std::string& old_name, const std::string& new_na
|
||||
return CharacterDataRepository::UpdateOne(*this, e);
|
||||
}
|
||||
|
||||
bool Database::UpdateNameByID(const int character_id, const std::string& new_name)
|
||||
{
|
||||
LogInfo("Renaming [{}] to [{}]", character_id, new_name);
|
||||
|
||||
auto l = CharacterDataRepository::GetWhere(
|
||||
*this,
|
||||
fmt::format(
|
||||
"`id` = {}",
|
||||
character_id
|
||||
)
|
||||
);
|
||||
|
||||
if (l.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& e = l.front();
|
||||
|
||||
e.name = new_name;
|
||||
|
||||
return CharacterDataRepository::UpdateOne(*this, e);
|
||||
}
|
||||
|
||||
bool Database::IsNameUsed(const std::string& name)
|
||||
{
|
||||
if (RuleB(Bots, Enabled)) {
|
||||
@@ -1019,20 +982,6 @@ bool Database::IsNameUsed(const std::string& name)
|
||||
return !character_data.empty();
|
||||
}
|
||||
|
||||
// Players cannot have the same name as a pet vanity name, or memory corruption occurs.
|
||||
bool Database::IsPetNameUsed(const std::string& name)
|
||||
{
|
||||
const auto& pet_name_data = CharacterPetNameRepository::GetWhere(
|
||||
*this,
|
||||
fmt::format(
|
||||
"`name` = '{}'",
|
||||
Strings::Escape(name)
|
||||
)
|
||||
);
|
||||
|
||||
return !pet_name_data.empty();
|
||||
}
|
||||
|
||||
uint32 Database::GetServerType()
|
||||
{
|
||||
const auto& l = VariablesRepository::GetWhere(*this, "`varname` = 'ServerType' LIMIT 1");
|
||||
@@ -1109,13 +1058,13 @@ void Database::SetLFP(uint32 character_id, bool is_lfp)
|
||||
CharacterDataRepository::UpdateOne(*this, e);
|
||||
}
|
||||
|
||||
void Database::SetLoginFlags(uint32 character_id, bool is_lfp, bool is_lfg, uint8 ingame)
|
||||
void Database::SetLoginFlags(uint32 character_id, bool is_lfp, bool is_lfg, uint8 first_logon)
|
||||
{
|
||||
auto e = CharacterDataRepository::FindOne(*this, character_id);
|
||||
|
||||
e.ingame = ingame;
|
||||
e.lfg = is_lfg ? 1 : 0;
|
||||
e.lfp = is_lfp ? 1 : 0;
|
||||
e.firstlogon = first_logon;
|
||||
e.lfg = is_lfg ? 1 : 0;
|
||||
e.lfp = is_lfp ? 1 : 0;
|
||||
|
||||
CharacterDataRepository::UpdateOne(*this, e);
|
||||
}
|
||||
@@ -1129,11 +1078,11 @@ void Database::SetLFG(uint32 character_id, bool is_lfg)
|
||||
CharacterDataRepository::UpdateOne(*this, e);
|
||||
}
|
||||
|
||||
void Database::SetIngame(uint32 character_id, uint8 ingame)
|
||||
void Database::SetFirstLogon(uint32 character_id, uint8 first_logon)
|
||||
{
|
||||
auto e = CharacterDataRepository::FindOne(*this, character_id);
|
||||
|
||||
e.ingame = ingame;
|
||||
e.firstlogon = first_logon;
|
||||
|
||||
CharacterDataRepository::UpdateOne(*this, e);
|
||||
}
|
||||
@@ -1934,7 +1883,6 @@ bool Database::CopyCharacter(
|
||||
std::vector<std::string> tables_to_zero_id = {
|
||||
"keyring",
|
||||
"data_buckets",
|
||||
"character_evolving_items",
|
||||
"character_instance_safereturns",
|
||||
"character_expedition_lockouts",
|
||||
"character_instance_lockouts",
|
||||
@@ -1966,12 +1914,6 @@ bool Database::CopyCharacter(
|
||||
)
|
||||
);
|
||||
|
||||
if (!results.Success()) {
|
||||
LogError("Transaction failed [{}] rolling back", results.ErrorMessage());
|
||||
TransactionRollback();
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> columns = {};
|
||||
int column_count = 0;
|
||||
|
||||
@@ -1990,12 +1932,6 @@ bool Database::CopyCharacter(
|
||||
)
|
||||
);
|
||||
|
||||
if (!results.Success()) {
|
||||
LogError("Transaction failed [{}] rolling back", results.ErrorMessage());
|
||||
TransactionRollback();
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::vector<std::string>> new_rows;
|
||||
|
||||
for (auto row : results) {
|
||||
@@ -2063,18 +1999,13 @@ bool Database::CopyCharacter(
|
||||
LogInfo("Copying table [{}] rows [{}]", table_name, Strings::Commify(rows_copied));
|
||||
|
||||
if (!insert.ErrorMessage().empty()) {
|
||||
LogError("Error copying table [{}] [{}]", table_name, insert.ErrorMessage());
|
||||
TransactionRollback();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto r = TransactionCommit();
|
||||
if (!r.Success()) {
|
||||
LogError("Transaction failed [{}] rolling back", r.ErrorMessage());
|
||||
return false;
|
||||
}
|
||||
TransactionCommit();
|
||||
|
||||
LogInfo(
|
||||
"Character [{}] copied to [{}] total rows [{}]",
|
||||
@@ -2244,7 +2175,7 @@ void Database::PurgeCharacterParcels()
|
||||
pel.event_data = ss.str();
|
||||
pel.created_at = std::time(nullptr);
|
||||
|
||||
PlayerEventLogs::Instance()->AddToQueue(pel);
|
||||
player_event_logs.AddToQueue(pel);
|
||||
|
||||
ss.str("");
|
||||
ss.clear();
|
||||
|
||||
+1
-4
@@ -103,7 +103,6 @@ public:
|
||||
bool ReserveName(uint32 account_id, const std::string& name);
|
||||
bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp);
|
||||
bool UpdateName(const std::string& old_name, const std::string& new_name);
|
||||
bool UpdateNameByID(const int character_id, const std::string& new_name);
|
||||
bool CopyCharacter(
|
||||
const std::string& source_character_name,
|
||||
const std::string& destination_character_name,
|
||||
@@ -117,7 +116,6 @@ public:
|
||||
bool CheckGMIPs(const std::string& login_ip, uint32 account_id);
|
||||
bool CheckNameFilter(const std::string& name, bool surname = false);
|
||||
bool IsNameUsed(const std::string& name);
|
||||
bool IsPetNameUsed(const std::string& name);
|
||||
|
||||
uint32 GetAccountIDByChar(const std::string& name, uint32* character_id = 0);
|
||||
uint32 GetAccountIDByChar(uint32 character_id);
|
||||
@@ -141,7 +139,6 @@ public:
|
||||
bool CheckInstanceExpired(uint16 instance_id);
|
||||
bool CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration);
|
||||
bool GetUnusedInstanceID(uint16& instance_id);
|
||||
bool TryGetUnusedInstanceID(uint16& instance_id);
|
||||
bool IsGlobalInstance(uint16 instance_id);
|
||||
bool RemoveClientFromInstance(uint16 instance_id, uint32 char_id);
|
||||
bool RemoveClientsFromInstance(uint16 instance_id);
|
||||
@@ -263,7 +260,7 @@ public:
|
||||
bool SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year);
|
||||
void ClearMerchantTemp();
|
||||
void ClearPTimers(uint32 character_id);
|
||||
void SetIngame(uint32 character_id, uint8 ingame);
|
||||
void SetFirstLogon(uint32 character_id, uint8 first_logon);
|
||||
void SetLFG(uint32 character_id, bool is_lfg);
|
||||
void SetLFP(uint32 character_id, bool is_lfp);
|
||||
void SetLoginFlags(uint32 character_id, bool is_lfp, bool is_lfg, uint8 first_logon);
|
||||
|
||||
@@ -50,7 +50,7 @@ bool DatabaseDumpService::IsMySQLInstalled()
|
||||
{
|
||||
std::string version_output = GetMySQLVersion();
|
||||
|
||||
return version_output.find("mysql") != std::string::npos && (version_output.find("Ver") != std::string::npos || version_output.find("from") != std::string::npos);
|
||||
return version_output.find("mysql") != std::string::npos && version_output.find("Ver") != std::string::npos;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -204,7 +204,7 @@ void DatabaseDumpService::DatabaseDump()
|
||||
}
|
||||
|
||||
if (IsDumpOutputToConsole()) {
|
||||
EQEmuLogSys::Instance()->SilenceConsoleLogging();
|
||||
LogSys.SilenceConsoleLogging();
|
||||
}
|
||||
|
||||
LogInfo("MySQL installed [{}]", GetMySQLVersion());
|
||||
@@ -324,7 +324,7 @@ void DatabaseDumpService::DatabaseDump()
|
||||
}
|
||||
|
||||
if (!IsDumpOutputToConsole()) {
|
||||
EQEmuLogSys::Instance()->LoadLogSettingsDefaults();
|
||||
LogSys.LoadLogSettingsDefaults();
|
||||
}
|
||||
|
||||
if (!pipe_file.empty()) {
|
||||
@@ -596,12 +596,7 @@ void DatabaseDumpService::BuildCredentialsFile()
|
||||
void DatabaseDumpService::RemoveCredentialsFile()
|
||||
{
|
||||
if (File::Exists(CREDENTIALS_FILE)) {
|
||||
try {
|
||||
std::filesystem::remove(CREDENTIALS_FILE);
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
LogError("std::filesystem::remove err [{}]", e.what());
|
||||
}
|
||||
std::filesystem::remove(CREDENTIALS_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ private:
|
||||
bool dump_system_tables = false;
|
||||
bool dump_content_tables = false;
|
||||
bool dump_player_tables = false;
|
||||
bool dump_query_server_tables = false;
|
||||
bool dump_login_server_tables = false;
|
||||
bool dump_with_no_data = false;
|
||||
bool dump_table_lock = false;
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "../http/httplib.h"
|
||||
|
||||
#include "database_update_manifest.cpp"
|
||||
#include "database_update_manifest_custom.cpp"
|
||||
#include "database_update_manifest_bots.cpp"
|
||||
#include "database_dump_service.h"
|
||||
|
||||
@@ -15,7 +14,7 @@ constexpr int BREAK_LENGTH = 70;
|
||||
|
||||
DatabaseVersion DatabaseUpdate::GetDatabaseVersions()
|
||||
{
|
||||
auto results = m_database->QueryDatabase("SELECT `version`, `bots_version`, `custom_version` FROM `db_version` LIMIT 1");
|
||||
auto results = m_database->QueryDatabase("SELECT `version`, `bots_version` FROM `db_version` LIMIT 1");
|
||||
if (!results.Success() || !results.RowCount()) {
|
||||
LogError("Failed to read from [db_version] table!");
|
||||
return DatabaseVersion{};
|
||||
@@ -26,7 +25,6 @@ DatabaseVersion DatabaseUpdate::GetDatabaseVersions()
|
||||
return DatabaseVersion{
|
||||
.server_database_version = Strings::ToInt(r[0]),
|
||||
.bots_database_version = Strings::ToInt(r[1]),
|
||||
.custom_database_version = Strings::ToInt(r[2]),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -35,7 +33,6 @@ DatabaseVersion DatabaseUpdate::GetBinaryDatabaseVersions()
|
||||
return DatabaseVersion{
|
||||
.server_database_version = CURRENT_BINARY_DATABASE_VERSION,
|
||||
.bots_database_version = (RuleB(Bots, Enabled) ? CURRENT_BINARY_BOTS_DATABASE_VERSION : 0),
|
||||
.custom_database_version = CUSTOM_BINARY_DATABASE_VERSION,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -46,7 +43,6 @@ constexpr int LOOK_BACK_AMOUNT = 10;
|
||||
// this check will take action
|
||||
void DatabaseUpdate::CheckDbUpdates()
|
||||
{
|
||||
InjectCustomVersionColumn();
|
||||
InjectBotsVersionColumn();
|
||||
auto v = GetDatabaseVersions();
|
||||
auto b = GetBinaryDatabaseVersions();
|
||||
@@ -63,15 +59,6 @@ void DatabaseUpdate::CheckDbUpdates()
|
||||
m_database->QueryDatabase(fmt::format("UPDATE `db_version` SET `version` = {}", b.server_database_version));
|
||||
}
|
||||
|
||||
if (UpdateManifest(manifest_entries_custom, v.custom_database_version, b.custom_database_version)) {
|
||||
LogInfo(
|
||||
"Updates ran successfully, setting database version to [{}] from [{}]",
|
||||
b.custom_database_version,
|
||||
v.custom_database_version
|
||||
);
|
||||
m_database->QueryDatabase(fmt::format("UPDATE `db_version` SET `custom_version` = {}", b.custom_database_version));
|
||||
}
|
||||
|
||||
if (b.bots_database_version > 0) {
|
||||
if (UpdateManifest(bot_manifest_entries, v.bots_database_version, b.bots_database_version)) {
|
||||
LogInfo(
|
||||
@@ -154,7 +141,7 @@ bool DatabaseUpdate::UpdateManifest(
|
||||
std::vector<int> missing_migrations = {};
|
||||
if (version_low != version_high) {
|
||||
|
||||
EQEmuLogSys::Instance()->DisableMySQLErrorLogs();
|
||||
LogSys.DisableMySQLErrorLogs();
|
||||
bool force_interactive = false;
|
||||
for (int version = version_low + 1; version <= version_high; ++version) {
|
||||
for (auto &e: entries) {
|
||||
@@ -184,7 +171,7 @@ bool DatabaseUpdate::UpdateManifest(
|
||||
}
|
||||
}
|
||||
}
|
||||
EQEmuLogSys::Instance()->EnableMySQLErrorLogs();
|
||||
LogSys.EnableMySQLErrorLogs();
|
||||
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
||||
|
||||
if (!missing_migrations.empty() && m_skip_backup) {
|
||||
@@ -357,16 +344,6 @@ bool DatabaseUpdate::CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b)
|
||||
);
|
||||
}
|
||||
|
||||
if (b.custom_database_version > 0) {
|
||||
LogInfo(
|
||||
"{:>8} | database [{}] binary [{}] {}",
|
||||
"Custom",
|
||||
v.custom_database_version,
|
||||
b.custom_database_version,
|
||||
(v.custom_database_version == b.custom_database_version) ? "up to date" : "checking updates"
|
||||
);
|
||||
}
|
||||
|
||||
LogInfo("{:>8} | [server.auto_database_updates] [<green>true]", "Config");
|
||||
|
||||
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
||||
@@ -376,10 +353,7 @@ bool DatabaseUpdate::CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b)
|
||||
// bots database version is optional, if not enabled then it is always up-to-date
|
||||
bool bots_up_to_date = RuleB(Bots, Enabled) ? v.bots_database_version >= b.bots_database_version : true;
|
||||
|
||||
// custom database version is optional, if not enabled then it is always up-to-date
|
||||
bool custom_up_to_date = v.custom_database_version >= b.custom_database_version;
|
||||
|
||||
return server_up_to_date && bots_up_to_date && custom_up_to_date;
|
||||
return server_up_to_date && bots_up_to_date;
|
||||
}
|
||||
|
||||
// checks to see if there are pending updates
|
||||
@@ -399,12 +373,3 @@ void DatabaseUpdate::InjectBotsVersionColumn()
|
||||
m_database->QueryDatabase("ALTER TABLE db_version ADD bots_version int(11) DEFAULT '0' AFTER version");
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseUpdate::InjectCustomVersionColumn()
|
||||
{
|
||||
auto results = m_database->QueryDatabase("SHOW COLUMNS FROM `db_version` LIKE 'custom_version'");
|
||||
if (!results.Success() || results.RowCount() == 0) {
|
||||
LogInfo("Adding custom_version column to db_version table");
|
||||
m_database->QueryDatabase("ALTER TABLE `db_version` ADD COLUMN `custom_version` INT(11) UNSIGNED NOT NULL DEFAULT 0");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ struct ManifestEntry {
|
||||
struct DatabaseVersion {
|
||||
int server_database_version;
|
||||
int bots_database_version;
|
||||
int custom_database_version;
|
||||
};
|
||||
|
||||
class DatabaseUpdate {
|
||||
@@ -33,20 +32,12 @@ public:
|
||||
DatabaseUpdate *SetContentDatabase(Database *db);
|
||||
DatabaseUpdate *SetSkipBackup(bool skip);
|
||||
bool HasPendingUpdates();
|
||||
|
||||
static DatabaseUpdate* Instance()
|
||||
{
|
||||
static DatabaseUpdate instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_skip_backup = false;
|
||||
Database *m_database;
|
||||
Database *m_content_database;
|
||||
static bool CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b);
|
||||
void InjectBotsVersionColumn();
|
||||
void InjectCustomVersionColumn();
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -6417,7 +6417,7 @@ ADD COLUMN `guid` bigint(20) UNSIGNED NOT NULL DEFAULT 0 AFTER `ornament_hero_mo
|
||||
ADD PRIMARY KEY (`account_id`, `slot_id`);
|
||||
)",
|
||||
.content_schema_update = false,
|
||||
.force_interactive = false
|
||||
.force_interactive = true
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9298,
|
||||
@@ -6481,7 +6481,7 @@ UPDATE `sharedbank` SET `slot_id` = ((`slot_id` - 2531) + 11010) WHERE `slot_id`
|
||||
UPDATE `sharedbank` SET `slot_id` = ((`slot_id` - 2541) + 11210) WHERE `slot_id` BETWEEN 2541 AND 2550; -- Shared Bank Bag 2
|
||||
)",
|
||||
.content_schema_update = false,
|
||||
.force_interactive = false
|
||||
.force_interactive = true
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9299,
|
||||
@@ -6770,372 +6770,7 @@ SET `aliases` =
|
||||
WHERE `command` = 'illusionblock'
|
||||
AND `aliases` NOT LIKE '%ib%';
|
||||
)",
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9303,
|
||||
.description = "2025_02_13_corpse_slot_fix.sql",
|
||||
.check = "SELECT * FROM `character_corpse_items` WHERE `equip_slot` BETWEEN 251 AND 350",
|
||||
.condition = "not_empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
UPDATE `character_corpse_items` SET `equip_slot` = ((`equip_slot` - 251) + 4010) WHERE `equip_slot` BETWEEN 251 AND 260; -- Bag 1
|
||||
UPDATE `character_corpse_items` SET `equip_slot` = ((`equip_slot` - 261) + 4210) WHERE `equip_slot` BETWEEN 261 AND 270; -- Bag 2
|
||||
UPDATE `character_corpse_items` SET `equip_slot` = ((`equip_slot` - 271) + 4410) WHERE `equip_slot` BETWEEN 271 AND 280; -- Bag 3
|
||||
UPDATE `character_corpse_items` SET `equip_slot` = ((`equip_slot` - 281) + 4610) WHERE `equip_slot` BETWEEN 281 AND 290; -- Bag 4
|
||||
UPDATE `character_corpse_items` SET `equip_slot` = ((`equip_slot` - 291) + 4810) WHERE `equip_slot` BETWEEN 291 AND 300; -- Bag 5
|
||||
UPDATE `character_corpse_items` SET `equip_slot` = ((`equip_slot` - 301) + 5010) WHERE `equip_slot` BETWEEN 301 AND 310; -- Bag 6
|
||||
UPDATE `character_corpse_items` SET `equip_slot` = ((`equip_slot` - 311) + 5210) WHERE `equip_slot` BETWEEN 311 AND 320; -- Bag 7
|
||||
UPDATE `character_corpse_items` SET `equip_slot` = ((`equip_slot` - 321) + 5410) WHERE `equip_slot` BETWEEN 321 AND 330; -- Bag 8
|
||||
UPDATE `character_corpse_items` SET `equip_slot` = ((`equip_slot` - 331) + 5610) WHERE `equip_slot` BETWEEN 331 AND 340; -- Bag 9
|
||||
UPDATE `character_corpse_items` SET `equip_slot` = ((`equip_slot` - 341) + 5810) WHERE `equip_slot` BETWEEN 341 AND 350; -- Bag 10
|
||||
)",
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9304,
|
||||
.description = "2024_12_01_update_guild_bank",
|
||||
.check = "SHOW COLUMNS FROM `guild_bank` LIKE 'augment_one_id'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `guild_bank`
|
||||
DROP INDEX `guildid`,
|
||||
CHANGE COLUMN `guildid` `guild_id` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `id`,
|
||||
CHANGE COLUMN `itemid` `item_id` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `slot`,
|
||||
CHANGE COLUMN `whofor` `who_for` VARCHAR(64) NULL DEFAULT NULL COLLATE 'utf8_general_ci' AFTER `permissions`,
|
||||
ADD COLUMN `augment_one_id` INT UNSIGNED NULL DEFAULT '0' AFTER `item_id`,
|
||||
ADD COLUMN `augment_two_id` INT UNSIGNED NULL DEFAULT '0' AFTER `augment_one_id`,
|
||||
ADD COLUMN `augment_three_id` INT UNSIGNED NULL DEFAULT '0' AFTER `augment_two_id`,
|
||||
ADD COLUMN `augment_four_id` INT UNSIGNED NULL DEFAULT '0' AFTER `augment_three_id`,
|
||||
ADD COLUMN `augment_five_id` INT UNSIGNED NULL DEFAULT '0' AFTER `augment_four_id`,
|
||||
ADD COLUMN `augment_six_id` INT UNSIGNED NULL DEFAULT '0' AFTER `augment_five_id`,
|
||||
CHANGE COLUMN `qty` `quantity` INT(10) NOT NULL DEFAULT '0' AFTER `augment_six_id`;
|
||||
ALTER TABLE `guild_bank`
|
||||
ADD INDEX `guild_id` (`guild_id`);
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9305,
|
||||
.description = "2024_12_01_expedition_dz_merge.sql",
|
||||
.check = "SHOW COLUMNS FROM `dynamic_zones` LIKE 'is_locked'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `dynamic_zones`
|
||||
ADD COLUMN `is_locked` TINYINT NOT NULL DEFAULT '0' AFTER `has_zone_in`,
|
||||
ADD COLUMN `add_replay` TINYINT NOT NULL DEFAULT '1' AFTER `is_locked`;
|
||||
|
||||
ALTER TABLE `expedition_lockouts`
|
||||
CHANGE COLUMN `expedition_id` `dynamic_zone_id` INT(10) UNSIGNED NOT NULL AFTER `id`,
|
||||
DROP INDEX `expedition_id_event_name`,
|
||||
ADD UNIQUE INDEX `dz_id_event_name` (`dynamic_zone_id`, `event_name`) USING BTREE;
|
||||
|
||||
UPDATE expedition_lockouts lockouts
|
||||
INNER JOIN expeditions ON lockouts.dynamic_zone_id = expeditions.id
|
||||
SET lockouts.dynamic_zone_id = expeditions.dynamic_zone_id;
|
||||
|
||||
DROP TABLE `expeditions`;
|
||||
|
||||
RENAME TABLE `expedition_lockouts` TO `dynamic_zone_lockouts`;
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9306,
|
||||
.description = "2025_02_16_data_buckets_zone_id_instance_id.sql",
|
||||
.check = "SHOW COLUMNS FROM `data_buckets` LIKE 'zone_id'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
-- Drop old indexes if exists
|
||||
DROP INDEX IF EXISTS `keys` ON `data_buckets`;
|
||||
DROP INDEX IF EXISTS `idx_npc_expires` ON `data_buckets`;
|
||||
DROP INDEX IF EXISTS `idx_bot_expires` ON `data_buckets`;
|
||||
|
||||
-- Add zone_id, instance_id
|
||||
ALTER TABLE `data_buckets`
|
||||
MODIFY COLUMN `npc_id` int(11) NOT NULL DEFAULT 0 AFTER `character_id`,
|
||||
MODIFY COLUMN `bot_id` int(11) NOT NULL DEFAULT 0 AFTER `npc_id`,
|
||||
ADD COLUMN `zone_id` smallint(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `bot_id`,
|
||||
ADD COLUMN `instance_id` smallint(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `zone_id`;
|
||||
|
||||
ALTER TABLE `data_buckets`
|
||||
MODIFY COLUMN `account_id` bigint(11) UNSIGNED NULL DEFAULT 0 AFTER `expires`,
|
||||
MODIFY COLUMN `character_id` bigint(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `account_id`,
|
||||
MODIFY COLUMN `npc_id` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `character_id`,
|
||||
MODIFY COLUMN `bot_id` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `npc_id`;
|
||||
|
||||
-- Create optimized unique index with `key` first
|
||||
CREATE UNIQUE INDEX `keys` ON data_buckets (`key`, character_id, npc_id, bot_id, account_id, zone_id, instance_id);
|
||||
|
||||
-- Create indexes for just instance_id (instance deletion)
|
||||
CREATE INDEX idx_instance_id ON data_buckets (instance_id);
|
||||
)",
|
||||
.content_schema_update = false
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9307,
|
||||
.description = "2025_02_17_zone_state_spawns.sql",
|
||||
.check = "SHOW TABLES LIKE 'zone_state_spawns'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
CREATE TABLE `zone_state_spawns` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`zone_id` int(11) unsigned DEFAULT NULL,
|
||||
`instance_id` int(11) unsigned DEFAULT NULL,
|
||||
`is_corpse` tinyint(11) DEFAULT 0,
|
||||
`decay_in_seconds` int(11) DEFAULT 0,
|
||||
`npc_id` int(10) unsigned DEFAULT NULL,
|
||||
`spawn2_id` int(10) unsigned NOT NULL,
|
||||
`spawngroup_id` int(10) unsigned NOT NULL,
|
||||
`x` float NOT NULL,
|
||||
`y` float NOT NULL,
|
||||
`z` float NOT NULL,
|
||||
`heading` float NOT NULL,
|
||||
`respawn_time` int(10) unsigned NOT NULL,
|
||||
`variance` int(10) unsigned NOT NULL,
|
||||
`grid` int(10) unsigned DEFAULT 0,
|
||||
`current_waypoint` int(11) DEFAULT 0,
|
||||
`path_when_zone_idle` smallint(6) DEFAULT 0,
|
||||
`condition_id` smallint(5) unsigned DEFAULT 0,
|
||||
`condition_min_value` smallint(6) DEFAULT 0,
|
||||
`enabled` smallint(6) DEFAULT 1,
|
||||
`anim` smallint(5) unsigned DEFAULT 0,
|
||||
`loot_data` text DEFAULT NULL,
|
||||
`entity_variables` text DEFAULT NULL,
|
||||
`buffs` text DEFAULT NULL,
|
||||
`hp` bigint(20) DEFAULT 0,
|
||||
`mana` bigint(20) DEFAULT 0,
|
||||
`endurance` bigint(20) DEFAULT 0,
|
||||
`created_at` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4
|
||||
)",
|
||||
.content_schema_update = false
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9308,
|
||||
.description = "2025_03_29_add_multivalue_support_to_evolving_subtype.sql",
|
||||
.check = "SHOW COLUMNS FROM `items_evolving_details` LIKE 'sub_type'",
|
||||
.condition = "missing",
|
||||
.match = "varchar(200)",
|
||||
.sql = R"(
|
||||
ALTER TABLE `items_evolving_details`
|
||||
CHANGE COLUMN `sub_type` `sub_type` VARCHAR(200) NULL DEFAULT '0' AFTER `type`;
|
||||
)",
|
||||
.content_schema_update = true
|
||||
},
|
||||
// this one got missed being added to PEQ dumps so adding it again so it gets added when folks take a new release
|
||||
ManifestEntry{
|
||||
.version = 9309,
|
||||
.description = "2025_03_1_create_pet_names_table_if_not_exist.sql",
|
||||
.check = "SHOW TABLES LIKE 'character_pet_name'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
CREATE TABLE `character_pet_name` (
|
||||
`character_id` INT(11) NOT NULL PRIMARY KEY,
|
||||
`name` VARCHAR(64) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
)",
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9310,
|
||||
.description = "2025_03_7_expand_horse_def.sql",
|
||||
.check = "SHOW COLUMNS FROM `horses` LIKE 'helmtexture'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `horses`
|
||||
ADD COLUMN `helmtexture` TINYINT(2) NOT NULL DEFAULT -1 AFTER `texture`;
|
||||
)",
|
||||
.content_schema_update = true
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9311,
|
||||
.description = "2025_03_09_add_zone_state_is_zone_field.sql",
|
||||
.check = "SHOW COLUMNS FROM `zone_state_spawns` LIKE 'is_zone'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `zone_state_spawns`
|
||||
ADD COLUMN `is_zone` tinyint(11) NULL DEFAULT 0 AFTER `is_corpse`;
|
||||
)",
|
||||
.content_schema_update = false
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9312,
|
||||
.description = "2025_03_11_data_bucket_indexes.sql",
|
||||
.check = "SHOW INDEX FROM data_buckets",
|
||||
.condition = "missing",
|
||||
.match = "idx_zone_instance_expires",
|
||||
.sql = R"(
|
||||
DROP INDEX IF EXISTS `idx_zone_instance_expires` ON `data_buckets`;
|
||||
DROP INDEX IF EXISTS `idx_character_expires` ON `data_buckets`;
|
||||
DROP INDEX IF EXISTS `idx_bot_expires` ON `data_buckets`;
|
||||
ALTER TABLE data_buckets ADD INDEX idx_zone_instance_expires (zone_id, instance_id, expires);
|
||||
ALTER TABLE data_buckets ADD INDEX idx_character_expires (character_id, expires);
|
||||
ALTER TABLE data_buckets ADD INDEX idx_bot_expires (bot_id, expires);
|
||||
)",
|
||||
.content_schema_update = false
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9313,
|
||||
.description = "2025_03_11_zone_state_spawns.sql",
|
||||
.check = "SHOW INDEX FROM zone_state_spawns",
|
||||
.condition = "missing",
|
||||
.match = "idx_zone_instance",
|
||||
.sql = R"(
|
||||
ALTER TABLE zone_state_spawns ADD INDEX idx_zone_instance (zone_id, instance_id);
|
||||
)",
|
||||
.content_schema_update = false
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9314,
|
||||
.description = "2025_03_12_zone_state_spawns_one_time_truncate.sql",
|
||||
.check = "SELECT * FROM db_version WHERE version >= 9314",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
TRUNCATE TABLE zone_state_spawns;
|
||||
)",
|
||||
.content_schema_update = false
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9315,
|
||||
.description = "2025_03_29_character_tribute_index.sql",
|
||||
.check = "SHOW INDEX FROM character_tribute",
|
||||
.condition = "missing",
|
||||
.match = "idx_character_id",
|
||||
.sql = R"(
|
||||
ALTER TABLE character_tribute ADD INDEX idx_character_id (character_id);
|
||||
)",
|
||||
.content_schema_update = false
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9316,
|
||||
.description = "2025_03_29_player_titlesets_index.sql",
|
||||
.check = "SHOW INDEX FROM player_titlesets",
|
||||
.condition = "missing",
|
||||
.match = "idx_char_id",
|
||||
.sql = R"(
|
||||
ALTER TABLE player_titlesets ADD INDEX idx_char_id (char_id);
|
||||
)",
|
||||
.content_schema_update = false
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9317,
|
||||
.description = "2025_03_29_respawn_times_instance_index.sql",
|
||||
.check = "SHOW INDEX FROM respawn_times",
|
||||
.condition = "missing",
|
||||
.match = "idx_instance_id",
|
||||
.sql = R"(
|
||||
ALTER TABLE respawn_times ADD INDEX idx_instance_id (instance_id);
|
||||
)",
|
||||
.content_schema_update = false
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9318,
|
||||
.description = "2025_03_29_zone_state_spawns_instance_index.sql",
|
||||
.check = "SHOW INDEX FROM zone_state_spawns",
|
||||
.condition = "missing",
|
||||
.match = "idx_instance_id",
|
||||
.sql = R"(
|
||||
ALTER TABLE zone_state_spawns ADD INDEX idx_instance_id (instance_id);
|
||||
)",
|
||||
.content_schema_update = false
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9319,
|
||||
.description = "2025_03_29_data_buckets_expires_index.sql",
|
||||
.check = "SHOW INDEX FROM data_buckets",
|
||||
.condition = "missing",
|
||||
.match = "idx_expires",
|
||||
.sql = R"(
|
||||
CREATE INDEX idx_expires ON data_buckets (expires);
|
||||
)",
|
||||
.content_schema_update = false
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9320,
|
||||
.description = "2025_03_23_add_respawn_times_expire_at.sql",
|
||||
.check = "SHOW COLUMNS FROM `respawn_times` LIKE 'expire_at'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `respawn_times`
|
||||
ADD COLUMN `expire_at` int(11) UNSIGNED NULL DEFAULT 0 AFTER `duration`;
|
||||
|
||||
UPDATE respawn_times set expire_at = `start` + `duration`; -- backfill existing data
|
||||
|
||||
CREATE INDEX `idx_expire_at` ON `respawn_times` (`expire_at`);
|
||||
)",
|
||||
.content_schema_update = false
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9321,
|
||||
.description = "2025_03_30_instance_list_add_expire_at.sql",
|
||||
.check = "SHOW COLUMNS FROM `instance_list` LIKE 'expire_at'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `instance_list`
|
||||
ADD COLUMN `expire_at` bigint(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `duration`;
|
||||
|
||||
UPDATE instance_list set expire_at = `start_time` + `duration`; -- backfill existing data
|
||||
|
||||
CREATE INDEX `idx_expire_at` ON `instance_list` (`expire_at`);
|
||||
)",
|
||||
.content_schema_update = false
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9322,
|
||||
.description = "2025_04_24_add_npc_tint_id.sql",
|
||||
.check = "SHOW COLUMNS FROM `npc_types` LIKE 'npc_tint_id'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `npc_types`
|
||||
ADD COLUMN `npc_tint_id` SMALLINT UNSIGNED NULL DEFAULT '0' AFTER `multiquest_enabled`;
|
||||
)",
|
||||
.content_schema_update = true
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9323,
|
||||
.description = "2025_04_16_character_data_first_login.sql",
|
||||
.check = "SHOW COLUMNS FROM `character_data` LIKE 'first_login'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `character_data`
|
||||
CHANGE COLUMN `firstlogon` `ingame` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 AFTER `xtargets`,
|
||||
ADD COLUMN `first_login` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `xtargets`;
|
||||
)",
|
||||
.content_schema_update = false
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9324,
|
||||
.description = "2025_06_11_player_event_logs_table.sql",
|
||||
.check = "SHOW CREATE TABLE `player_event_logs`",
|
||||
.condition = "missing",
|
||||
.match = "COMPRESS",
|
||||
.sql = R"(
|
||||
ALTER TABLE player_event_logs ROW_FORMAT=COMPRESSED;
|
||||
CREATE INDEX idx_event_type_char_id ON player_event_logs (event_type_id, character_id);
|
||||
)",
|
||||
.content_schema_update = false
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9325,
|
||||
.description = "2025_06_10_character_corpses_entity_variables.sql",
|
||||
.check = "SHOW COLUMNS FROM `character_corpses` LIKE 'entity_variables'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `character_corpses`
|
||||
ADD COLUMN `entity_variables` TEXT DEFAULT NULL AFTER `rezzable`;
|
||||
)",
|
||||
.content_schema_update = false
|
||||
},
|
||||
}
|
||||
// -- template; copy/paste this when you need to create a new entry
|
||||
// ManifestEntry{
|
||||
// .version = 9228,
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
#include "database_update.h"
|
||||
|
||||
std::vector<ManifestEntry> manifest_entries_custom = {
|
||||
ManifestEntry{
|
||||
.version = 1,
|
||||
.description = "2025_05_16_new_database_check_test",
|
||||
.check = "SHOW TABLES LIKE 'new_table'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
CREATE TABLE `new_table` (
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
)",
|
||||
.content_schema_update = false,
|
||||
},
|
||||
// Used for testing
|
||||
// ManifestEntry{
|
||||
// .version = 9229,
|
||||
// .description = "new_database_check_test",
|
||||
// .check = "SHOW TABLES LIKE 'new_table'",
|
||||
// .condition = "empty",
|
||||
// .match = "",
|
||||
// .sql = R"(
|
||||
//CREATE TABLE `new_table` (
|
||||
// `id` int NOT NULL AUTO_INCREMENT,
|
||||
// PRIMARY KEY (`id`)
|
||||
//);
|
||||
//CREATE TABLE `new_table1` (
|
||||
// `id` int NOT NULL AUTO_INCREMENT,
|
||||
// PRIMARY KEY (`id`)
|
||||
//);
|
||||
//CREATE TABLE `new_table2` (
|
||||
// `id` int NOT NULL AUTO_INCREMENT,
|
||||
// PRIMARY KEY (`id`)
|
||||
//);
|
||||
//CREATE TABLE `new_table3` (
|
||||
// `id` int NOT NULL AUTO_INCREMENT,
|
||||
// PRIMARY KEY (`id`)
|
||||
//);
|
||||
//)",
|
||||
// }
|
||||
|
||||
};
|
||||
|
||||
// see struct definitions for what each field does
|
||||
// struct ManifestEntry {
|
||||
// int version{}; // database version of the migration
|
||||
// std::string description{}; // description of the migration ex: "add_new_table" or "add_index_to_table"
|
||||
// std::string check{}; // query that checks against the condition
|
||||
// std::string condition{}; // condition or "match_type" - Possible values [contains|match|missing|empty|not_empty]
|
||||
// std::string match{}; // match field that is not always used, but works in conjunction with "condition" values [missing|match|contains]
|
||||
// std::string sql{}; // the SQL DDL that gets ran when the condition is true
|
||||
// };
|
||||
@@ -30,8 +30,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "../common/repositories/respawn_times_repository.h"
|
||||
#include "../common/repositories/spawn_condition_values_repository.h"
|
||||
#include "repositories/spawn2_disabled_repository.h"
|
||||
#include "repositories/data_buckets_repository.h"
|
||||
#include "repositories/zone_state_spawns_repository.h"
|
||||
|
||||
|
||||
#include "database.h"
|
||||
|
||||
#include <iomanip>
|
||||
@@ -128,35 +128,11 @@ bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version
|
||||
e.version = version;
|
||||
e.start_time = std::time(nullptr);
|
||||
e.duration = duration;
|
||||
e.expire_at = e.start_time + duration;
|
||||
|
||||
RespawnTimesRepository::ClearInstanceTimers(*this, e.id);
|
||||
InstanceListRepository::ReplaceOne(*this, e);
|
||||
return instance_id > 0 && e.id;
|
||||
return InstanceListRepository::InsertOne(*this, e).id;
|
||||
}
|
||||
|
||||
bool Database::GetUnusedInstanceID(uint16 &instance_id)
|
||||
{
|
||||
// attempt to get an unused instance id
|
||||
for (int a = 0; a < 10; a++) {
|
||||
uint16 attempted_id = 0;
|
||||
if (TryGetUnusedInstanceID(attempted_id)) {
|
||||
auto i = InstanceListRepository::NewEntity();
|
||||
i.id = attempted_id;
|
||||
i.notes = "Prefetching";
|
||||
auto n = InstanceListRepository::InsertOne(*this, i);
|
||||
if (n.id > 0) {
|
||||
instance_id = n.id;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
instance_id = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Database::TryGetUnusedInstanceID(uint16 &instance_id)
|
||||
{
|
||||
uint32 max_reserved_instance_id = RuleI(Instances, ReservedInstances);
|
||||
uint32 max_instance_id = 32000;
|
||||
@@ -503,10 +479,6 @@ void Database::DeleteInstance(uint16 instance_id)
|
||||
DynamicZoneMembersRepository::DeleteByInstance(*this, instance_id);
|
||||
DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id));
|
||||
CharacterCorpsesRepository::BuryInstance(*this, instance_id);
|
||||
DataBucketsRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id));
|
||||
if (RuleB(Zone, StateSavingOnShutdown)) {
|
||||
ZoneStateSpawnsRepository::DeleteWhere(*this, fmt::format("`instance_id` = {}", instance_id));
|
||||
}
|
||||
}
|
||||
|
||||
void Database::FlagInstanceByGroupLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 group_id)
|
||||
@@ -561,12 +533,14 @@ void Database::GetCharactersInInstance(uint16 instance_id, std::list<uint32> &ch
|
||||
|
||||
void Database::PurgeExpiredInstances()
|
||||
{
|
||||
/**
|
||||
* Delay purging by a day so that we can continue using adjacent free instance id's
|
||||
* from the table without risking the chance we immediately re-allocate a zone that freshly expired but
|
||||
* has not been fully de-allocated
|
||||
*/
|
||||
auto l = InstanceListRepository::GetWhere(
|
||||
*this,
|
||||
fmt::format(
|
||||
"expire_at <= (UNIX_TIMESTAMP() - {}) and expire_at != 0 AND never_expires = 0",
|
||||
RuleI(Instances, ExpireOffsetTimeSeconds)
|
||||
)
|
||||
"(start_time + duration) <= (UNIX_TIMESTAMP() - 86400) AND never_expires = 0"
|
||||
);
|
||||
if (l.empty()) {
|
||||
return;
|
||||
@@ -577,24 +551,16 @@ void Database::PurgeExpiredInstances()
|
||||
instance_ids.emplace_back(std::to_string(e.id));
|
||||
}
|
||||
|
||||
const auto ids = Strings::Implode(",", instance_ids);
|
||||
const auto imploded_instance_ids = Strings::Implode(",", instance_ids);
|
||||
|
||||
TransactionBegin();
|
||||
InstanceListRepository::DeleteWhere(*this, fmt::format("id IN ({})", ids));
|
||||
InstanceListPlayerRepository::DeleteWhere(*this, fmt::format("id IN ({})", ids));
|
||||
RespawnTimesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", ids));
|
||||
SpawnConditionValuesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", ids));
|
||||
CharacterCorpsesRepository::BuryInstances(*this, ids);
|
||||
DynamicZoneMembersRepository::DeleteByManyInstances(*this, ids);
|
||||
DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", ids));
|
||||
Spawn2DisabledRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", ids));
|
||||
DataBucketsRepository::DeleteWhere(*this, fmt::format("instance_id != 0 and instance_id IN ({})", ids));
|
||||
if (RuleB(Zone, StateSavingOnShutdown)) {
|
||||
ZoneStateSpawnsRepository::DeleteWhere(*this, fmt::format("`instance_id` IN ({})", ids));
|
||||
}
|
||||
TransactionCommit();
|
||||
|
||||
LogInfo("Purged [{}] expired instances", l.size());
|
||||
InstanceListRepository::DeleteWhere(*this, fmt::format("id IN ({})", imploded_instance_ids));
|
||||
InstanceListPlayerRepository::DeleteWhere(*this, fmt::format("id IN ({})", imploded_instance_ids));
|
||||
RespawnTimesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
|
||||
SpawnConditionValuesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
|
||||
CharacterCorpsesRepository::BuryInstances(*this, imploded_instance_ids);
|
||||
DynamicZoneMembersRepository::DeleteByManyInstances(*this, imploded_instance_ids);
|
||||
DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
|
||||
Spawn2DisabledRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
|
||||
}
|
||||
|
||||
void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration)
|
||||
@@ -606,7 +572,6 @@ void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration)
|
||||
|
||||
i.start_time = std::time(nullptr);
|
||||
i.duration = new_duration;
|
||||
i.expire_at = i.start_time + i.duration;
|
||||
|
||||
InstanceListRepository::UpdateOne(*this, i);
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace DatabaseSchema {
|
||||
{"guild_members", "char_id"},
|
||||
{"guilds", "id"},
|
||||
{"instance_list_player", "id"},
|
||||
{"inventory", "character_id"},
|
||||
{"inventory", "charid"},
|
||||
{"inventory_snapshots", "charid"},
|
||||
{"keyring", "char_id"},
|
||||
{"mail", "charid"},
|
||||
@@ -139,7 +139,6 @@ namespace DatabaseSchema {
|
||||
"character_pet_buffs",
|
||||
"character_pet_info",
|
||||
"character_pet_inventory",
|
||||
"character_pet_name",
|
||||
"character_peqzone_flags",
|
||||
"character_potionbelt",
|
||||
"character_skills",
|
||||
@@ -312,9 +311,10 @@ namespace DatabaseSchema {
|
||||
"completed_shared_task_members",
|
||||
"completed_shared_tasks",
|
||||
"discord_webhooks",
|
||||
"dynamic_zone_lockouts",
|
||||
"dynamic_zone_members",
|
||||
"dynamic_zones",
|
||||
"expedition_lockouts",
|
||||
"expeditions",
|
||||
"gm_ips",
|
||||
"group_id",
|
||||
"group_leaders",
|
||||
@@ -351,7 +351,6 @@ namespace DatabaseSchema {
|
||||
"shared_task_dynamic_zones",
|
||||
"shared_task_members",
|
||||
"shared_tasks",
|
||||
"zone_state_spawns",
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+4
-6
@@ -160,7 +160,7 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
|
||||
(uint32) mysql_insert_id(mysql)
|
||||
);
|
||||
|
||||
if (EQEmuLogSys::Instance()->log_settings[Logs::MySQLQuery].is_category_enabled == 1) {
|
||||
if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1) {
|
||||
if ((strncasecmp(query, "select", 6) == 0)) {
|
||||
LogMySQLQuery(
|
||||
"{0} -- ({1} row{2} returned) ({3}s)",
|
||||
@@ -189,9 +189,9 @@ void DBcore::TransactionBegin()
|
||||
QueryDatabase("START TRANSACTION");
|
||||
}
|
||||
|
||||
MySQLRequestResult DBcore::TransactionCommit()
|
||||
void DBcore::TransactionCommit()
|
||||
{
|
||||
return QueryDatabase("COMMIT");
|
||||
QueryDatabase("COMMIT");
|
||||
}
|
||||
|
||||
void DBcore::TransactionRollback()
|
||||
@@ -302,9 +302,7 @@ std::string DBcore::Escape(const std::string& s)
|
||||
|
||||
void DBcore::SetMutex(Mutex *mutex)
|
||||
{
|
||||
if (m_mutex && m_mutex != mutex) {
|
||||
safe_delete(m_mutex);
|
||||
}
|
||||
safe_delete(m_mutex);
|
||||
|
||||
DBcore::m_mutex = mutex;
|
||||
}
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ public:
|
||||
MySQLRequestResult QueryDatabase(const std::string& query, bool retryOnFailureOnce = true);
|
||||
MySQLRequestResult QueryDatabaseMulti(const std::string &query);
|
||||
void TransactionBegin();
|
||||
MySQLRequestResult TransactionCommit();
|
||||
void TransactionCommit();
|
||||
void TransactionRollback();
|
||||
std::string Escape(const std::string& s);
|
||||
uint32 DoEscapeString(char *tobuf, const char *frombuf, uint32 fromlen);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <string>
|
||||
#include "../types.h"
|
||||
#include "../http/httplib.h"
|
||||
#include "../repositories/player_event_logs_repository.h"
|
||||
#include "../events/player_events.h"
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ void DiscordManager::ProcessMessageQueue()
|
||||
continue;
|
||||
}
|
||||
|
||||
auto webhook = EQEmuLogSys::Instance()->GetDiscordWebhooks()[q.first];
|
||||
auto webhook = LogSys.GetDiscordWebhooks()[q.first];
|
||||
std::string message;
|
||||
|
||||
for (auto &m: q.second) {
|
||||
@@ -68,7 +68,7 @@ void DiscordManager::ProcessMessageQueue()
|
||||
|
||||
void DiscordManager::QueuePlayerEventMessage(const PlayerEvent::PlayerEventContainer& e)
|
||||
{
|
||||
auto w = PlayerEventLogs::Instance()->GetDiscordWebhookUrlFromEventType(e.player_event_log.event_type_id);
|
||||
auto w = player_event_logs.GetDiscordWebhookUrlFromEventType(e.player_event_log.event_type_id);
|
||||
if (!w.empty()) {
|
||||
Discord::SendPlayerEventMessage(e, w);
|
||||
}
|
||||
|
||||
@@ -13,12 +13,6 @@ public:
|
||||
void QueueWebhookMessage(uint32 webhook_id, const std::string& message);
|
||||
void ProcessMessageQueue();
|
||||
void QueuePlayerEventMessage(const PlayerEvent::PlayerEventContainer& e);
|
||||
|
||||
static DiscordManager* Instance()
|
||||
{
|
||||
static DiscordManager instance;
|
||||
return &instance;
|
||||
}
|
||||
private:
|
||||
std::mutex webhook_queue_lock{};
|
||||
std::map<uint32, std::vector<std::string>> webhook_message_queue{};
|
||||
|
||||
+67
-297
@@ -1,13 +1,11 @@
|
||||
#include "dynamic_zone_base.h"
|
||||
#include "database.h"
|
||||
#include "eqemu_logsys.h"
|
||||
#include "repositories/instance_list_repository.h"
|
||||
#include "repositories/instance_list_player_repository.h"
|
||||
#include "rulesys.h"
|
||||
#include "servertalk.h"
|
||||
#include "util/uuid.h"
|
||||
#include "repositories/character_expedition_lockouts_repository.h"
|
||||
#include "repositories/dynamic_zone_lockouts_repository.h"
|
||||
#include "repositories/instance_list_repository.h"
|
||||
#include "repositories/instance_list_player_repository.h"
|
||||
|
||||
DynamicZoneBase::DynamicZoneBase(DynamicZonesRepository::DynamicZoneInstance&& entry)
|
||||
{
|
||||
@@ -58,16 +56,15 @@ uint32_t DynamicZoneBase::CreateInstance()
|
||||
insert_instance.start_time = static_cast<int>(std::chrono::system_clock::to_time_t(m_start_time));
|
||||
insert_instance.duration = static_cast<int>(m_duration.count());
|
||||
insert_instance.never_expires = m_never_expires;
|
||||
insert_instance.expire_at = insert_instance.start_time + insert_instance.duration;
|
||||
|
||||
auto instance = InstanceListRepository::ReplaceOne(GetDatabase(), insert_instance);
|
||||
if (!instance)
|
||||
auto instance = InstanceListRepository::InsertOne(GetDatabase(), insert_instance);
|
||||
if (instance.id == 0)
|
||||
{
|
||||
LogDynamicZones("Failed to create instance [{}] for zone [{}]", unused_instance_id, m_zone_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_instance_id = unused_instance_id;
|
||||
m_instance_id = instance.id;
|
||||
|
||||
return m_instance_id;
|
||||
}
|
||||
@@ -96,15 +93,13 @@ void DynamicZoneBase::LoadRepositoryResult(DynamicZonesRepository::DynamicZoneIn
|
||||
m_zonein.y = dz_entry.zone_in_y;
|
||||
m_zonein.z = dz_entry.zone_in_z;
|
||||
m_zonein.heading = dz_entry.zone_in_heading;
|
||||
m_has_zonein = dz_entry.has_zone_in != 0;
|
||||
m_is_locked = dz_entry.is_locked;
|
||||
m_add_replay = dz_entry.add_replay;
|
||||
m_has_zonein = (dz_entry.has_zone_in != 0);
|
||||
// instance_list portion
|
||||
m_zone_id = dz_entry.zone;
|
||||
m_zone_version = dz_entry.version;
|
||||
m_start_time = std::chrono::system_clock::from_time_t(dz_entry.start_time);
|
||||
m_duration = std::chrono::seconds(dz_entry.duration);
|
||||
m_never_expires = dz_entry.never_expires != 0;
|
||||
m_never_expires = (dz_entry.never_expires != 0);
|
||||
m_expire_time = m_start_time + m_duration;
|
||||
}
|
||||
|
||||
@@ -124,40 +119,37 @@ void DynamicZoneBase::AddMemberFromRepositoryResult(
|
||||
uint32_t DynamicZoneBase::SaveToDatabase()
|
||||
{
|
||||
LogDynamicZonesDetail("Saving dz instance [{}] to database", m_instance_id);
|
||||
if (m_instance_id == 0)
|
||||
|
||||
if (m_instance_id != 0)
|
||||
{
|
||||
return 0;
|
||||
auto insert_dz = DynamicZonesRepository::NewEntity();
|
||||
insert_dz.uuid = m_uuid;
|
||||
insert_dz.name = m_name;
|
||||
insert_dz.leader_id = m_leader.id;
|
||||
insert_dz.min_players = m_min_players;
|
||||
insert_dz.max_players = m_max_players;
|
||||
insert_dz.instance_id = m_instance_id,
|
||||
insert_dz.type = static_cast<int>(m_type);
|
||||
insert_dz.dz_switch_id = m_dz_switch_id;
|
||||
insert_dz.compass_zone_id = m_compass.zone_id;
|
||||
insert_dz.compass_x = m_compass.x;
|
||||
insert_dz.compass_y = m_compass.y;
|
||||
insert_dz.compass_z = m_compass.z;
|
||||
insert_dz.safe_return_zone_id = m_safereturn.zone_id;
|
||||
insert_dz.safe_return_x = m_safereturn.x;
|
||||
insert_dz.safe_return_y = m_safereturn.y;
|
||||
insert_dz.safe_return_z = m_safereturn.z;
|
||||
insert_dz.safe_return_heading = m_safereturn.heading;
|
||||
insert_dz.zone_in_x = m_zonein.x;
|
||||
insert_dz.zone_in_y = m_zonein.y;
|
||||
insert_dz.zone_in_z = m_zonein.z;
|
||||
insert_dz.zone_in_heading = m_zonein.heading;
|
||||
insert_dz.has_zone_in = m_has_zonein;
|
||||
|
||||
auto inserted_dz = DynamicZonesRepository::InsertOne(GetDatabase(), insert_dz);
|
||||
return inserted_dz.id;
|
||||
}
|
||||
|
||||
auto dz = DynamicZonesRepository::NewEntity();
|
||||
dz.uuid = m_uuid;
|
||||
dz.name = m_name;
|
||||
dz.leader_id = m_leader.id;
|
||||
dz.min_players = m_min_players;
|
||||
dz.max_players = m_max_players;
|
||||
dz.instance_id = static_cast<int32_t>(m_instance_id),
|
||||
dz.type = static_cast<uint8_t>(m_type);
|
||||
dz.dz_switch_id = m_dz_switch_id;
|
||||
dz.compass_zone_id = m_compass.zone_id;
|
||||
dz.compass_x = m_compass.x;
|
||||
dz.compass_y = m_compass.y;
|
||||
dz.compass_z = m_compass.z;
|
||||
dz.safe_return_zone_id = m_safereturn.zone_id;
|
||||
dz.safe_return_x = m_safereturn.x;
|
||||
dz.safe_return_y = m_safereturn.y;
|
||||
dz.safe_return_z = m_safereturn.z;
|
||||
dz.safe_return_heading = m_safereturn.heading;
|
||||
dz.zone_in_x = m_zonein.x;
|
||||
dz.zone_in_y = m_zonein.y;
|
||||
dz.zone_in_z = m_zonein.z;
|
||||
dz.zone_in_heading = m_zonein.heading;
|
||||
dz.has_zone_in = static_cast<uint8_t>(m_has_zonein);
|
||||
dz.is_locked = static_cast<int8_t>(m_is_locked);
|
||||
dz.add_replay = static_cast<int8_t>(m_add_replay);
|
||||
|
||||
dz = DynamicZonesRepository::InsertOne(GetDatabase(), std::move(dz));
|
||||
|
||||
return dz.id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool DynamicZoneBase::AddMember(const DynamicZoneMember& add_member)
|
||||
@@ -204,9 +196,10 @@ bool DynamicZoneBase::RemoveMember(const DynamicZoneMember& remove_member)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DynamicZoneBase::SwapMember(const DynamicZoneMember& add_member, const std::string& remove_name)
|
||||
bool DynamicZoneBase::SwapMember(
|
||||
const DynamicZoneMember& add_member, const std::string& remove_char_name)
|
||||
{
|
||||
auto remove_member = GetMemberData(remove_name);
|
||||
auto remove_member = GetMemberData(remove_char_name);
|
||||
if (!add_member.IsValid() || !remove_member.IsValid())
|
||||
{
|
||||
return false;
|
||||
@@ -237,18 +230,9 @@ void DynamicZoneBase::RemoveAllMembers()
|
||||
|
||||
void DynamicZoneBase::SaveMembers(const std::vector<DynamicZoneMember>& members)
|
||||
{
|
||||
if (members.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LogDynamicZonesDetail("Saving [{}] member(s) for dz [{}]", members.size(), m_id);
|
||||
|
||||
m_members = members;
|
||||
if (m_members.size() > m_max_players)
|
||||
{
|
||||
m_members.resize(m_max_players);
|
||||
}
|
||||
|
||||
// the lower level instance_list_players needs to be kept updated as well
|
||||
std::vector<DynamicZoneMembersRepository::DynamicZoneMembers> insert_members;
|
||||
@@ -258,12 +242,12 @@ void DynamicZoneBase::SaveMembers(const std::vector<DynamicZoneMember>& members)
|
||||
DynamicZoneMembersRepository::DynamicZoneMembers member_entry{};
|
||||
member_entry.dynamic_zone_id = m_id;
|
||||
member_entry.character_id = member.id;
|
||||
insert_members.push_back(member_entry);
|
||||
insert_members.emplace_back(member_entry);
|
||||
|
||||
InstanceListPlayerRepository::InstanceListPlayer player_entry{};
|
||||
player_entry.id = m_instance_id;
|
||||
player_entry.charid = member.id;
|
||||
insert_players.push_back(player_entry);
|
||||
InstanceListPlayerRepository::InstanceListPlayer player_entry;
|
||||
player_entry.id = static_cast<int>(m_instance_id);
|
||||
player_entry.charid = static_cast<int>(member.id);
|
||||
insert_players.emplace_back(player_entry);
|
||||
}
|
||||
|
||||
DynamicZoneMembersRepository::InsertOrUpdateMany(GetDatabase(), insert_members);
|
||||
@@ -355,44 +339,6 @@ void DynamicZoneBase::SetLeader(const DynamicZoneMember& new_leader, bool update
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicZoneBase::SetLocked(bool lock, bool update_db, DzLockMsg lock_msg, uint32_t color)
|
||||
{
|
||||
m_is_locked = lock;
|
||||
|
||||
if (update_db)
|
||||
{
|
||||
DynamicZonesRepository::UpdateLocked(GetDatabase(), m_id, lock);
|
||||
|
||||
ServerPacket pack(ServerOP_DzLock, sizeof(ServerDzLock_Struct));
|
||||
auto buf = reinterpret_cast<ServerDzLock_Struct*>(pack.pBuffer);
|
||||
buf->dz_id = GetID();
|
||||
buf->sender_zone_id = GetCurrentZoneID();
|
||||
buf->sender_instance_id = GetCurrentInstanceID();
|
||||
buf->lock = m_is_locked;
|
||||
buf->lock_msg = static_cast<uint8_t>(lock_msg);
|
||||
buf->color = color;
|
||||
SendServerPacket(&pack);
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicZoneBase::SetReplayOnJoin(bool enabled, bool update_db)
|
||||
{
|
||||
m_add_replay = enabled;
|
||||
|
||||
if (update_db)
|
||||
{
|
||||
DynamicZonesRepository::UpdateReplayOnJoin(GetDatabase(), m_id, enabled);
|
||||
|
||||
ServerPacket pack(ServerOP_DzReplayOnJoin, sizeof(ServerDzBool_Struct));
|
||||
auto buf = reinterpret_cast<ServerDzBool_Struct*>(pack.pBuffer);
|
||||
buf->dz_id = GetID();
|
||||
buf->sender_zone_id = GetCurrentZoneID();
|
||||
buf->sender_instance_id = GetCurrentInstanceID();
|
||||
buf->enabled = enabled;
|
||||
SendServerPacket(&pack);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t DynamicZoneBase::GetSecondsRemaining() const
|
||||
{
|
||||
auto remaining = std::chrono::duration_cast<std::chrono::seconds>(GetDurationRemaining()).count();
|
||||
@@ -532,13 +478,13 @@ void DynamicZoneBase::RemoveInternalMember(uint32_t character_id)
|
||||
), m_members.end());
|
||||
}
|
||||
|
||||
bool DynamicZoneBase::HasMember(uint32_t character_id) const
|
||||
bool DynamicZoneBase::HasMember(uint32_t character_id)
|
||||
{
|
||||
return std::any_of(m_members.begin(), m_members.end(),
|
||||
[&](const DynamicZoneMember& member) { return member.id == character_id; });
|
||||
}
|
||||
|
||||
bool DynamicZoneBase::HasMember(const std::string& character_name) const
|
||||
bool DynamicZoneBase::HasMember(const std::string& character_name)
|
||||
{
|
||||
return std::any_of(m_members.begin(), m_members.end(),
|
||||
[&](const DynamicZoneMember& member) {
|
||||
@@ -644,34 +590,35 @@ std::string DynamicZoneBase::GetDynamicZoneTypeName(DynamicZoneType dz_type)
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerPacket(uint16_t zone_id, uint16_t instance_id)
|
||||
EQ::Net::DynamicPacket DynamicZoneBase::GetSerializedDzPacket()
|
||||
{
|
||||
std::ostringstream ss = GetSerialized();
|
||||
std::string_view sv = ss.view();
|
||||
EQ::Net::DynamicPacket dyn_pack;
|
||||
dyn_pack.PutSerialize(0, *this);
|
||||
|
||||
auto pack_size = sizeof(ServerDzCreate_Struct) + sv.size();
|
||||
LogDynamicZonesDetail("Serialized server dz size [{}]", dyn_pack.Length());
|
||||
return dyn_pack;
|
||||
}
|
||||
|
||||
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerDzCreatePacket(
|
||||
uint16_t origin_zone_id, uint16_t origin_instance_id)
|
||||
{
|
||||
EQ::Net::DynamicPacket dyn_pack = GetSerializedDzPacket();
|
||||
|
||||
auto pack_size = sizeof(ServerDzCreateSerialized_Struct) + dyn_pack.Length();
|
||||
auto pack = std::make_unique<ServerPacket>(ServerOP_DzCreated, static_cast<uint32_t>(pack_size));
|
||||
auto buf = reinterpret_cast<ServerDzCreate_Struct*>(pack->pBuffer);
|
||||
buf->origin_zone_id = zone_id;
|
||||
buf->origin_instance_id = instance_id;
|
||||
buf->dz_id = GetID();
|
||||
buf->cereal_size = static_cast<uint32_t>(sv.size());
|
||||
memcpy(buf->cereal_data, sv.data(), sv.size());
|
||||
auto buf = reinterpret_cast<ServerDzCreateSerialized_Struct*>(pack->pBuffer);
|
||||
buf->origin_zone_id = origin_zone_id;
|
||||
buf->origin_instance_id = origin_instance_id;
|
||||
buf->cereal_size = static_cast<uint32_t>(dyn_pack.Length());
|
||||
memcpy(buf->cereal_data, dyn_pack.Data(), dyn_pack.Length());
|
||||
|
||||
return pack;
|
||||
}
|
||||
|
||||
std::ostringstream DynamicZoneBase::GetSerialized()
|
||||
void DynamicZoneBase::LoadSerializedDzPacket(char* cereal_data, uint32_t cereal_size)
|
||||
{
|
||||
std::ostringstream ss;
|
||||
cereal::BinaryOutputArchive archive(ss);
|
||||
archive(*this);
|
||||
return ss;
|
||||
}
|
||||
|
||||
void DynamicZoneBase::Unserialize(std::span<char> buf)
|
||||
{
|
||||
EQ::Util::MemoryStreamReader ss(buf.data(), buf.size());
|
||||
LogDynamicZonesDetail("Deserializing server dz size [{}]", cereal_size);
|
||||
EQ::Util::MemoryStreamReader ss(cereal_data, cereal_size);
|
||||
cereal::BinaryInputArchive archive(ss);
|
||||
archive(*this);
|
||||
}
|
||||
@@ -700,180 +647,3 @@ void DynamicZoneBase::LoadTemplate(const DynamicZoneTemplatesRepository::Dynamic
|
||||
m_zonein.z = dz_template.zone_in_z;
|
||||
m_zonein.heading = dz_template.zone_in_h;
|
||||
}
|
||||
|
||||
std::vector<uint32_t> DynamicZoneBase::GetMemberIds()
|
||||
{
|
||||
std::vector<uint32_t> ids;
|
||||
ids.reserve(m_members.size());
|
||||
for (const auto& member : m_members)
|
||||
{
|
||||
ids.push_back(member.id);
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
bool DynamicZoneBase::HasLockout(const std::string& event)
|
||||
{
|
||||
return std::ranges::any_of(m_lockouts, [&](const auto& l) { return l.IsEvent(event); });
|
||||
}
|
||||
|
||||
bool DynamicZoneBase::HasReplayLockout()
|
||||
{
|
||||
return HasLockout(DzLockout::ReplayTimer);
|
||||
}
|
||||
|
||||
void DynamicZoneBase::AddLockout(const std::string& event, uint32_t seconds)
|
||||
{
|
||||
auto lockout = DzLockout::Create(m_name, event, seconds, m_uuid);
|
||||
AddLockout(lockout);
|
||||
}
|
||||
|
||||
void DynamicZoneBase::AddLockout(const DzLockout& lockout, bool members_only)
|
||||
{
|
||||
if (!members_only)
|
||||
{
|
||||
DynamicZoneLockoutsRepository::InsertLockouts(GetDatabase(), GetID(), { lockout });
|
||||
}
|
||||
|
||||
CharacterExpeditionLockoutsRepository::InsertLockout(GetDatabase(), GetMemberIds(), lockout);
|
||||
|
||||
HandleLockoutUpdate(lockout, false, members_only);
|
||||
SendServerPacket(CreateLockoutPacket(lockout, false, members_only).get());
|
||||
}
|
||||
|
||||
void DynamicZoneBase::AddLockoutDuration(const std::string& event, int seconds, bool members_only)
|
||||
{
|
||||
auto lockout = DzLockout::Create(m_name, event, std::max(0, seconds), m_uuid);
|
||||
|
||||
// lockout has unsigned duration, pass original seconds to support reducing existing timers
|
||||
int secs = static_cast<int>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
|
||||
CharacterExpeditionLockoutsRepository::AddLockoutDuration(GetDatabase(), GetMemberIds(), lockout, secs);
|
||||
|
||||
HandleLockoutDuration(lockout, seconds, members_only, true);
|
||||
SendServerPacket(CreateLockoutDurationPacket(lockout, seconds, members_only).get());
|
||||
}
|
||||
|
||||
void DynamicZoneBase::UpdateLockoutDuration(const std::string& event, uint32_t seconds, bool members_only)
|
||||
{
|
||||
// some live expeditions update existing lockout timers during progression
|
||||
auto it = std::ranges::find_if(m_lockouts, [&](const auto& l) { return l.IsEvent(event); });
|
||||
if (it != m_lockouts.end())
|
||||
{
|
||||
seconds = static_cast<uint32_t>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
|
||||
DzLockout lockout(m_uuid, m_name, event, it->GetStartTime() + seconds, seconds);
|
||||
AddLockout(lockout, members_only);
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicZoneBase::RemoveLockout(const std::string& event)
|
||||
{
|
||||
DynamicZoneLockoutsRepository::DeleteWhere(GetDatabase(), fmt::format(
|
||||
"dynamic_zone_id = {} AND event_name = '{}'", GetID(), Strings::Escape(event)));
|
||||
|
||||
CharacterExpeditionLockoutsRepository::DeleteWhere(GetDatabase(), fmt::format(
|
||||
"character_id IN ({}) AND expedition_name = '{}' AND event_name = '{}'",
|
||||
fmt::join(GetMemberIds(), ","), Strings::Escape(m_name), Strings::Escape(event)));
|
||||
|
||||
DzLockout lockout{m_uuid, m_name, event, 0, 0};
|
||||
HandleLockoutUpdate(lockout, true, false);
|
||||
SendServerPacket(CreateLockoutPacket(lockout, true).get());
|
||||
}
|
||||
|
||||
void DynamicZoneBase::HandleLockoutUpdate(const DzLockout& lockout, bool remove, bool members_only)
|
||||
{
|
||||
if (!members_only)
|
||||
{
|
||||
std::erase_if(m_lockouts, [&](const auto& l) { return l.IsEvent(lockout.Event()); });
|
||||
if (!remove)
|
||||
{
|
||||
m_lockouts.push_back(lockout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicZoneBase::HandleLockoutDuration(const DzLockout& lockout, int seconds, bool members_only, bool insert_db)
|
||||
{
|
||||
if (!members_only)
|
||||
{
|
||||
auto it = std::ranges::find_if(m_lockouts, [&](const auto& l) { return l.IsEvent(lockout.Event()); });
|
||||
if (it != m_lockouts.end())
|
||||
{
|
||||
it->AddLockoutTime(seconds);
|
||||
}
|
||||
else
|
||||
{
|
||||
it = m_lockouts.insert(m_lockouts.end(), lockout);
|
||||
}
|
||||
|
||||
if (insert_db)
|
||||
{
|
||||
DynamicZoneLockoutsRepository::InsertLockouts(GetDatabase(), GetID(), { *it });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateLockoutPacket(const DzLockout& lockout, bool remove, bool members_only) const
|
||||
{
|
||||
uint32_t pack_size = sizeof(ServerDzLockout_Struct);
|
||||
auto pack = std::make_unique<ServerPacket>(ServerOP_DzLockout, pack_size);
|
||||
auto buf = reinterpret_cast<ServerDzLockout_Struct*>(pack->pBuffer);
|
||||
buf->dz_id = GetID();
|
||||
buf->expire_time = lockout.GetExpireTime();
|
||||
buf->duration = lockout.GetDuration();
|
||||
buf->sender_zone_id = GetCurrentZoneID();
|
||||
buf->sender_instance_id = GetCurrentInstanceID();
|
||||
buf->remove = remove;
|
||||
buf->members_only = members_only;
|
||||
strn0cpy(buf->event_name, lockout.Event().c_str(), sizeof(buf->event_name));
|
||||
return pack;
|
||||
}
|
||||
|
||||
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateLockoutDurationPacket(const DzLockout& lockout, int seconds, bool members_only) const
|
||||
{
|
||||
uint32_t pack_size = sizeof(ServerDzLockout_Struct);
|
||||
auto pack = std::make_unique<ServerPacket>(ServerOP_DzLockoutDuration, pack_size);
|
||||
auto buf = reinterpret_cast<ServerDzLockout_Struct*>(pack->pBuffer);
|
||||
buf->dz_id = GetID();
|
||||
buf->expire_time = lockout.GetExpireTime();
|
||||
buf->duration = lockout.GetDuration();
|
||||
buf->sender_zone_id = GetCurrentZoneID();
|
||||
buf->sender_instance_id = GetCurrentInstanceID();
|
||||
buf->members_only = members_only;
|
||||
buf->seconds = seconds;
|
||||
strn0cpy(buf->event_name, lockout.Event().c_str(), sizeof(buf->event_name));
|
||||
return pack;
|
||||
}
|
||||
|
||||
void DynamicZoneBase::SyncCharacterLockouts(uint32_t char_id, std::vector<DzLockout>& lockouts)
|
||||
{
|
||||
// adds missing event lockouts to client for this expedition and updates
|
||||
// client timers that are both shorter and from another expedition
|
||||
bool modified = false;
|
||||
|
||||
for (const auto& lockout : m_lockouts)
|
||||
{
|
||||
if (lockout.IsReplay() || lockout.IsExpired() || lockout.UUID() != m_uuid)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto it = std::find_if(lockouts.begin(), lockouts.end(), [&](const DzLockout& l) { return l.IsSame(lockout); });
|
||||
if (it == lockouts.end())
|
||||
{
|
||||
modified = true;
|
||||
lockouts.push_back(lockout); // insert missing
|
||||
}
|
||||
else if (it->GetSecondsRemaining() < lockout.GetSecondsRemaining() && it->UUID() != m_uuid)
|
||||
{
|
||||
// only update lockout timer not uuid so loot event apis still work
|
||||
modified = true;
|
||||
it->SetDuration(lockout.GetDuration());
|
||||
it->SetExpireTime(lockout.GetExpireTime());
|
||||
}
|
||||
}
|
||||
|
||||
if (modified)
|
||||
{
|
||||
CharacterExpeditionLockoutsRepository::InsertLockouts(GetDatabase(), char_id, lockouts);
|
||||
}
|
||||
}
|
||||
|
||||
+14
-68
@@ -1,8 +1,8 @@
|
||||
#ifndef COMMON_DYNAMIC_ZONE_BASE_H
|
||||
#define COMMON_DYNAMIC_ZONE_BASE_H
|
||||
|
||||
#include "dynamic_zone_lockout.h"
|
||||
#include "eq_constants.h"
|
||||
#include "net/packet.h"
|
||||
#include "repositories/dynamic_zones_repository.h"
|
||||
#include "repositories/dynamic_zone_members_repository.h"
|
||||
#include "repositories/dynamic_zone_templates_repository.h"
|
||||
@@ -10,40 +10,12 @@
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class Database;
|
||||
class ServerPacket;
|
||||
|
||||
// message string 8312 added in September 08 2020 Test patch (used by both dz and shared tasks)
|
||||
inline constexpr char DzNotAllAdded[] = "Not all players in your {0} were added to the {1}. The {1} can take a maximum of {2} players, and your {0} has {3}.";
|
||||
|
||||
enum class DzLockMsg : uint8_t
|
||||
{
|
||||
None = 0, Close, Begin
|
||||
};
|
||||
|
||||
enum class DynamicZoneType
|
||||
{
|
||||
None = 0,
|
||||
Expedition,
|
||||
Tutorial,
|
||||
Task,
|
||||
Mission, // Shared Task
|
||||
Quest
|
||||
};
|
||||
|
||||
enum class DynamicZoneMemberStatus
|
||||
{
|
||||
Unknown = 0,
|
||||
Online,
|
||||
Offline,
|
||||
InDynamicZone,
|
||||
LinkDead
|
||||
};
|
||||
|
||||
struct DynamicZoneMember
|
||||
{
|
||||
uint32_t id = 0;
|
||||
@@ -121,7 +93,6 @@ public:
|
||||
const std::string& GetName() const { return m_name; }
|
||||
const std::string& GetUUID() const { return m_uuid; }
|
||||
const DynamicZoneMember& GetLeader() const { return m_leader; }
|
||||
const std::vector<DzLockout>& GetLockouts() const { return m_lockouts; }
|
||||
const std::vector<DynamicZoneMember>& GetMembers() const { return m_members; }
|
||||
const DynamicZoneLocation& GetCompassLocation() const { return m_compass; }
|
||||
const DynamicZoneLocation& GetSafeReturnLocation() const { return m_safereturn; }
|
||||
@@ -133,34 +104,31 @@ public:
|
||||
uint32_t GetDatabaseMemberCount();
|
||||
DynamicZoneMember GetMemberData(uint32_t character_id);
|
||||
DynamicZoneMember GetMemberData(const std::string& character_name);
|
||||
std::vector<uint32_t> GetMemberIds();
|
||||
std::ostringstream GetSerialized();
|
||||
EQ::Net::DynamicPacket GetSerializedDzPacket();
|
||||
bool HasDatabaseMember(uint32_t character_id);
|
||||
bool HasMember(uint32_t character_id) const;
|
||||
bool HasMember(const std::string& character_name) const;
|
||||
bool HasMember(uint32_t character_id);
|
||||
bool HasMember(const std::string& character_name);
|
||||
bool HasMembers() const { return !m_members.empty(); }
|
||||
bool HasZoneInLocation() const { return m_has_zonein; }
|
||||
bool IsExpedition() const { return m_type == DynamicZoneType::Expedition; }
|
||||
bool IsExpired() const { return m_expire_time < std::chrono::system_clock::now(); }
|
||||
bool IsInstanceID(uint32_t instance_id) const { return (m_instance_id != 0 && m_instance_id == instance_id); }
|
||||
bool IsLocked() const { return m_is_locked; }
|
||||
bool IsValid() const { return m_instance_id != 0; }
|
||||
bool IsSameDz(uint32_t zone_id, uint32_t instance_id) const { return zone_id == m_zone_id && instance_id == m_instance_id; }
|
||||
void LoadSerializedDzPacket(char* cereal_data, uint32_t cereal_size);
|
||||
void LoadTemplate(const DynamicZoneTemplatesRepository::DynamicZoneTemplates& dz_template);
|
||||
void RemoveAllMembers();
|
||||
bool RemoveMember(uint32_t character_id);
|
||||
bool RemoveMember(const std::string& character_name);
|
||||
bool RemoveMember(const DynamicZoneMember& remove_member);
|
||||
void SaveMembers(const std::vector<DynamicZoneMember>& members);
|
||||
void SetCompass(const DynamicZoneLocation& location, bool update_db = false);
|
||||
void SetCompass(uint32_t zone_id, float x, float y, float z, bool update_db = false);
|
||||
void SetDuration(uint32_t seconds) { m_duration = std::chrono::seconds(seconds); }
|
||||
void SetLeader(const DynamicZoneMember& leader, bool update_db = false);
|
||||
void SetLocked(bool lock, bool update_db = false, DzLockMsg lock_msg = DzLockMsg::None, uint32_t color = Chat::Yellow);
|
||||
void SetMaxPlayers(uint32_t max_players) { m_max_players = max_players; }
|
||||
void SetMemberStatus(uint32_t character_id, DynamicZoneMemberStatus status);
|
||||
void SetMinPlayers(uint32_t min_players) { m_min_players = min_players; }
|
||||
void SetName(const std::string& name) { m_name = name; }
|
||||
void SetReplayOnJoin(bool enabled, bool update_db = false);
|
||||
void SetSafeReturn(const DynamicZoneLocation& location, bool update_db = false);
|
||||
void SetSafeReturn(uint32_t zone_id, float x, float y, float z, float heading, bool update_db = false);
|
||||
void SetSwitchID(int dz_switch_id, bool update_db = false);
|
||||
@@ -168,48 +136,34 @@ public:
|
||||
void SetUUID(std::string uuid) { m_uuid = std::move(uuid); }
|
||||
void SetZoneInLocation(const DynamicZoneLocation& location, bool update_db = false);
|
||||
void SetZoneInLocation(float x, float y, float z, float heading, bool update_db = false);
|
||||
bool SwapMember(const DynamicZoneMember& add_member, const std::string& remove_name);
|
||||
|
||||
void AddLockout(const std::string& event, uint32_t seconds);
|
||||
void AddLockoutDuration(const std::string& event, int seconds, bool members_only = true);
|
||||
bool HasLockout(const std::string& event);
|
||||
bool HasReplayLockout();
|
||||
void RemoveLockout(const std::string& event);
|
||||
void SyncCharacterLockouts(uint32_t char_id, std::vector<DzLockout>& lockouts);
|
||||
void UpdateLockoutDuration(const std::string& event, uint32_t seconds, bool members_only = true);
|
||||
bool SwapMember(const DynamicZoneMember& add_member, const std::string& remove_char_name);
|
||||
|
||||
protected:
|
||||
virtual uint16_t GetCurrentInstanceID() const { return 0; }
|
||||
virtual uint16_t GetCurrentZoneID() const { return 0; }
|
||||
virtual uint16_t GetCurrentInstanceID() { return 0; }
|
||||
virtual uint16_t GetCurrentZoneID() { return 0; }
|
||||
virtual Database& GetDatabase() = 0;
|
||||
virtual void HandleLockoutDuration(const DzLockout& lockout, int seconds, bool members_only, bool insert_db);
|
||||
virtual void HandleLockoutUpdate(const DzLockout& lockout, bool remove, bool members_only);
|
||||
virtual void ProcessCompassChange(const DynamicZoneLocation& location) { m_compass = location; }
|
||||
virtual void ProcessMemberAddRemove(const DynamicZoneMember& member, bool removed);
|
||||
virtual bool ProcessMemberStatusChange(uint32_t character_id, DynamicZoneMemberStatus status);
|
||||
virtual void ProcessRemoveAllMembers() { m_members.clear(); }
|
||||
virtual bool ProcessMemberStatusChange(uint32_t member_id, DynamicZoneMemberStatus status);
|
||||
virtual void ProcessRemoveAllMembers(bool silent = false) { m_members.clear(); }
|
||||
virtual void ProcessSetSwitchID(int dz_switch_id) { m_dz_switch_id = dz_switch_id; }
|
||||
virtual bool SendServerPacket(ServerPacket* packet) = 0;
|
||||
|
||||
void AddLockout(const DzLockout& lockout, bool members_only = false);
|
||||
void AddInternalMember(const DynamicZoneMember& member);
|
||||
uint32_t Create();
|
||||
uint32_t CreateInstance();
|
||||
void LoadRepositoryResult(DynamicZonesRepository::DynamicZoneInstance&& dz_entry);
|
||||
void RemoveInternalMember(uint32_t character_id);
|
||||
void SaveMembers(const std::vector<DynamicZoneMember>& members);
|
||||
uint32_t SaveToDatabase();
|
||||
bool SetInternalMemberStatus(uint32_t character_id, DynamicZoneMemberStatus status);
|
||||
|
||||
std::unique_ptr<ServerPacket> CreateServerPacket(uint16_t zone_id, uint16_t instance_id);
|
||||
std::unique_ptr<ServerPacket> CreateServerDzCreatePacket(uint16_t origin_zone_id, uint16_t origin_instance_id);
|
||||
std::unique_ptr<ServerPacket> CreateServerDzLocationPacket(uint16_t server_opcode, const DynamicZoneLocation& location);
|
||||
std::unique_ptr<ServerPacket> CreateServerDzSwitchIDPacket();
|
||||
std::unique_ptr<ServerPacket> CreateServerMemberAddRemovePacket(const DynamicZoneMember& member, bool removed);
|
||||
std::unique_ptr<ServerPacket> CreateServerMemberStatusPacket(uint32_t character_id, DynamicZoneMemberStatus status);
|
||||
std::unique_ptr<ServerPacket> CreateServerMemberSwapPacket(const DynamicZoneMember& remove_member, const DynamicZoneMember& add_member);
|
||||
std::unique_ptr<ServerPacket> CreateServerRemoveAllMembersPacket();
|
||||
std::unique_ptr<ServerPacket> CreateLockoutPacket(const DzLockout& lockout, bool remove, bool members_only = false) const;
|
||||
std::unique_ptr<ServerPacket> CreateLockoutDurationPacket(const DzLockout& lockout, int seconds, bool members_only = false) const;
|
||||
|
||||
uint32_t m_id = 0;
|
||||
uint32_t m_zone_id = 0;
|
||||
@@ -221,8 +175,6 @@ protected:
|
||||
bool m_never_expires = false;
|
||||
bool m_has_zonein = false;
|
||||
bool m_has_member_statuses = false;
|
||||
bool m_is_locked = false;
|
||||
bool m_add_replay = true;
|
||||
std::string m_name;
|
||||
std::string m_uuid;
|
||||
DynamicZoneMember m_leader;
|
||||
@@ -230,15 +182,12 @@ protected:
|
||||
DynamicZoneLocation m_compass;
|
||||
DynamicZoneLocation m_safereturn;
|
||||
DynamicZoneLocation m_zonein;
|
||||
std::chrono::seconds m_duration = {};
|
||||
std::chrono::seconds m_duration;
|
||||
std::chrono::time_point<std::chrono::system_clock> m_start_time;
|
||||
std::chrono::time_point<std::chrono::system_clock> m_expire_time;
|
||||
std::vector<DynamicZoneMember> m_members;
|
||||
std::vector<DzLockout> m_lockouts;
|
||||
|
||||
public:
|
||||
void Unserialize(std::span<char> buf);
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive& archive)
|
||||
{
|
||||
@@ -253,8 +202,6 @@ public:
|
||||
m_never_expires,
|
||||
m_has_zonein,
|
||||
m_has_member_statuses,
|
||||
m_is_locked,
|
||||
m_add_replay,
|
||||
m_name,
|
||||
m_uuid,
|
||||
m_leader,
|
||||
@@ -265,8 +212,7 @@ public:
|
||||
m_duration,
|
||||
m_start_time,
|
||||
m_expire_time,
|
||||
m_members,
|
||||
m_lockouts
|
||||
m_members
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
#include "dynamic_zone_lockout.h"
|
||||
#include "strings.h"
|
||||
#include "rulesys.h"
|
||||
#include "util/uuid.h"
|
||||
#include <fmt/format.h>
|
||||
#include <cereal/types/chrono.hpp>
|
||||
|
||||
DzLockout::DzLockout(std::string uuid, std::string expedition, std::string event, uint64_t expire_time, uint32_t duration)
|
||||
: m_uuid(std::move(uuid))
|
||||
, m_name(std::move(expedition))
|
||||
, m_event(std::move(event))
|
||||
, m_expire_time(std::chrono::system_clock::from_time_t(expire_time))
|
||||
, m_duration(duration)
|
||||
{
|
||||
m_is_replay = m_event == ReplayTimer;
|
||||
}
|
||||
|
||||
DzLockout::DzLockout(std::string_view name, BaseDynamicZoneLockoutsRepository::DynamicZoneLockouts&& lockout)
|
||||
: m_uuid(std::move(lockout.from_expedition_uuid))
|
||||
, m_name(name)
|
||||
, m_event(std::move(lockout.event_name))
|
||||
, m_expire_time(std::chrono::system_clock::from_time_t(lockout.expire_time))
|
||||
, m_duration(lockout.duration)
|
||||
{
|
||||
m_is_replay = m_event == ReplayTimer;
|
||||
}
|
||||
|
||||
DzLockout DzLockout::Create(const std::string& expedition, const std::string& event, uint32_t seconds, std::string uuid)
|
||||
{
|
||||
seconds = static_cast<uint32_t>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
|
||||
|
||||
if (uuid.empty())
|
||||
{
|
||||
uuid = EQ::Util::UUID::Generate().ToString();
|
||||
}
|
||||
|
||||
DzLockout lockout{uuid, expedition, event, 0, seconds};
|
||||
lockout.Reset(); // sets expire time
|
||||
return lockout;
|
||||
}
|
||||
|
||||
uint32_t DzLockout::GetSecondsRemaining() const
|
||||
{
|
||||
auto now = std::chrono::system_clock::now();
|
||||
if (m_expire_time > now)
|
||||
{
|
||||
auto remaining = m_expire_time - now;
|
||||
return static_cast<uint32_t>(std::chrono::duration_cast<std::chrono::seconds>(remaining).count());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DzLockout::TimeStrings DzLockout::GetTimeRemainingStrs() const
|
||||
{
|
||||
auto seconds = GetSecondsRemaining();
|
||||
return DzLockout::TimeStrings{
|
||||
fmt::format_int(seconds / 86400).str(), // days
|
||||
fmt::format_int(seconds / 3600 % 24).str(), // hours
|
||||
fmt::format_int(seconds / 60 % 60).str(), // minutes
|
||||
fmt::format_int(seconds % 60).str() // seconds
|
||||
};
|
||||
}
|
||||
|
||||
bool DzLockout::IsSame(const DzLockout& other) const
|
||||
{
|
||||
return other.IsSame(m_name, m_event);
|
||||
}
|
||||
|
||||
bool DzLockout::IsSame(const std::string& expedition, const std::string& event) const
|
||||
{
|
||||
return m_name == expedition && m_event == event;
|
||||
}
|
||||
|
||||
void DzLockout::AddLockoutTime(int seconds)
|
||||
{
|
||||
seconds = static_cast<int>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
|
||||
|
||||
auto new_duration = std::max(0, static_cast<int>(m_duration.count()) + seconds);
|
||||
|
||||
auto start_time = m_expire_time - m_duration;
|
||||
m_duration = std::chrono::seconds(new_duration);
|
||||
m_expire_time = start_time + m_duration;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void DzLockout::serialize(T& archive)
|
||||
{
|
||||
archive(m_is_replay, m_uuid, m_name, m_event, m_duration, m_expire_time);
|
||||
}
|
||||
|
||||
template void DzLockout::serialize(cereal::BinaryOutputArchive&);
|
||||
template void DzLockout::serialize(cereal::BinaryInputArchive&);
|
||||
@@ -1,56 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include "repositories/base/base_dynamic_zone_lockouts_repository.h"
|
||||
|
||||
class DzLockout
|
||||
{
|
||||
public:
|
||||
DzLockout() = default;
|
||||
DzLockout(std::string uuid, std::string expedition, std::string event, uint64_t expire_time, uint32_t duration);
|
||||
DzLockout(std::string_view name, BaseDynamicZoneLockoutsRepository::DynamicZoneLockouts&& lockout);
|
||||
|
||||
static constexpr char ReplayTimer[] = "Replay Timer";
|
||||
|
||||
static DzLockout Create(const std::string& expedition, const std::string& event, uint32_t seconds, std::string uuid = {});
|
||||
|
||||
struct TimeStrings
|
||||
{
|
||||
std::string days;
|
||||
std::string hours;
|
||||
std::string mins;
|
||||
std::string secs;
|
||||
};
|
||||
|
||||
void AddLockoutTime(int seconds);
|
||||
uint32_t GetDuration() const { return static_cast<uint32_t>(m_duration.count()); }
|
||||
uint64_t GetExpireTime() const { return std::chrono::system_clock::to_time_t(m_expire_time); }
|
||||
uint64_t GetStartTime() const { return std::chrono::system_clock::to_time_t(m_expire_time - m_duration); }
|
||||
uint32_t GetSecondsRemaining() const;
|
||||
TimeStrings GetTimeRemainingStrs() const;
|
||||
const std::string& DzName() const { return m_name; }
|
||||
const std::string& Event() const { return m_event; }
|
||||
const std::string& UUID() const { return m_uuid; }
|
||||
bool IsEvent(std::string_view event) const { return m_event == event; }
|
||||
bool IsExpired() const { return GetSecondsRemaining() == 0; }
|
||||
bool IsReplay() const { return m_is_replay; }
|
||||
bool IsSame(const DzLockout& other) const;
|
||||
bool IsSame(const std::string& expedition, const std::string& event) const;
|
||||
bool IsUUID(const std::string& uuid) const { return uuid == m_uuid; }
|
||||
void Reset() { m_expire_time = std::chrono::system_clock::now() + m_duration; }
|
||||
void SetDuration(uint32_t seconds) { m_duration = std::chrono::seconds(seconds); }
|
||||
void SetExpireTime(uint64_t expire_time) { m_expire_time = std::chrono::system_clock::from_time_t(expire_time); }
|
||||
void SetUUID(const std::string& uuid) { m_uuid = uuid; }
|
||||
|
||||
template <typename T>
|
||||
void serialize(T& archive);
|
||||
|
||||
private:
|
||||
bool m_is_replay = false;
|
||||
std::string m_uuid; // dz received in
|
||||
std::string m_name;
|
||||
std::string m_event;
|
||||
std::chrono::seconds m_duration = {};
|
||||
std::chrono::time_point<std::chrono::system_clock> m_expire_time;
|
||||
};
|
||||
@@ -130,8 +130,6 @@ namespace EQ
|
||||
using RoF2::invtype::MAIL_SIZE;
|
||||
using RoF2::invtype::GUILD_TROPHY_TRIBUTE_SIZE;
|
||||
using RoF2::invtype::KRONO_SIZE;
|
||||
using RoF2::invtype::GUILD_BANK_MAIN_SIZE;
|
||||
using RoF2::invtype::GUILD_BANK_DEPOSIT_SIZE;
|
||||
using RoF2::invtype::OTHER_SIZE;
|
||||
|
||||
using RoF2::invtype::TRADE_NPC_SIZE;
|
||||
|
||||
@@ -287,8 +287,6 @@ N(OP_InstillDoubt),
|
||||
N(OP_InterruptCast),
|
||||
N(OP_InvokeChangePetName),
|
||||
N(OP_InvokeChangePetNameImmediate),
|
||||
N(OP_InvokeNameChangeImmediate),
|
||||
N(OP_InvokeNameChangeLazy),
|
||||
N(OP_ItemLinkClick),
|
||||
N(OP_ItemLinkResponse),
|
||||
N(OP_ItemLinkText),
|
||||
|
||||
@@ -974,6 +974,25 @@ namespace ZoneBlockedSpellTypes {
|
||||
const uint8 Region = 2;
|
||||
};
|
||||
|
||||
enum class DynamicZoneType
|
||||
{
|
||||
None = 0,
|
||||
Expedition,
|
||||
Tutorial,
|
||||
Task,
|
||||
Mission, // Shared Task
|
||||
Quest
|
||||
};
|
||||
|
||||
enum class DynamicZoneMemberStatus : uint8_t
|
||||
{
|
||||
Unknown = 0,
|
||||
Online,
|
||||
Offline,
|
||||
InDynamicZone,
|
||||
LinkDead
|
||||
};
|
||||
|
||||
enum StartZoneIndex {
|
||||
Odus = 0,
|
||||
Qeynos,
|
||||
|
||||
+22
-22
@@ -173,7 +173,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL,
|
||||
ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL,
|
||||
ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL,
|
||||
ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL
|
||||
ClientUnknown::INULL
|
||||
),
|
||||
|
||||
ClientUnknown::INULL,
|
||||
@@ -200,7 +200,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
Client62::INULL, Client62::INULL, Client62::INULL,
|
||||
Client62::INULL, Client62::INULL, Client62::INULL,
|
||||
Client62::INULL, Client62::INULL, Client62::INULL,
|
||||
Client62::INULL, Client62::INULL, Client62::INULL
|
||||
Client62::INULL
|
||||
),
|
||||
|
||||
Client62::INULL,
|
||||
@@ -227,7 +227,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
Titanium::invtype::VIEW_MOD_PC_SIZE, Titanium::invtype::VIEW_MOD_BANK_SIZE, Titanium::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||
Titanium::invtype::VIEW_MOD_LIMBO_SIZE, Titanium::invtype::ALT_STORAGE_SIZE, Titanium::invtype::ARCHIVED_SIZE,
|
||||
Titanium::INULL, Titanium::INULL, Titanium::INULL,
|
||||
Titanium::INULL, Titanium::INULL, Titanium::invtype::OTHER_SIZE
|
||||
Titanium::invtype::OTHER_SIZE
|
||||
),
|
||||
|
||||
Titanium::invslot::EQUIPMENT_BITMASK,
|
||||
@@ -254,7 +254,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
SoF::invtype::VIEW_MOD_PC_SIZE, SoF::invtype::VIEW_MOD_BANK_SIZE, SoF::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||
SoF::invtype::VIEW_MOD_LIMBO_SIZE, SoF::invtype::ALT_STORAGE_SIZE, SoF::invtype::ARCHIVED_SIZE,
|
||||
SoF::INULL, SoF::INULL, SoF::INULL,
|
||||
SoF::INULL, SoF::INULL, SoF::invtype::OTHER_SIZE
|
||||
SoF::invtype::OTHER_SIZE
|
||||
),
|
||||
|
||||
SoF::invslot::EQUIPMENT_BITMASK,
|
||||
@@ -281,7 +281,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
SoD::invtype::VIEW_MOD_PC_SIZE, SoD::invtype::VIEW_MOD_BANK_SIZE, SoD::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||
SoD::invtype::VIEW_MOD_LIMBO_SIZE, SoD::invtype::ALT_STORAGE_SIZE, SoD::invtype::ARCHIVED_SIZE,
|
||||
SoD::INULL, SoD::INULL, SoD::INULL,
|
||||
SoD::INULL, SoD::INULL, SoD::invtype::OTHER_SIZE
|
||||
SoD::invtype::OTHER_SIZE
|
||||
),
|
||||
|
||||
SoD::invslot::EQUIPMENT_BITMASK,
|
||||
@@ -308,7 +308,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
UF::invtype::VIEW_MOD_PC_SIZE, UF::invtype::VIEW_MOD_BANK_SIZE, UF::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||
UF::invtype::VIEW_MOD_LIMBO_SIZE, UF::invtype::ALT_STORAGE_SIZE, UF::invtype::ARCHIVED_SIZE,
|
||||
UF::INULL, UF::INULL, UF::INULL,
|
||||
UF::INULL, UF::INULL, UF::invtype::OTHER_SIZE
|
||||
UF::invtype::OTHER_SIZE
|
||||
),
|
||||
|
||||
UF::invslot::EQUIPMENT_BITMASK,
|
||||
@@ -335,7 +335,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
RoF::invtype::VIEW_MOD_PC_SIZE, RoF::invtype::VIEW_MOD_BANK_SIZE, RoF::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||
RoF::invtype::VIEW_MOD_LIMBO_SIZE, RoF::invtype::ALT_STORAGE_SIZE, RoF::invtype::ARCHIVED_SIZE,
|
||||
RoF::invtype::MAIL_SIZE, RoF::invtype::GUILD_TROPHY_TRIBUTE_SIZE, RoF::INULL,
|
||||
RoF::INULL,RoF::INULL,RoF::invtype::OTHER_SIZE
|
||||
RoF::invtype::OTHER_SIZE
|
||||
),
|
||||
|
||||
RoF::invslot::EQUIPMENT_BITMASK,
|
||||
@@ -362,7 +362,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
RoF2::invtype::VIEW_MOD_PC_SIZE, RoF2::invtype::VIEW_MOD_BANK_SIZE, RoF2::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||
RoF2::invtype::VIEW_MOD_LIMBO_SIZE, RoF2::invtype::ALT_STORAGE_SIZE, RoF2::invtype::ARCHIVED_SIZE,
|
||||
RoF2::invtype::MAIL_SIZE, RoF2::invtype::GUILD_TROPHY_TRIBUTE_SIZE, RoF2::invtype::KRONO_SIZE,
|
||||
RoF2::invtype::GUILD_BANK_MAIN_SIZE,RoF2::invtype::GUILD_BANK_DEPOSIT_SIZE, RoF2::invtype::OTHER_SIZE
|
||||
RoF2::invtype::OTHER_SIZE
|
||||
),
|
||||
|
||||
RoF2::invslot::EQUIPMENT_BITMASK,
|
||||
@@ -389,7 +389,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
EntityLimits::NPC::INULL, EntityLimits::NPC::INULL, EntityLimits::NPC::INULL,
|
||||
EntityLimits::NPC::INULL, EntityLimits::NPC::INULL, EntityLimits::NPC::INULL,
|
||||
EntityLimits::NPC::INULL, EntityLimits::NPC::INULL, EntityLimits::NPC::INULL,
|
||||
EntityLimits::NPC::INULL, EntityLimits::NPC::INULL,EntityLimits::NPC::INULL
|
||||
EntityLimits::NPC::INULL
|
||||
),
|
||||
|
||||
EntityLimits::NPC::INULL,
|
||||
@@ -416,7 +416,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL,
|
||||
EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL,
|
||||
EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL,
|
||||
EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL
|
||||
EntityLimits::NPCMerchant::INULL
|
||||
),
|
||||
|
||||
EntityLimits::NPCMerchant::INULL,
|
||||
@@ -443,7 +443,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
EntityLimits::Merc::INULL, EntityLimits::Merc::INULL, EntityLimits::Merc::INULL,
|
||||
EntityLimits::Merc::INULL, EntityLimits::Merc::INULL, EntityLimits::Merc::INULL,
|
||||
EntityLimits::Merc::INULL, EntityLimits::Merc::INULL, EntityLimits::Merc::INULL,
|
||||
EntityLimits::Merc::INULL, EntityLimits::Merc::INULL, EntityLimits::Merc::INULL
|
||||
EntityLimits::Merc::INULL
|
||||
),
|
||||
|
||||
EntityLimits::Merc::INULL,
|
||||
@@ -470,7 +470,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
EntityLimits::Bot::INULL, EntityLimits::Bot::INULL, EntityLimits::Bot::INULL,
|
||||
EntityLimits::Bot::INULL, EntityLimits::Bot::INULL, EntityLimits::Bot::INULL,
|
||||
EntityLimits::Bot::INULL, EntityLimits::Bot::INULL, EntityLimits::Bot::INULL,
|
||||
EntityLimits::Bot::INULL, EntityLimits::Bot::INULL, EntityLimits::Bot::INULL
|
||||
EntityLimits::Bot::INULL
|
||||
),
|
||||
|
||||
EntityLimits::Bot::invslot::EQUIPMENT_BITMASK,
|
||||
@@ -497,7 +497,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL,
|
||||
EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL,
|
||||
EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL,
|
||||
EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL
|
||||
EntityLimits::ClientPet::INULL
|
||||
),
|
||||
|
||||
EntityLimits::ClientPet::INULL,
|
||||
@@ -524,7 +524,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL,
|
||||
EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL,
|
||||
EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL,
|
||||
EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL
|
||||
EntityLimits::NPCPet::INULL
|
||||
),
|
||||
|
||||
EntityLimits::NPCPet::INULL,
|
||||
@@ -551,7 +551,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL,
|
||||
EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL,
|
||||
EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL,
|
||||
EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL
|
||||
EntityLimits::MercPet::INULL
|
||||
),
|
||||
|
||||
EntityLimits::MercPet::INULL,
|
||||
@@ -578,7 +578,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL,
|
||||
EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL,
|
||||
EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL,
|
||||
EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL
|
||||
EntityLimits::BotPet::INULL
|
||||
),
|
||||
|
||||
EntityLimits::BotPet::INULL,
|
||||
@@ -605,7 +605,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
Titanium::invtype::VIEW_MOD_PC_SIZE, Titanium::invtype::VIEW_MOD_BANK_SIZE, Titanium::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||
Titanium::invtype::VIEW_MOD_LIMBO_SIZE, Titanium::INULL, Titanium::INULL,
|
||||
Titanium::INULL, Titanium::INULL, Titanium::INULL,
|
||||
Titanium::INULL, Titanium::INULL, Titanium::INULL
|
||||
Titanium::INULL
|
||||
),
|
||||
|
||||
Titanium::INULL,
|
||||
@@ -632,7 +632,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
SoF::invtype::VIEW_MOD_PC_SIZE, SoF::invtype::VIEW_MOD_BANK_SIZE, SoF::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||
SoF::invtype::VIEW_MOD_LIMBO_SIZE, SoF::INULL, SoF::INULL,
|
||||
SoF::INULL, SoF::INULL, SoF::INULL,
|
||||
SoF::INULL, SoF::INULL, SoF::INULL
|
||||
SoF::INULL
|
||||
),
|
||||
|
||||
SoF::INULL,
|
||||
@@ -659,7 +659,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
SoD::invtype::VIEW_MOD_PC_SIZE, SoD::invtype::VIEW_MOD_BANK_SIZE, SoD::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||
SoD::invtype::VIEW_MOD_LIMBO_SIZE, SoD::INULL, SoD::INULL,
|
||||
SoD::INULL, SoD::INULL, SoD::INULL,
|
||||
SoD::INULL, SoD::INULL, SoD::INULL
|
||||
SoD::INULL
|
||||
),
|
||||
|
||||
SoD::INULL,
|
||||
@@ -686,7 +686,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
UF::invtype::VIEW_MOD_PC_SIZE, UF::invtype::VIEW_MOD_BANK_SIZE, UF::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||
UF::invtype::VIEW_MOD_LIMBO_SIZE, UF::INULL, UF::INULL,
|
||||
UF::INULL, UF::INULL, UF::INULL,
|
||||
UF::INULL, UF::INULL, UF::INULL
|
||||
UF::INULL
|
||||
),
|
||||
|
||||
UF::INULL,
|
||||
@@ -713,7 +713,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
RoF::invtype::VIEW_MOD_PC_SIZE, RoF::invtype::VIEW_MOD_BANK_SIZE, RoF::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||
RoF::invtype::VIEW_MOD_LIMBO_SIZE, RoF::INULL, RoF::INULL,
|
||||
RoF::INULL, RoF::INULL, RoF::INULL,
|
||||
RoF::INULL, RoF::INULL, RoF::INULL
|
||||
RoF::INULL
|
||||
),
|
||||
|
||||
RoF::INULL,
|
||||
@@ -740,7 +740,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
RoF2::invtype::VIEW_MOD_PC_SIZE, RoF2::invtype::VIEW_MOD_BANK_SIZE, RoF2::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||
RoF2::invtype::VIEW_MOD_LIMBO_SIZE, RoF2::INULL, RoF2::INULL,
|
||||
RoF2::INULL, RoF2::INULL, RoF2::INULL,
|
||||
RoF2::INULL, RoF2::INULL, RoF2::INULL
|
||||
RoF2::INULL
|
||||
),
|
||||
|
||||
RoF2::INULL,
|
||||
|
||||
+3
-3
@@ -87,7 +87,7 @@ namespace EQ
|
||||
int16 ViewMODPC, ViewMODBank, ViewMODSharedBank;
|
||||
int16 ViewMODLimbo, AltStorage, Archived;
|
||||
int16 Mail, GuildTrophyTribute, Krono;
|
||||
int16 GuildBankMain,GuildBankDeposit, Other;
|
||||
int16 Other;
|
||||
|
||||
InventoryTypeSize_Struct(
|
||||
int16 Possessions, int16 Bank, int16 SharedBank,
|
||||
@@ -98,7 +98,7 @@ namespace EQ
|
||||
int16 ViewMODPC, int16 ViewMODBank, int16 ViewMODSharedBank,
|
||||
int16 ViewMODLimbo, int16 AltStorage, int16 Archived,
|
||||
int16 Mail, int16 GuildTrophyTribute, int16 Krono,
|
||||
int16 GuildBankMain,int16 GuildBankDeposit, int16 Other
|
||||
int16 Other
|
||||
) :
|
||||
Possessions(Possessions), Bank(Bank), SharedBank(SharedBank),
|
||||
Trade(Trade), World(World), Limbo(Limbo),
|
||||
@@ -108,7 +108,7 @@ namespace EQ
|
||||
ViewMODPC(ViewMODPC), ViewMODBank(ViewMODBank), ViewMODSharedBank(ViewMODSharedBank),
|
||||
ViewMODLimbo(ViewMODLimbo), AltStorage(AltStorage), Archived(Archived),
|
||||
Mail(Mail), GuildTrophyTribute(GuildTrophyTribute), Krono(Krono),
|
||||
GuildBankMain(GuildBankMain), GuildBankDeposit(GuildBankDeposit), Other(Other)
|
||||
Other(Other)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
+54
-72
@@ -19,17 +19,17 @@
|
||||
#ifndef EQ_PACKET_STRUCTS_H
|
||||
#define EQ_PACKET_STRUCTS_H
|
||||
|
||||
#include <list>
|
||||
#include "types.h"
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <time.h>
|
||||
#include "../cereal/include/cereal/archives/binary.hpp"
|
||||
#include "../cereal/include/cereal/types/string.hpp"
|
||||
#include "../cereal/include/cereal/types/vector.hpp"
|
||||
#include "../common/version.h"
|
||||
#include "emu_constants.h"
|
||||
#include "textures.h"
|
||||
#include "types.h"
|
||||
#include "../cereal/include/cereal/archives/binary.hpp"
|
||||
#include "../cereal/include/cereal/types/string.hpp"
|
||||
#include "../cereal/include/cereal/types/vector.hpp"
|
||||
|
||||
static const uint32 BUFF_COUNT = 42;
|
||||
static const uint32 PET_BUFF_COUNT = 30;
|
||||
@@ -47,7 +47,7 @@ static const uint32 ADVANCED_LORE_LENGTH = 8192;
|
||||
*/
|
||||
#pragma pack(1)
|
||||
|
||||
struct LoginInfo {
|
||||
struct LoginInfo_Struct {
|
||||
/*000*/ char login_info[64];
|
||||
/*064*/ uint8 unknown064[124];
|
||||
/*188*/ uint8 zoning; // 01 if zoning, 00 if not
|
||||
@@ -324,8 +324,6 @@ union
|
||||
bool guild_show;
|
||||
bool trader;
|
||||
bool buyer;
|
||||
bool untargetable;
|
||||
uint32 npc_tint_id;
|
||||
};
|
||||
|
||||
struct PlayerState_Struct {
|
||||
@@ -5531,65 +5529,56 @@ struct GuildBankWithdrawItem_Struct
|
||||
|
||||
struct GuildBankItemUpdate_Struct
|
||||
{
|
||||
void Init(
|
||||
uint32 inAction,
|
||||
uint32 inUnknown004,
|
||||
uint16 inSlotID,
|
||||
uint16 inArea,
|
||||
uint16 inUnknown012,
|
||||
uint32 inItemID,
|
||||
uint32 inIcon,
|
||||
uint32 inQuantity,
|
||||
uint32 inPermissions,
|
||||
uint32 inAllowMerge,
|
||||
bool inUseable)
|
||||
void Init(uint32 inAction, uint32 inUnknown004, uint16 inSlotID, uint16 inArea, uint16 inUnknown012, uint32 inItemID, uint32 inIcon, uint32 inQuantity,
|
||||
uint32 inPermissions, uint32 inAllowMerge, bool inUseable)
|
||||
{
|
||||
action = inAction;
|
||||
unknown004 = inUnknown004;
|
||||
slot_id = inSlotID;
|
||||
area = inArea;
|
||||
display = inUnknown012;
|
||||
item_id = inItemID;
|
||||
icon_id = inIcon;
|
||||
quantity = inQuantity;
|
||||
permissions = inPermissions;
|
||||
allow_merge = inAllowMerge;
|
||||
is_useable = inUseable;
|
||||
item_name[0] = '\0';
|
||||
donator[0] = '\0';
|
||||
who_for[0] = '\0';
|
||||
Action = inAction;
|
||||
Unknown004 = inUnknown004;
|
||||
SlotID = inSlotID;
|
||||
Area = inArea;
|
||||
Unknown012 = inUnknown012;
|
||||
ItemID = inItemID;
|
||||
Icon = inIcon;
|
||||
Quantity = inQuantity;
|
||||
Permissions = inPermissions;
|
||||
AllowMerge = inAllowMerge;
|
||||
Useable = inUseable;
|
||||
ItemName[0] = '\0';
|
||||
Donator[0] = '\0';
|
||||
WhoFor[0] = '\0';
|
||||
};
|
||||
|
||||
/*000*/ uint32 action;
|
||||
/*004*/ uint32 unknown004;
|
||||
/*008*/ uint16 slot_id;
|
||||
/*010*/ uint16 area;
|
||||
/*012*/ uint32 display;
|
||||
/*016*/ uint32 item_id;
|
||||
/*020*/ uint32 icon_id;
|
||||
/*024*/ uint32 quantity;
|
||||
/*028*/ uint32 permissions;
|
||||
/*032*/ uint8 allow_merge;
|
||||
/*033*/ uint8 is_useable; // Used in conjunction with the Public-if-useable permission.
|
||||
/*034*/ char item_name[64];
|
||||
/*098*/ char donator[64];
|
||||
/*162*/ char who_for[64];
|
||||
/*226*/ uint16 unknown226;
|
||||
/*000*/ uint32 Action;
|
||||
/*004*/ uint32 Unknown004;
|
||||
/*008*/ uint16 SlotID;
|
||||
/*010*/ uint16 Area;
|
||||
/*012*/ uint32 Unknown012;
|
||||
/*016*/ uint32 ItemID;
|
||||
/*020*/ uint32 Icon;
|
||||
/*024*/ uint32 Quantity;
|
||||
/*028*/ uint32 Permissions;
|
||||
/*032*/ uint8 AllowMerge;
|
||||
/*033*/ uint8 Useable; // Used in conjunction with the Public-if-useable permission.
|
||||
/*034*/ char ItemName[64];
|
||||
/*098*/ char Donator[64];
|
||||
/*162*/ char WhoFor[64];
|
||||
/*226*/ uint16 Unknown226;
|
||||
};
|
||||
|
||||
// newer clients (RoF+) send a list that contains 240 entries
|
||||
// The packets don't actually use all 64 chars in the strings, but we'll just overallocate for these
|
||||
struct GuildBankItemListEntry_Struct {
|
||||
uint8 vaild;
|
||||
struct GuildBankItemListEntry_Struct
|
||||
{
|
||||
uint8 vaild;
|
||||
uint32 permissions;
|
||||
char whofor[64];
|
||||
char donator[64];
|
||||
char whofor[64];
|
||||
char donator[64];
|
||||
uint32 item_id;
|
||||
uint32 item_icon;
|
||||
uint32 quantity;
|
||||
uint8 allow_merge; // 1 here for non-full stacks
|
||||
uint8 usable;
|
||||
char item_name[64];
|
||||
uint8 allow_merge; // 1 here for non-full stacks
|
||||
uint8 usable;
|
||||
char item_name[64];
|
||||
};
|
||||
|
||||
struct GuildBankClear_Struct
|
||||
@@ -5834,28 +5823,21 @@ struct ChangeSize_Struct
|
||||
/*16*/
|
||||
};
|
||||
|
||||
enum ChangeNameResponse : int {
|
||||
Denied = 0, // 5167: "You have requested an invalid name or a Customer Service Representative has denied your name request. Please try another name."
|
||||
Accepted = 1, // 5976: "Your request for a name change was successful."
|
||||
Timeout = -1, // 5977: "Your request for a name change has timed out. Please try again later."
|
||||
ServerError = -2, // 5978: "The server had an error while processing your name request. Please try again later."
|
||||
RateLimited = -3, // 5979: "You must wait longer before submitting another name request. Please try again in a few minutes."
|
||||
Ineligible = -4, // 5980: "Your character is not eligible for a name change."
|
||||
Pending = -5 // 5193: "You already have a name change pending. Please wait until it is fully processed before attempting another name change."
|
||||
};
|
||||
|
||||
struct AltChangeName_Struct {
|
||||
/*00*/ char new_name[64];
|
||||
/*40*/ char old_name[64];
|
||||
/*80*/ int response_code;
|
||||
};
|
||||
|
||||
struct ChangePetName_Struct {
|
||||
/*00*/ char new_pet_name[64];
|
||||
/*40*/ char pet_owner_name[64];
|
||||
/*80*/ int response_code;
|
||||
};
|
||||
|
||||
enum ChangePetNameResponse : int {
|
||||
Denied = 0, // 5167 You have requested an invalid name or a Customer Service Representative has denied your name request. Please try another name.
|
||||
Accepted = 1, // 5976 Your request for a name change was successful.
|
||||
Timeout = -3, // 5979 You must wait longer before submitting another name request. Please try again in a few minutes.
|
||||
NotEligible = -4, // 5980 Your character is not eligible for a name change.
|
||||
Pending = -5, // 5193 You already have a name change pending. Please wait until it is fully processed before attempting another name change.
|
||||
Unhandled = -1
|
||||
};
|
||||
|
||||
// New OpCode/Struct for SoD+
|
||||
struct GroupMakeLeader_Struct
|
||||
{
|
||||
|
||||
@@ -545,13 +545,13 @@ void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p)
|
||||
uint32 chunksize, used;
|
||||
uint32 length;
|
||||
|
||||
if (EQEmuLogSys::Instance()->log_settings[Logs::Server_Client_Packet].is_category_enabled == 1){
|
||||
if (LogSys.log_settings[Logs::Server_Client_Packet].is_category_enabled == 1){
|
||||
if (p->GetOpcode() != OP_SpecialMesg){
|
||||
Log(Logs::General, Logs::Server_Client_Packet, "[%s - 0x%04x] [Size: %u]", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size());
|
||||
}
|
||||
}
|
||||
|
||||
if (EQEmuLogSys::Instance()->log_settings[Logs::Server_Client_Packet_With_Dump].is_category_enabled == 1){
|
||||
if (LogSys.log_settings[Logs::Server_Client_Packet_With_Dump].is_category_enabled == 1){
|
||||
if (p->GetOpcode() != OP_SpecialMesg){
|
||||
Log(Logs::General, Logs::Server_Client_Packet_With_Dump, "[%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size(), DumpPacketToString(p).c_str());
|
||||
}
|
||||
|
||||
+2
-17
@@ -177,21 +177,6 @@ void EQEmuConfig::parse_config()
|
||||
SharedMemDir = _root["server"]["directories"].get("shared_memory", "shared/").asString();
|
||||
LogDir = _root["server"]["directories"].get("logs", "logs/").asString();
|
||||
|
||||
auto load_paths = [&](const std::string& key, std::vector<std::string>& target) {
|
||||
const auto& paths = _root["server"]["directories"][key];
|
||||
if (paths.isArray()) {
|
||||
for (const auto& dir : paths) {
|
||||
if (dir.isString()) {
|
||||
target.push_back(dir.asString());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
load_paths("quest_paths", m_quest_directories);
|
||||
load_paths("plugin_paths", m_plugin_directories);
|
||||
load_paths("lua_module_paths", m_lua_module_directories);
|
||||
|
||||
/**
|
||||
* Logs
|
||||
*/
|
||||
@@ -436,11 +421,11 @@ void EQEmuConfig::CheckUcsConfigConversion()
|
||||
LogInfo("Migrating old [eqemu_config] UCS configuration to new configuration");
|
||||
|
||||
std::string config_file_path = std::filesystem::path{
|
||||
PathManager::Instance()->GetServerPath() + "/eqemu_config.json"
|
||||
path.GetServerPath() + "/eqemu_config.json"
|
||||
}.string();
|
||||
|
||||
std::string config_file_bak_path = std::filesystem::path{
|
||||
PathManager::Instance()->GetServerPath() + "/eqemu_config.ucs-migrate-json.bak"
|
||||
path.GetServerPath() + "/eqemu_config.ucs-migrate-json.bak"
|
||||
}.string();
|
||||
|
||||
// copy eqemu_config.json to eqemu_config.json.bak
|
||||
|
||||
+1
-22
@@ -120,22 +120,6 @@ class EQEmuConfig
|
||||
const std::string &GetUCSHost() const;
|
||||
uint16 GetUCSPort() const;
|
||||
|
||||
std::vector<std::string> GetQuestDirectories() const
|
||||
{
|
||||
return m_quest_directories;
|
||||
}
|
||||
|
||||
std::vector<std::string> GetPluginsDirectories() const
|
||||
{
|
||||
return m_plugin_directories;
|
||||
}
|
||||
|
||||
std::vector<std::string> GetLuaModuleDirectories() const
|
||||
{
|
||||
return m_lua_module_directories;
|
||||
}
|
||||
|
||||
|
||||
// uint16 DynamicCount;
|
||||
|
||||
// map<string,uint16> StaticZones;
|
||||
@@ -149,11 +133,6 @@ class EQEmuConfig
|
||||
Json::Value _root;
|
||||
static std::string ConfigFile;
|
||||
|
||||
std::vector<std::string> m_quest_directories = {};
|
||||
std::vector<std::string> m_plugin_directories = {};
|
||||
std::vector<std::string> m_lua_module_directories = {};
|
||||
|
||||
protected:
|
||||
void parse_config();
|
||||
|
||||
EQEmuConfig()
|
||||
@@ -191,7 +170,7 @@ class EQEmuConfig
|
||||
|
||||
std::string file = fmt::format(
|
||||
"{}/{}",
|
||||
(file_path.empty() ? PathManager::Instance()->GetServerPath() : file_path),
|
||||
(file_path.empty() ? path.GetServerPath() : file_path),
|
||||
EQEmuConfig::ConfigFile
|
||||
);
|
||||
|
||||
|
||||
+13
-40
@@ -537,9 +537,9 @@ void EQEmuLogSys::StartFileLogs(const std::string &log_name)
|
||||
{
|
||||
EQEmuLogSys::CloseFileLogs();
|
||||
|
||||
if (!File::Exists(PathManager::Instance()->GetLogPath())) {
|
||||
LogInfo("Logs directory not found, creating [{}]", PathManager::Instance()->GetLogPath());
|
||||
File::Makedir(PathManager::Instance()->GetLogPath());
|
||||
if (!File::Exists(path.GetLogPath())) {
|
||||
LogInfo("Logs directory not found, creating [{}]", path.GetLogPath());
|
||||
File::Makedir(path.GetLogPath());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -614,7 +614,7 @@ void EQEmuLogSys::EnableConsoleLogging()
|
||||
std::copy(std::begin(pre_silence_settings), std::end(pre_silence_settings), std::begin(log_settings));
|
||||
}
|
||||
|
||||
EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings(bool silent_load)
|
||||
EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
|
||||
{
|
||||
InjectTablesIfNotExist();
|
||||
|
||||
@@ -656,7 +656,7 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings(bool silent_load)
|
||||
// If we go through this whole loop and nothing is set to any debug level, there
|
||||
// is no point to create a file or keep anything open
|
||||
if (log_settings[c.log_category_id].log_to_file > 0) {
|
||||
m_file_logs_enabled = true;
|
||||
LogSys.m_file_logs_enabled = true;
|
||||
}
|
||||
|
||||
db_categories.emplace_back(c.log_category_id);
|
||||
@@ -682,33 +682,14 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings(bool silent_load)
|
||||
if (is_missing_in_database && !is_deprecated_category) {
|
||||
LogInfo("Automatically adding new log category [{}] ({})", Logs::LogCategoryName[i], i);
|
||||
|
||||
auto e = LogsysCategoriesRepository::NewEntity();
|
||||
e.log_category_id = i;
|
||||
e.log_category_description = Strings::Escape(Logs::LogCategoryName[i]);
|
||||
e.log_to_console = log_settings[i].log_to_console;
|
||||
e.log_to_gmsay = log_settings[i].log_to_gmsay;
|
||||
e.log_to_file = log_settings[i].log_to_file;
|
||||
e.log_to_discord = log_settings[i].log_to_discord;
|
||||
db_categories_to_add.emplace_back(e);
|
||||
}
|
||||
|
||||
// look to see if the category name is different in the database
|
||||
auto it = std::find_if(
|
||||
categories.begin(),
|
||||
categories.end(),
|
||||
[i](const auto &c) { return c.log_category_id == i; }
|
||||
);
|
||||
if (it != categories.end()) {
|
||||
if (it->log_category_description != Logs::LogCategoryName[i]) {
|
||||
LogInfo(
|
||||
"Updating log category [{}] ({}) to new name [{}]",
|
||||
it->log_category_description,
|
||||
i,
|
||||
Logs::LogCategoryName[i]
|
||||
);
|
||||
it->log_category_description = Logs::LogCategoryName[i];
|
||||
LogsysCategoriesRepository::ReplaceOne(*m_database, *it);
|
||||
}
|
||||
auto new_category = LogsysCategoriesRepository::NewEntity();
|
||||
new_category.log_category_id = i;
|
||||
new_category.log_category_description = Strings::Escape(Logs::LogCategoryName[i]);
|
||||
new_category.log_to_console = log_settings[i].log_to_console;
|
||||
new_category.log_to_gmsay = log_settings[i].log_to_gmsay;
|
||||
new_category.log_to_file = log_settings[i].log_to_file;
|
||||
new_category.log_to_discord = log_settings[i].log_to_discord;
|
||||
db_categories_to_add.emplace_back(new_category);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -718,10 +699,6 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings(bool silent_load)
|
||||
return this;
|
||||
}
|
||||
|
||||
if (silent_load) {
|
||||
SilenceConsoleLogging();
|
||||
}
|
||||
|
||||
LogInfo("Loaded [{}] log categories", categories.size());
|
||||
|
||||
auto webhooks = DiscordWebhooksRepository::GetWhere(*m_database, fmt::format("id < {}", MAX_DISCORD_WEBHOOK_ID));
|
||||
@@ -739,10 +716,6 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings(bool silent_load)
|
||||
log_settings[Logs::Info].log_to_file = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::Info].log_to_console = static_cast<uint8>(Logs::General);
|
||||
|
||||
if (silent_load) {
|
||||
SilenceConsoleLogging();
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
+15
-25
@@ -74,7 +74,7 @@ namespace Logs {
|
||||
Spawns,
|
||||
Spells,
|
||||
Status, // deprecated
|
||||
TCPConnection, // deprecated
|
||||
TCPConnection,
|
||||
Tasks,
|
||||
Tradeskills,
|
||||
Trading,
|
||||
@@ -149,9 +149,6 @@ namespace Logs {
|
||||
BotSpellChecks,
|
||||
BotSpellTypeChecks,
|
||||
NpcHandin,
|
||||
ZoneState,
|
||||
NetClient,
|
||||
NetTCP,
|
||||
MaxCategoryID /* Don't Remove this */
|
||||
};
|
||||
|
||||
@@ -185,7 +182,7 @@ namespace Logs {
|
||||
"Spawns",
|
||||
"Spells",
|
||||
"Status (Deprecated)",
|
||||
"TCP Connection (Deprecated)",
|
||||
"TCP Connection",
|
||||
"Tasks",
|
||||
"Tradeskills",
|
||||
"Trading",
|
||||
@@ -194,8 +191,8 @@ namespace Logs {
|
||||
"Web Interface (Deprecated)",
|
||||
"World Server (Deprecated)",
|
||||
"Zone Server (Deprecated)",
|
||||
"MySQL Error",
|
||||
"MySQL Query",
|
||||
"QueryErr",
|
||||
"Query",
|
||||
"Mercenaries",
|
||||
"Quest Debug",
|
||||
"Legacy Packet Logging (Deprecated)",
|
||||
@@ -211,15 +208,15 @@ namespace Logs {
|
||||
"Traps",
|
||||
"NPC Roam Box",
|
||||
"NPC Scaling",
|
||||
"Mob Appearance",
|
||||
"MobAppearance",
|
||||
"Info",
|
||||
"Warning",
|
||||
"Critical (Deprecated)",
|
||||
"Emergency (Deprecated)",
|
||||
"Alert (Deprecated)",
|
||||
"Notice (Deprecated)",
|
||||
"AI Scan Close",
|
||||
"AI Yell For Help",
|
||||
"AI Scan",
|
||||
"AI Yell",
|
||||
"AI CastBeneficial",
|
||||
"AOE Cast",
|
||||
"Entity Management",
|
||||
@@ -237,7 +234,7 @@ namespace Logs {
|
||||
"DialogueWindow",
|
||||
"HTTP",
|
||||
"Saylink",
|
||||
"Checksum Verification",
|
||||
"ChecksumVer",
|
||||
"CombatRecord",
|
||||
"Hate",
|
||||
"Discord",
|
||||
@@ -259,13 +256,12 @@ namespace Logs {
|
||||
"Bot Settings",
|
||||
"Bot Spell Checks",
|
||||
"Bot Spell Type Checks",
|
||||
"NpcHandin",
|
||||
"ZoneState",
|
||||
"Net Server <-> Client",
|
||||
"Net TCP"
|
||||
"NpcHandin"
|
||||
};
|
||||
}
|
||||
|
||||
#include "eqemu_logsys_log_aliases.h"
|
||||
|
||||
class Database;
|
||||
|
||||
constexpr uint16 MAX_DISCORD_WEBHOOK_ID = 300;
|
||||
@@ -281,13 +277,7 @@ public:
|
||||
*/
|
||||
void CloseFileLogs();
|
||||
EQEmuLogSys *LoadLogSettingsDefaults();
|
||||
EQEmuLogSys *LoadLogDatabaseSettings(bool silent_load = false);
|
||||
|
||||
static EQEmuLogSys *Instance()
|
||||
{
|
||||
static EQEmuLogSys instance;
|
||||
return &instance;
|
||||
}
|
||||
EQEmuLogSys *LoadLogDatabaseSettings();
|
||||
|
||||
/**
|
||||
* @param directory_name
|
||||
@@ -354,7 +344,7 @@ public:
|
||||
/**
|
||||
* Internally used memory reference for all log settings per category
|
||||
* These are loaded via DB and have defaults loaded in LoadLogSettingsDefaults
|
||||
* Database loaded via EQEmuLogSys::Instance()->SetDatabase(&database)->LoadLogDatabaseSettings();
|
||||
* Database loaded via LogSys.SetDatabase(&database)->LoadLogDatabaseSettings();
|
||||
*/
|
||||
LogSettings log_settings[Logs::LogCategory::MaxCategoryID]{};
|
||||
|
||||
@@ -438,7 +428,7 @@ private:
|
||||
void InjectTablesIfNotExist();
|
||||
};
|
||||
|
||||
#include "eqemu_logsys_log_aliases.h"
|
||||
extern EQEmuLogSys LogSys;
|
||||
|
||||
/**
|
||||
template<typename... Args>
|
||||
@@ -460,7 +450,7 @@ void OutF(
|
||||
|
||||
#define OutF(ls, debug_level, log_category, file, func, line, formatStr, ...) \
|
||||
do { \
|
||||
ls->Out(debug_level, log_category, file, func, line, fmt::format(formatStr, ##__VA_ARGS__).c_str()); \
|
||||
ls.Out(debug_level, log_category, file, func, line, fmt::format(formatStr, ##__VA_ARGS__).c_str()); \
|
||||
} while(0)
|
||||
|
||||
#endif
|
||||
|
||||
+372
-384
File diff suppressed because it is too large
Load Diff
@@ -716,7 +716,7 @@ std::string PlayerEventDiscordFormatter::FormatNPCHandinEvent(
|
||||
);
|
||||
|
||||
for (int i = 0; i < h.augment_ids.size(); i++) {
|
||||
if (!h.augment_names[i].empty()) {
|
||||
if (!Strings::EqualFold(h.augment_names[i], "None")) {
|
||||
const uint8 slot_id = (i + 1);
|
||||
handin_items_info += fmt::format(
|
||||
"Augment {}: {} ({})\n",
|
||||
@@ -741,7 +741,7 @@ std::string PlayerEventDiscordFormatter::FormatNPCHandinEvent(
|
||||
);
|
||||
|
||||
for (int i = 0; i < r.augment_ids.size(); i++) {
|
||||
if (!r.augment_names[i].empty()) {
|
||||
if (!Strings::EqualFold(r.augment_names[i], "None")) {
|
||||
const uint8 slot_id = (i + 1);
|
||||
return_items_info += fmt::format(
|
||||
"Augment {}: {} ({})\n",
|
||||
|
||||
@@ -15,9 +15,9 @@ const uint32 PROCESS_RETENTION_TRUNCATION_TIMER_INTERVAL = 60 * 60 * 1000; // 1
|
||||
// general initialization routine
|
||||
void PlayerEventLogs::Init()
|
||||
{
|
||||
|
||||
m_process_batch_events_timer.SetTimer(RuleI(Logging, BatchPlayerEventProcessIntervalSeconds) * 1000);
|
||||
m_process_retention_truncation_timer.SetTimer(PROCESS_RETENTION_TRUNCATION_TIMER_INTERVAL);
|
||||
m_database_ping_timer.SetTimer(10 * 1000); // 10 seconds
|
||||
|
||||
ValidateDatabaseConnection();
|
||||
|
||||
@@ -82,12 +82,13 @@ void PlayerEventLogs::Init()
|
||||
PlayerEventLogSettingsRepository::ReplaceMany(*m_database, settings_to_insert);
|
||||
}
|
||||
|
||||
LoadEtlIds();
|
||||
|
||||
bool processing_in_world = !RuleB(Logging, PlayerEventsQSProcess) && IsWorld();
|
||||
bool processing_in_qs = RuleB(Logging, PlayerEventsQSProcess) && IsQueryServ();
|
||||
|
||||
// on initial boot process truncation
|
||||
if (processing_in_world || processing_in_qs) {
|
||||
LoadEtlIds();
|
||||
ProcessRetentionTruncation();
|
||||
}
|
||||
}
|
||||
@@ -181,26 +182,16 @@ void PlayerEventLogs::ProcessBatchQueue()
|
||||
|
||||
// Helper to deserialize event data
|
||||
auto Deserialize = [](const std::string &data, auto &out) {
|
||||
if (!Strings::IsValidJson(data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// cpp exceptions are terrible, don't ever use them
|
||||
try {
|
||||
std::stringstream ss(data);
|
||||
cereal::JSONInputArchive ar(ss);
|
||||
out.serialize(ar);
|
||||
}
|
||||
catch (const std::exception &e) {}
|
||||
std::stringstream ss(data);
|
||||
cereal::JSONInputArchive ar(ss);
|
||||
out.serialize(ar);
|
||||
};
|
||||
|
||||
// Helper to assign ETL table ID
|
||||
|
||||
auto AssignEtlId = [&](
|
||||
PlayerEventLogsRepository::PlayerEventLogs& r,
|
||||
PlayerEvent::EventType type
|
||||
)
|
||||
{
|
||||
auto AssignEtlId = [&](
|
||||
PlayerEventLogsRepository::PlayerEventLogs &r,
|
||||
PlayerEvent::EventType type
|
||||
) {
|
||||
if (m_etl_settings.contains(type)) {
|
||||
r.etl_table_id = m_etl_settings.at(type).next_id++;
|
||||
}
|
||||
@@ -408,9 +399,10 @@ void PlayerEventLogs::ProcessBatchQueue()
|
||||
auto it = event_processors.find(static_cast<PlayerEvent::EventType>(r.event_type_id));
|
||||
if (it != event_processors.end()) {
|
||||
it->second(r); // Call the appropriate lambda
|
||||
r.event_data = "{}"; // Clear event data
|
||||
}
|
||||
else {
|
||||
LogPlayerEventsDetail("Non-Implemented ETL routing [{}]", r.event_type_id);
|
||||
LogError("Non-Implemented ETL routing [{}]", r.event_type_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -509,7 +501,7 @@ bool PlayerEventLogs::IsEventDiscordEnabled(int32_t event_type_id)
|
||||
}
|
||||
|
||||
// ensure there is a matching webhook to begin with
|
||||
if (!EQEmuLogSys::Instance()->GetDiscordWebhooks()[m_settings[event_type_id].discord_webhook_id].webhook_url.empty()) {
|
||||
if (!LogSys.GetDiscordWebhooks()[m_settings[event_type_id].discord_webhook_id].webhook_url.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -529,27 +521,13 @@ std::string PlayerEventLogs::GetDiscordWebhookUrlFromEventType(int32_t event_typ
|
||||
}
|
||||
|
||||
// ensure there is a matching webhook to begin with
|
||||
if (!EQEmuLogSys::Instance()->GetDiscordWebhooks()[m_settings[event_type_id].discord_webhook_id].webhook_url.empty()) {
|
||||
return EQEmuLogSys::Instance()->GetDiscordWebhooks()[m_settings[event_type_id].discord_webhook_id].webhook_url;
|
||||
if (!LogSys.GetDiscordWebhooks()[m_settings[event_type_id].discord_webhook_id].webhook_url.empty()) {
|
||||
return LogSys.GetDiscordWebhooks()[m_settings[event_type_id].discord_webhook_id].webhook_url;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void PlayerEventLogs::LoadPlayerEventSettingsFromQS(
|
||||
const std::vector<PlayerEventLogSettingsRepository::PlayerEventLogSettings> &settings
|
||||
)
|
||||
{
|
||||
for (const auto &e : settings) {
|
||||
if (e.id >= PlayerEvent::MAX || e.id < 0) {
|
||||
continue;
|
||||
}
|
||||
m_settings[e.id] = e;
|
||||
}
|
||||
|
||||
LogInfo("Applied [{}] player event log settings from QS", settings.size());
|
||||
}
|
||||
|
||||
// GM_COMMAND | [x] Implemented Formatter
|
||||
// ZONING | [x] Implemented Formatter
|
||||
// AA_GAIN | [x] Implemented Formatter
|
||||
@@ -931,10 +909,6 @@ std::string PlayerEventLogs::GetDiscordPayloadFromEvent(const PlayerEvent::Playe
|
||||
// general process function, used in world or QS depending on rule Logging:PlayerEventsQSProcess
|
||||
void PlayerEventLogs::Process()
|
||||
{
|
||||
if (m_database_ping_timer.Check()) {
|
||||
m_database->ping();
|
||||
}
|
||||
|
||||
if (m_process_batch_events_timer.Check() ||
|
||||
m_record_batch_queue.size() >= RuleI(Logging, BatchPlayerEventProcessChunkSize)) {
|
||||
ProcessBatchQueue();
|
||||
|
||||
@@ -73,11 +73,9 @@ public:
|
||||
return BuildPlayerEventPacket(c);
|
||||
}
|
||||
|
||||
[[nodiscard]] const PlayerEventLogSettingsRepository::PlayerEventLogSettings * GetSettings() const;
|
||||
bool IsEventDiscordEnabled(int32_t event_type_id);
|
||||
std::string GetDiscordWebhookUrlFromEventType(int32_t event_type_id);
|
||||
|
||||
void LoadPlayerEventSettingsFromQS(const std::vector<PlayerEventLogSettingsRepository::PlayerEventLogSettings>& settings);
|
||||
[[nodiscard]] const PlayerEventLogSettingsRepository::PlayerEventLogSettings *GetSettings() const;
|
||||
bool IsEventDiscordEnabled(int32_t event_type_id);
|
||||
std::string GetDiscordWebhookUrlFromEventType(int32_t event_type_id);
|
||||
|
||||
static std::string GetDiscordPayloadFromEvent(const PlayerEvent::PlayerEventContainer &e);
|
||||
|
||||
@@ -96,12 +94,6 @@ public:
|
||||
std::vector<PlayerEventAaPurchaseRepository::PlayerEventAaPurchase> aa_purchase;
|
||||
};
|
||||
|
||||
static PlayerEventLogs* Instance()
|
||||
{
|
||||
static PlayerEventLogs instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
private:
|
||||
struct EtlSettings {
|
||||
bool enabled;
|
||||
@@ -121,7 +113,6 @@ private:
|
||||
std::map<PlayerEvent::EventType, EtlSettings> m_etl_settings{};
|
||||
|
||||
// timers
|
||||
Timer m_database_ping_timer; // database ping timer
|
||||
Timer m_process_batch_events_timer; // events processing timer
|
||||
Timer m_process_retention_truncation_timer; // timer for truncating events based on retention settings
|
||||
|
||||
@@ -135,4 +126,6 @@ public:
|
||||
std::map<PlayerEvent::EventType, EtlSettings> &GetEtlSettings() { return m_etl_settings;}
|
||||
};
|
||||
|
||||
extern PlayerEventLogs player_event_logs;
|
||||
|
||||
#endif //EQEMU_PLAYER_EVENT_LOGS_H
|
||||
|
||||
+120
-597
File diff suppressed because it is too large
Load Diff
+18
-41
@@ -21,8 +21,8 @@ void EvolvingItemsManager::LoadEvolvingItems() const
|
||||
results.begin(),
|
||||
results.end(),
|
||||
std::inserter(
|
||||
EvolvingItemsManager::Instance()->GetEvolvingItemsCache(),
|
||||
EvolvingItemsManager::Instance()->GetEvolvingItemsCache().end()
|
||||
evolving_items_manager.GetEvolvingItemsCache(),
|
||||
evolving_items_manager.GetEvolvingItemsCache().end()
|
||||
),
|
||||
[](const ItemsEvolvingDetailsRepository::ItemsEvolvingDetails &x) {
|
||||
return std::make_pair(x.item_id, x);
|
||||
@@ -42,22 +42,18 @@ void EvolvingItemsManager::SetContentDatabase(Database *db)
|
||||
|
||||
double EvolvingItemsManager::CalculateProgression(const uint64 current_amount, const uint32 item_id)
|
||||
{
|
||||
if (!EvolvingItemsManager::Instance()->GetEvolvingItemsCache().contains(item_id)) {
|
||||
if (!evolving_items_manager.GetEvolvingItemsCache().contains(item_id)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return EvolvingItemsManager::Instance()->GetEvolvingItemsCache().at(item_id).required_amount > 0
|
||||
return evolving_items_manager.GetEvolvingItemsCache().at(item_id).required_amount > 0
|
||||
? static_cast<double>(current_amount)
|
||||
/ static_cast<double>(EvolvingItemsManager::Instance()->GetEvolvingItemsCache().at(item_id).required_amount) * 100
|
||||
/ static_cast<double>(evolving_items_manager.GetEvolvingItemsCache().at(item_id).required_amount) * 100
|
||||
: 0;
|
||||
}
|
||||
|
||||
void EvolvingItemsManager::DoLootChecks(const uint32 char_id, const uint16 slot_id, const EQ::ItemInstance &inst) const
|
||||
{
|
||||
if (!inst) {
|
||||
return;
|
||||
}
|
||||
|
||||
inst.SetEvolveEquipped(false);
|
||||
if (inst.IsEvolving() && slot_id <= EQ::invslot::EQUIPMENT_END && slot_id >= EQ::invslot::EQUIPMENT_BEGIN) {
|
||||
inst.SetEvolveEquipped(true);
|
||||
@@ -73,7 +69,7 @@ void EvolvingItemsManager::DoLootChecks(const uint32 char_id, const uint16 slot_
|
||||
e.character_id = char_id;
|
||||
e.item_id = inst.GetID();
|
||||
e.equipped = inst.GetEvolveEquipped();
|
||||
e.final_item_id = EvolvingItemsManager::Instance()->GetFinalItemID(inst);
|
||||
e.final_item_id = evolving_items_manager.GetFinalItemID(inst);
|
||||
|
||||
auto r = CharacterEvolvingItemsRepository::InsertOne(*m_db, e);
|
||||
e.id = r.id;
|
||||
@@ -91,25 +87,21 @@ void EvolvingItemsManager::DoLootChecks(const uint32 char_id, const uint16 slot_
|
||||
|
||||
uint32 EvolvingItemsManager::GetFinalItemID(const EQ::ItemInstance &inst) const
|
||||
{
|
||||
if (!inst) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const auto start_iterator = std::ranges::find_if(
|
||||
EvolvingItemsManager::Instance()->GetEvolvingItemsCache().cbegin(),
|
||||
EvolvingItemsManager::Instance()->GetEvolvingItemsCache().cend(),
|
||||
evolving_items_manager.GetEvolvingItemsCache().cbegin(),
|
||||
evolving_items_manager.GetEvolvingItemsCache().cend(),
|
||||
[&](const std::pair<uint32, ItemsEvolvingDetailsRepository::ItemsEvolvingDetails> &a) {
|
||||
return a.second.item_evo_id == inst.GetEvolveLoreID();
|
||||
}
|
||||
);
|
||||
|
||||
if (start_iterator == std::end(EvolvingItemsManager::Instance()->GetEvolvingItemsCache())) {
|
||||
if (start_iterator == std::end(evolving_items_manager.GetEvolvingItemsCache())) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const auto final_id = std::ranges::max_element(
|
||||
start_iterator,
|
||||
EvolvingItemsManager::Instance()->GetEvolvingItemsCache().cend(),
|
||||
evolving_items_manager.GetEvolvingItemsCache().cend(),
|
||||
[&](
|
||||
const std::pair<uint32, ItemsEvolvingDetailsRepository::ItemsEvolvingDetails> &a,
|
||||
const std::pair<uint32, ItemsEvolvingDetailsRepository::ItemsEvolvingDetails> &b
|
||||
@@ -124,22 +116,18 @@ uint32 EvolvingItemsManager::GetFinalItemID(const EQ::ItemInstance &inst) const
|
||||
|
||||
uint32 EvolvingItemsManager::GetNextEvolveItemID(const EQ::ItemInstance &inst) const
|
||||
{
|
||||
if (!inst) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8 const current_level = inst.GetEvolveLvl();
|
||||
|
||||
const auto iterator = std::ranges::find_if(
|
||||
EvolvingItemsManager::Instance()->GetEvolvingItemsCache().cbegin(),
|
||||
EvolvingItemsManager::Instance()->GetEvolvingItemsCache().cend(),
|
||||
evolving_items_manager.GetEvolvingItemsCache().cbegin(),
|
||||
evolving_items_manager.GetEvolvingItemsCache().cend(),
|
||||
[&](const std::pair<uint32, ItemsEvolvingDetailsRepository::ItemsEvolvingDetails> &a) {
|
||||
return a.second.item_evo_id == inst.GetEvolveLoreID() &&
|
||||
a.second.item_evolve_level == current_level + 1;
|
||||
}
|
||||
);
|
||||
|
||||
if (iterator == std::end(EvolvingItemsManager::Instance()->GetEvolvingItemsCache())) {
|
||||
if (iterator == std::end(evolving_items_manager.GetEvolvingItemsCache())) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -203,10 +191,6 @@ uint64 EvolvingItemsManager::GetTotalEarnedXP(const EQ::ItemInstance &inst)
|
||||
EvolveGetNextItem EvolvingItemsManager::GetNextItemByXP(const EQ::ItemInstance &inst_in, const int64 in_xp)
|
||||
{
|
||||
EvolveGetNextItem ets{};
|
||||
if (!inst_in) {
|
||||
return ets;
|
||||
}
|
||||
|
||||
const auto evolve_items = GetEvolveIDItems(inst_in.GetEvolveLoreID());
|
||||
uint32 max_transfer_level = 0;
|
||||
int64 xp = in_xp;
|
||||
@@ -251,12 +235,9 @@ EvolveTransfer EvolvingItemsManager::DetermineTransferResults(
|
||||
)
|
||||
{
|
||||
EvolveTransfer ets{};
|
||||
if (!inst_from || !inst_to) {
|
||||
return ets;
|
||||
}
|
||||
|
||||
auto evolving_details_inst_from = EvolvingItemsManager::Instance()->GetEvolveItemDetails(inst_from.GetID());
|
||||
auto evolving_details_inst_to = EvolvingItemsManager::Instance()->GetEvolveItemDetails(inst_to.GetID());
|
||||
auto evolving_details_inst_from = evolving_items_manager.GetEvolveItemDetails(inst_from.GetID());
|
||||
auto evolving_details_inst_to = evolving_items_manager.GetEvolveItemDetails(inst_to.GetID());
|
||||
|
||||
if (!evolving_details_inst_from.id || !evolving_details_inst_to.id) {
|
||||
return ets;
|
||||
@@ -272,10 +253,10 @@ EvolveTransfer EvolvingItemsManager::DetermineTransferResults(
|
||||
compatibility = 30;
|
||||
}
|
||||
|
||||
xp = EvolvingItemsManager::Instance()->GetTotalEarnedXP(inst_from) * compatibility / 100;
|
||||
auto results = EvolvingItemsManager::Instance()->GetNextItemByXP(inst_to, xp);
|
||||
xp = evolving_items_manager.GetTotalEarnedXP(inst_from) * compatibility / 100;
|
||||
auto results = evolving_items_manager.GetNextItemByXP(inst_to, xp);
|
||||
|
||||
ets.item_from_id = EvolvingItemsManager::Instance()->GetFirstItemInLoreGroup(inst_from.GetEvolveLoreID());
|
||||
ets.item_from_id = evolving_items_manager.GetFirstItemInLoreGroup(inst_from.GetEvolveLoreID());
|
||||
ets.item_from_current_amount = results.from_current_amount;
|
||||
ets.item_to_id = results.new_item_id;
|
||||
ets.item_to_current_amount = results.new_current_amount;
|
||||
@@ -314,10 +295,6 @@ uint32 EvolvingItemsManager::GetFirstItemInLoreGroupByItemID(const uint32 item_i
|
||||
|
||||
void EvolvingItemsManager::LoadPlayerEvent(const EQ::ItemInstance &inst, PlayerEvent::EvolveItem &e)
|
||||
{
|
||||
if (!inst) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.item_id = inst.GetID();
|
||||
e.item_name = inst.GetItem() ? inst.GetItem()->Name : std::string();
|
||||
e.level = inst.GetEvolveLvl();
|
||||
|
||||
@@ -53,18 +53,15 @@ public:
|
||||
ItemsEvolvingDetailsRepository::ItemsEvolvingDetails GetEvolveItemDetails(uint64 id);
|
||||
EvolveTransfer DetermineTransferResults(const EQ::ItemInstance& inst_from, const EQ::ItemInstance& inst_to);
|
||||
EvolveGetNextItem GetNextItemByXP(const EQ::ItemInstance &inst_in, int64 in_xp);
|
||||
std::map<uint32, ItemsEvolvingDetailsRepository::ItemsEvolvingDetails>& GetEvolvingItemsCache() { return m_evolving_items_cache; }
|
||||
std::map<uint32, ItemsEvolvingDetailsRepository::ItemsEvolvingDetails>& GetEvolvingItemsCache() { return evolving_items_cache; }
|
||||
std::vector<ItemsEvolvingDetailsRepository::ItemsEvolvingDetails> GetEvolveIDItems(uint32 evolve_id);
|
||||
|
||||
static EvolvingItemsManager* Instance()
|
||||
{
|
||||
static EvolvingItemsManager instance;
|
||||
return &instance;
|
||||
}
|
||||
private:
|
||||
std::map<uint32, ItemsEvolvingDetailsRepository::ItemsEvolvingDetails> m_evolving_items_cache;
|
||||
std::map<uint32, ItemsEvolvingDetailsRepository::ItemsEvolvingDetails> evolving_items_cache;
|
||||
Database * m_db;
|
||||
Database * m_content_db;
|
||||
};
|
||||
|
||||
extern EvolvingItemsManager evolving_items_manager;
|
||||
|
||||
#endif //EVOLVING_H
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "expedition_lockout_timer.h"
|
||||
#include "../common/strings.h"
|
||||
#include "../common/rulesys.h"
|
||||
#include "../common/util/uuid.h"
|
||||
#include <fmt/format.h>
|
||||
|
||||
const char* const DZ_REPLAY_TIMER_NAME = "Replay Timer"; // see December 14, 2016 patch notes
|
||||
|
||||
ExpeditionLockoutTimer::ExpeditionLockoutTimer(
|
||||
std::string expedition_uuid, std::string expedition_name,
|
||||
std::string event_name, uint64_t expire_time, uint32_t duration
|
||||
) :
|
||||
m_expedition_uuid{std::move(expedition_uuid)},
|
||||
m_expedition_name{std::move(expedition_name)},
|
||||
m_event_name{std::move(event_name)},
|
||||
m_expire_time(std::chrono::system_clock::from_time_t(expire_time)),
|
||||
m_duration(duration)
|
||||
{
|
||||
if (m_event_name == DZ_REPLAY_TIMER_NAME)
|
||||
{
|
||||
m_is_replay_timer = true;
|
||||
}
|
||||
}
|
||||
|
||||
ExpeditionLockoutTimer ExpeditionLockoutTimer::CreateLockout(
|
||||
const std::string& expedition_name, const std::string& event_name, uint32_t seconds, std::string uuid)
|
||||
{
|
||||
seconds = static_cast<uint32_t>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
|
||||
|
||||
if (uuid.empty())
|
||||
{
|
||||
uuid = EQ::Util::UUID::Generate().ToString();
|
||||
}
|
||||
|
||||
ExpeditionLockoutTimer lockout{uuid, expedition_name, event_name, 0, seconds};
|
||||
lockout.Reset(); // sets expire time
|
||||
return lockout;
|
||||
}
|
||||
|
||||
uint32_t ExpeditionLockoutTimer::GetSecondsRemaining() const
|
||||
{
|
||||
auto now = std::chrono::system_clock::now();
|
||||
if (m_expire_time > now)
|
||||
{
|
||||
auto remaining = m_expire_time - now;
|
||||
return static_cast<uint32_t>(std::chrono::duration_cast<std::chrono::seconds>(remaining).count());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ExpeditionLockoutTimer::DaysHoursMinutes ExpeditionLockoutTimer::GetDaysHoursMinutesRemaining() const
|
||||
{
|
||||
auto seconds = GetSecondsRemaining();
|
||||
return ExpeditionLockoutTimer::DaysHoursMinutes{
|
||||
fmt::format_int(seconds / 86400).str(), // days
|
||||
fmt::format_int((seconds / 3600) % 24).str(), // hours
|
||||
fmt::format_int((seconds / 60) % 60).str() // minutes
|
||||
};
|
||||
}
|
||||
|
||||
bool ExpeditionLockoutTimer::IsSameLockout(const ExpeditionLockoutTimer& compare_lockout) const
|
||||
{
|
||||
return compare_lockout.IsSameLockout(GetExpeditionName(), GetEventName());
|
||||
}
|
||||
|
||||
bool ExpeditionLockoutTimer::IsSameLockout(
|
||||
const std::string& expedition_name, const std::string& event_name) const
|
||||
{
|
||||
return GetExpeditionName() == expedition_name && GetEventName() == event_name;
|
||||
}
|
||||
|
||||
void ExpeditionLockoutTimer::AddLockoutTime(int seconds)
|
||||
{
|
||||
seconds = static_cast<uint32_t>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
|
||||
|
||||
auto new_duration = std::max(0, static_cast<int>(m_duration.count()) + seconds);
|
||||
|
||||
auto start_time = m_expire_time - m_duration;
|
||||
m_duration = std::chrono::seconds(new_duration);
|
||||
m_expire_time = start_time + m_duration;
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EXPEDITION_LOCKOUT_TIMER_H
|
||||
#define EXPEDITION_LOCKOUT_TIMER_H
|
||||
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
|
||||
extern const char* const DZ_REPLAY_TIMER_NAME;
|
||||
|
||||
class ExpeditionLockoutTimer
|
||||
{
|
||||
public:
|
||||
ExpeditionLockoutTimer() = default;
|
||||
ExpeditionLockoutTimer(
|
||||
std::string expedition_uuid, std::string expedition_name,
|
||||
std::string event_name, uint64_t expire_time, uint32_t duration);
|
||||
|
||||
static ExpeditionLockoutTimer CreateLockout(
|
||||
const std::string& expedition_name, const std::string& event_name,
|
||||
uint32_t seconds, std::string uuid = {});
|
||||
|
||||
struct DaysHoursMinutes
|
||||
{
|
||||
std::string days;
|
||||
std::string hours;
|
||||
std::string mins;
|
||||
};
|
||||
|
||||
void AddLockoutTime(int seconds);
|
||||
uint32_t GetDuration() const { return static_cast<uint32_t>(m_duration.count()); }
|
||||
uint64_t GetExpireTime() const { return std::chrono::system_clock::to_time_t(m_expire_time); }
|
||||
uint64_t GetStartTime() const { return std::chrono::system_clock::to_time_t(m_expire_time - m_duration); }
|
||||
uint32_t GetSecondsRemaining() const;
|
||||
DaysHoursMinutes GetDaysHoursMinutesRemaining() const;
|
||||
const std::string& GetExpeditionName() const { return m_expedition_name; }
|
||||
const std::string& GetExpeditionUUID() const { return m_expedition_uuid; }
|
||||
const std::string& GetEventName() const { return m_event_name; }
|
||||
bool IsExpired() const { return GetSecondsRemaining() == 0; }
|
||||
bool IsFromExpedition(const std::string& uuid) const { return uuid == m_expedition_uuid; }
|
||||
bool IsReplayTimer() const { return m_is_replay_timer; }
|
||||
bool IsSameLockout(const ExpeditionLockoutTimer& compare_lockout) const;
|
||||
bool IsSameLockout(const std::string& expedition_name, const std::string& event_name) const;
|
||||
void Reset() { m_expire_time = std::chrono::system_clock::now() + m_duration; }
|
||||
void SetDuration(uint32_t seconds) { m_duration = std::chrono::seconds(seconds); }
|
||||
void SetExpireTime(uint64_t expire_time) { m_expire_time = std::chrono::system_clock::from_time_t(expire_time); }
|
||||
void SetUUID(const std::string& uuid) { m_expedition_uuid = uuid; }
|
||||
|
||||
private:
|
||||
bool m_is_replay_timer = false;
|
||||
std::string m_expedition_uuid; // expedition received in
|
||||
std::string m_expedition_name;
|
||||
std::string m_event_name;
|
||||
std::chrono::seconds m_duration;
|
||||
std::chrono::time_point<std::chrono::system_clock> m_expire_time;
|
||||
};
|
||||
|
||||
#endif
|
||||
+13
-12
@@ -39,7 +39,6 @@
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <sys/stat.h>
|
||||
#include <vector>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
@@ -91,21 +90,23 @@ std::string File::GetCwd()
|
||||
|
||||
FileContentsResult File::GetContents(const std::string &file_name)
|
||||
{
|
||||
std::ifstream f(file_name, std::ios::in | std::ios::binary);
|
||||
if (!f) {
|
||||
return { .error = fmt::format("Couldn't open file [{}]", file_name) };
|
||||
}
|
||||
|
||||
constexpr size_t CHUNK_SIZE = 4096; // Read 4KB chunks
|
||||
std::string error;
|
||||
std::ifstream f;
|
||||
f.open(file_name);
|
||||
std::string line;
|
||||
std::string lines;
|
||||
std::vector<char> buffer(CHUNK_SIZE);
|
||||
|
||||
while (f.read(buffer.data(), CHUNK_SIZE) || f.gcount() > 0) {
|
||||
lines.append(buffer.data(), f.gcount());
|
||||
if (f.is_open()) {
|
||||
while (f) {
|
||||
std::getline(f, line);
|
||||
lines += line + "\n";
|
||||
}
|
||||
}
|
||||
else {
|
||||
error = fmt::format("Couldn't open file [{}]", file_name);
|
||||
}
|
||||
|
||||
return FileContentsResult{
|
||||
.contents = lines,
|
||||
.error = {}
|
||||
.error = error,
|
||||
};
|
||||
}
|
||||
|
||||
+26
-28
@@ -547,62 +547,60 @@ uint32 BaseGuildManager::UpdateDbCreateGuild(std::string name, uint32 leader)
|
||||
|
||||
bool BaseGuildManager::UpdateDbDeleteGuild(uint32 guild_id, bool local_delete, bool db_delete)
|
||||
{
|
||||
auto const where_filter = fmt::format("guild_id = {}", guild_id);
|
||||
auto const bank_items = GuildBankRepository::GetWhere(*m_db, where_filter);
|
||||
|
||||
if (local_delete) {
|
||||
auto where_filter = fmt::format("guildid = {}", guild_id);
|
||||
auto bank_items = GuildBankRepository::GetWhere(*m_db, where_filter);
|
||||
if (!bank_items.empty()) {
|
||||
LogError(
|
||||
"Attempt to delete guild id [{}] that still has [{}] items in the bank. Please remove them and try "
|
||||
"again.",
|
||||
"Attempt to delete guild id [{}] that still has [{}] items in the bank. Please remove them and try again.",
|
||||
guild_id,
|
||||
bank_items.size()
|
||||
);
|
||||
LogGuilds(
|
||||
"Attempt to delete guild id [{}] that still has [{}] items in the bank. Please remove them and try "
|
||||
"again.",
|
||||
"Attempt to delete guild id [{}] that still has [{}] items in the bank. Please remove them and try again.",
|
||||
guild_id,
|
||||
bank_items.size()
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
auto res = m_guilds.find(guild_id);
|
||||
if (res != m_guilds.end()) {
|
||||
safe_delete(res->second);
|
||||
m_guilds.erase(res);
|
||||
LogGuilds("Deleted guild [{}] from memory", guild_id);
|
||||
// Does this need to be sent to world?
|
||||
else {
|
||||
std::map<uint32, GuildInfo *>::iterator res;
|
||||
res = m_guilds.find(guild_id);
|
||||
if (res != m_guilds.end()) {
|
||||
delete res->second;
|
||||
m_guilds.erase(res);
|
||||
LogGuilds("Deleted guild [{}] from memory", guild_id);
|
||||
//Does this need to be sent to world?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (db_delete) {
|
||||
auto where_filter = fmt::format("guildid = {}", guild_id);
|
||||
auto bank_items = GuildBankRepository::GetWhere(*m_db, where_filter);
|
||||
if (!bank_items.empty()) {
|
||||
LogError(
|
||||
"Attempt to delete guild id [{}] that still has [{}] items in the bank. Please remove them and try "
|
||||
"again.",
|
||||
"Attempt to delete guild id [{}] that still has [{}] items in the bank. Please remove them and try again.",
|
||||
guild_id,
|
||||
bank_items.size()
|
||||
);
|
||||
LogGuilds(
|
||||
"Attempt to delete guild id [{}] that still has [{}] items in the bank. Please remove them and try "
|
||||
"again.",
|
||||
"Attempt to delete guild id [{}] that still has [{}] items in the bank. Please remove them and try again.",
|
||||
guild_id,
|
||||
bank_items.size()
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
GuildTributesRepository::DeleteOne(*m_db, guild_id);
|
||||
GuildsRepository::DeleteOne(*m_db, guild_id);
|
||||
GuildRanksRepository::DeleteWhere(*m_db, where_filter);
|
||||
GuildPermissionsRepository::DeleteWhere(*m_db, where_filter);
|
||||
GuildMembersRepository::DeleteWhere(*m_db, where_filter);
|
||||
LogGuilds("Deleted guild [{}] from the database", guild_id);
|
||||
else {
|
||||
auto where_filter = fmt::format("guild_id = {}", guild_id);
|
||||
GuildTributesRepository::DeleteOne(*m_db, guild_id);
|
||||
GuildsRepository::DeleteOne(*m_db, guild_id);
|
||||
GuildRanksRepository::DeleteWhere(*m_db, where_filter);
|
||||
GuildPermissionsRepository::DeleteWhere(*m_db, where_filter);
|
||||
GuildMembersRepository::DeleteWhere(*m_db, where_filter);
|
||||
LogGuilds("Deleted guild [{}] from the database", guild_id);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -2028,57 +2028,3 @@ int16 EQ::InventoryProfile::_HasEvolvingItem(ItemInstQueue &iqueue, uint64 evolv
|
||||
|
||||
return INVALID_INDEX;
|
||||
}
|
||||
|
||||
|
||||
int16 EQ::InventoryProfile::FindFirstFreeSlotThatFitsItemWithStacking(ItemInstance *item_inst) const
|
||||
{
|
||||
auto item_data = item_inst->GetItem();
|
||||
if (!item_data) {
|
||||
return INVALID_INDEX;
|
||||
}
|
||||
|
||||
for (int16 i = invslot::GENERAL_BEGIN; i <= invslot::GENERAL_END; i++) {
|
||||
auto const inv_item = GetItem(i);
|
||||
if (!inv_item) {
|
||||
// Found available slot in personal inventory
|
||||
// Anything will fit here
|
||||
return i;
|
||||
}
|
||||
|
||||
if (item_data->IsClassBag() && item_inst->IsNoneEmptyContainer()) {
|
||||
// If the inbound item is a bag with items, it cannot be stored within a bag
|
||||
// Move to next potential slot
|
||||
continue;
|
||||
}
|
||||
|
||||
if (inv_item->GetID() == item_data->ID && item_data->Stackable) {
|
||||
if (item_inst->GetCharges() + inv_item->GetCharges() <= item_data->StackSize) {
|
||||
// Found a personal inventory slot that has room for a stackable addition
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
if (inv_item->IsClassBag() && CanItemFitInContainer(item_data, inv_item->GetItem())) {
|
||||
int16 const base_slot_id = CalcSlotId(i, invbag::SLOT_BEGIN);
|
||||
uint8 const bag_size = inv_item->GetItem()->BagSlots;
|
||||
uint8 const item_size = item_data->Size;
|
||||
|
||||
for (uint8 bag_slot = invbag::SLOT_BEGIN; bag_slot < bag_size; bag_slot++) {
|
||||
auto bag_item = GetItem(base_slot_id + bag_slot);
|
||||
if (!bag_item) {
|
||||
// Found available slot within bag that will hold inbound item
|
||||
return base_slot_id + bag_slot;
|
||||
}
|
||||
|
||||
if (bag_item && item_data->Stackable && bag_item->GetID() == item_data->ID) {
|
||||
if (item_inst->GetCharges() + bag_item->GetCharges() <= item_data->StackSize) {
|
||||
// Found a bag slot has room for a stackable addition
|
||||
return base_slot_id + bag_slot;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return INVALID_INDEX;
|
||||
}
|
||||
|
||||
@@ -179,7 +179,6 @@ namespace EQ
|
||||
int16 FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size = 0, bool is_arrow = false);
|
||||
int16 FindFreeSlotForTradeItem(const ItemInstance* inst, int16 general_start = invslot::GENERAL_BEGIN, uint8 bag_start = invbag::SLOT_BEGIN);
|
||||
int16 FindFirstFreeSlotThatFitsItem(const EQ::ItemData *inst);
|
||||
int16 FindFirstFreeSlotThatFitsItemWithStacking(ItemInstance *inst) const;
|
||||
|
||||
// Calculate slot_id for an item within a bag
|
||||
static int16 CalcSlotId(int16 slot_id); // Calc parent bag's slot_id
|
||||
|
||||
@@ -259,84 +259,3 @@ bool IpUtil::IsIPAddress(const std::string &ip_address)
|
||||
}
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#pragma comment(lib, "ws2_32.lib") // Link against Winsock library
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h> // For inet_pton
|
||||
#pragma comment(lib, "ws2_32.lib") // Link against Winsock library
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h> // For inet_pton
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
bool IpUtil::IsPortInUse(const std::string& ip, int port) {
|
||||
bool in_use = false;
|
||||
|
||||
#ifdef _WIN32
|
||||
WSADATA wsaData;
|
||||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
||||
std::cerr << "WSAStartup failed\n";
|
||||
return true; // Assume in use on failure
|
||||
}
|
||||
#endif
|
||||
|
||||
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sock < 0) {
|
||||
#ifdef _WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
return true; // Assume in use on failure
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
int opt = 1;
|
||||
setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char*)&opt, sizeof(opt)); // Windows-specific
|
||||
#else
|
||||
int opt = 1;
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); // Linux/macOS
|
||||
#endif
|
||||
|
||||
sockaddr_in addr{};
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
|
||||
// Convert IP address from string to binary format
|
||||
if (inet_pton(AF_INET, ip.c_str(), &addr.sin_addr) <= 0) {
|
||||
std::cerr << "Invalid IP address format: " << ip << std::endl;
|
||||
#ifdef _WIN32
|
||||
closesocket(sock);
|
||||
WSACleanup();
|
||||
#else
|
||||
close(sock);
|
||||
#endif
|
||||
return true; // Assume in use on failure
|
||||
}
|
||||
|
||||
if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
|
||||
in_use = true; // Bind failed, port is in use
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
closesocket(sock);
|
||||
WSACleanup();
|
||||
#else
|
||||
close(sock);
|
||||
#endif
|
||||
|
||||
return in_use;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@ public:
|
||||
int port
|
||||
);
|
||||
static bool IsIPAddress(const std::string &ip_address);
|
||||
static bool IsPortInUse(const std::string& ip, int port);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace EQ {
|
||||
EQ_EXCEPT("IPC Mutex", "Could not create mutex.");
|
||||
}
|
||||
#else
|
||||
std::string final_name = fmt::format("{}/{}.lock", PathManager::Instance()->GetSharedMemoryPath(), name);
|
||||
std::string final_name = fmt::format("{}/{}.lock", path.GetSharedMemoryPath(), name);
|
||||
|
||||
#ifdef __DARWIN
|
||||
#if __DARWIN_C_LEVEL < 200809L
|
||||
|
||||
+10
-18
@@ -574,7 +574,7 @@ EQ::ItemInstance* EQ::ItemInstance::GetOrnamentationAugment() const
|
||||
uint32 EQ::ItemInstance::GetOrnamentHeroModel(int32 material_slot) const
|
||||
{
|
||||
// Not a Hero Forge item.
|
||||
if (m_ornament_hero_model == 0) {
|
||||
if (m_ornament_hero_model == 0 || material_slot < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -906,32 +906,24 @@ bool EQ::ItemInstance::IsSlotAllowed(int16 slot_id) const {
|
||||
|
||||
bool EQ::ItemInstance::IsDroppable(bool recurse) const
|
||||
{
|
||||
if (!m_item) {
|
||||
if (!m_item)
|
||||
return false;
|
||||
}
|
||||
/*if (m_ornamentidfile) // not implemented
|
||||
return false;*/
|
||||
if (m_attuned) {
|
||||
if (m_attuned)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (RuleI(World, FVNoDropFlag) == FVNoDropFlagRule::Enabled && m_item->FVNoDrop == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_item->NoDrop == 0) {
|
||||
/*if (m_item->FVNoDrop != 0) // not implemented
|
||||
return false;*/
|
||||
if (m_item->NoDrop == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (recurse) {
|
||||
for (auto iter: m_contents) {
|
||||
if (!iter.second) {
|
||||
for (auto iter : m_contents) {
|
||||
if (!iter.second)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!iter.second->IsDroppable(recurse)) {
|
||||
if (!iter.second->IsDroppable(recurse))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1799,7 +1791,7 @@ std::vector<std::string> EQ::ItemInstance::GetAugmentNames() const
|
||||
|
||||
for (uint8 slot_id = invaug::SOCKET_BEGIN; slot_id <= invaug::SOCKET_END; slot_id++) {
|
||||
const auto augment = GetAugment(slot_id);
|
||||
augment_names.push_back(augment ? augment->GetItem()->Name : "");
|
||||
augment_names.push_back(augment ? augment->GetItem()->Name : "None");
|
||||
}
|
||||
|
||||
return augment_names;
|
||||
|
||||
@@ -335,7 +335,7 @@ namespace EQ
|
||||
void SetEvolveAddToCurrentAmount(const uint64 in) const { m_evolving_details.current_amount += in; }
|
||||
void SetEvolveFinalItemID(const uint32 in) const { m_evolving_details.final_item_id = in; }
|
||||
bool TransferOwnership(Database& db, const uint32 to_char_id) const;
|
||||
void CalculateEvolveProgression() const { m_evolving_details.progression = EvolvingItemsManager::Instance()->CalculateProgression(GetEvolveCurrentAmount(), GetID()); }
|
||||
void CalculateEvolveProgression() const { m_evolving_details.progression = evolving_items_manager.CalculateProgression(GetEvolveCurrentAmount(), GetID()); }
|
||||
|
||||
protected:
|
||||
//////////////////////////
|
||||
|
||||
@@ -25,7 +25,6 @@ struct LootItem {
|
||||
uint16 trivial_max_level;
|
||||
uint16 npc_min_level;
|
||||
uint16 npc_max_level;
|
||||
uint32 lootdrop_id; // required for zone state referencing
|
||||
};
|
||||
|
||||
typedef std::list<LootItem*> LootItems;
|
||||
|
||||
+104
-142
@@ -1,16 +1,12 @@
|
||||
#include "daybreak_connection.h"
|
||||
#include "../event/event_loop.h"
|
||||
#include "../event/task.h"
|
||||
#include "../data_verification.h"
|
||||
#include "crc32.h"
|
||||
#include "../eqemu_logsys.h"
|
||||
#include <zlib.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
// observed client receive window is 300 packets, 140KB
|
||||
constexpr size_t MAX_CLIENT_RECV_PACKETS_PER_WINDOW = 300;
|
||||
constexpr size_t MAX_CLIENT_RECV_BYTES_PER_WINDOW = 140 * 1024;
|
||||
|
||||
// buffer pools
|
||||
SendBufferPool send_buffer_pool;
|
||||
#include <sstream>
|
||||
|
||||
EQ::Net::DaybreakConnectionManager::DaybreakConnectionManager()
|
||||
{
|
||||
@@ -57,22 +53,16 @@ void EQ::Net::DaybreakConnectionManager::Attach(uv_loop_t *loop)
|
||||
uv_ip4_addr("0.0.0.0", m_options.port, &recv_addr);
|
||||
int rc = uv_udp_bind(&m_socket, (const struct sockaddr *)&recv_addr, UV_UDP_REUSEADDR);
|
||||
|
||||
rc = uv_udp_recv_start(
|
||||
&m_socket,
|
||||
[](uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
|
||||
if (suggested_size > 65536) {
|
||||
buf->base = new char[suggested_size];
|
||||
buf->len = suggested_size;
|
||||
return;
|
||||
}
|
||||
|
||||
static thread_local char temp_buf[65536];
|
||||
buf->base = temp_buf;
|
||||
buf->len = 65536;
|
||||
},
|
||||
rc = uv_udp_recv_start(&m_socket,
|
||||
[](uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
|
||||
buf->base = new char[suggested_size];
|
||||
memset(buf->base, 0, suggested_size);
|
||||
buf->len = suggested_size;
|
||||
},
|
||||
[](uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags) {
|
||||
DaybreakConnectionManager *c = (DaybreakConnectionManager*)handle->data;
|
||||
if (nread < 0 || addr == nullptr) {
|
||||
delete[] buf->base;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -80,10 +70,7 @@ void EQ::Net::DaybreakConnectionManager::Attach(uv_loop_t *loop)
|
||||
uv_ip4_name((const sockaddr_in*)addr, endpoint, 16);
|
||||
auto port = ntohs(((const sockaddr_in*)addr)->sin_port);
|
||||
c->ProcessPacket(endpoint, port, buf->base, nread);
|
||||
|
||||
if (buf->len > 65536) {
|
||||
delete[] buf->base;
|
||||
}
|
||||
delete[] buf->base;
|
||||
});
|
||||
|
||||
m_attached = loop;
|
||||
@@ -323,7 +310,7 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner
|
||||
m_last_session_stats = Clock::now();
|
||||
m_outgoing_budget = owner->m_options.outgoing_data_rate;
|
||||
|
||||
LogNetClient("New session [{}] with encode key [{}]", m_connect_code, HostToNetwork(m_encode_key));
|
||||
LogNetcode("New session [{}] with encode key [{}]", m_connect_code, HostToNetwork(m_encode_key));
|
||||
}
|
||||
|
||||
//new connection made as client
|
||||
@@ -355,16 +342,16 @@ EQ::Net::DaybreakConnection::~DaybreakConnection()
|
||||
|
||||
void EQ::Net::DaybreakConnection::Close()
|
||||
{
|
||||
if (m_status != StatusDisconnected && m_status != StatusDisconnecting) {
|
||||
if (m_status == StatusConnected) {
|
||||
FlushBuffer();
|
||||
SendDisconnect();
|
||||
}
|
||||
|
||||
if (m_status != StatusDisconnecting) {
|
||||
m_close_time = Clock::now();
|
||||
ChangeStatus(StatusDisconnecting);
|
||||
}
|
||||
else {
|
||||
ChangeStatus(StatusDisconnecting);
|
||||
}
|
||||
|
||||
ChangeStatus(StatusDisconnecting);
|
||||
}
|
||||
|
||||
void EQ::Net::DaybreakConnection::QueuePacket(Packet &p)
|
||||
@@ -647,7 +634,7 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
|
||||
p.PutSerialize(0, reply);
|
||||
InternalSend(p);
|
||||
|
||||
LogNetClient("[OP_SessionRequest] Session [{}] started with encode key [{}]", m_connect_code, HostToNetwork(m_encode_key));
|
||||
LogNetcode("[OP_SessionRequest] Session [{}] started with encode key [{}]", m_connect_code, HostToNetwork(m_encode_key));
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -666,7 +653,7 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
|
||||
m_max_packet_size = reply.max_packet_size;
|
||||
ChangeStatus(StatusConnected);
|
||||
|
||||
LogNetClient(
|
||||
LogNetcode(
|
||||
"[OP_SessionResponse] Session [{}] refresh with encode key [{}]",
|
||||
m_connect_code,
|
||||
HostToNetwork(m_encode_key)
|
||||
@@ -795,7 +782,7 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
|
||||
SendDisconnect();
|
||||
}
|
||||
|
||||
LogNetClient(
|
||||
LogNetcode(
|
||||
"[OP_SessionDisconnect] Session [{}] disconnect with encode key [{}]",
|
||||
m_connect_code,
|
||||
HostToNetwork(m_encode_key)
|
||||
@@ -865,7 +852,7 @@ bool EQ::Net::DaybreakConnection::ValidateCRC(Packet &p)
|
||||
}
|
||||
|
||||
if (p.Length() < (size_t)m_crc_bytes) {
|
||||
LogNetClient("Session [{}] ignored packet (crc bytes invalid on session)", m_connect_code);
|
||||
LogNetcode("Session [{}] ignored packet (crc bytes invalid on session)", m_connect_code);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1056,7 +1043,7 @@ void EQ::Net::DaybreakConnection::Decompress(Packet &p, size_t offset, size_t le
|
||||
return;
|
||||
}
|
||||
|
||||
static thread_local uint8_t new_buffer[4096];
|
||||
static uint8_t new_buffer[4096];
|
||||
uint8_t *buffer = (uint8_t*)p.Data() + offset;
|
||||
uint32_t new_length = 0;
|
||||
|
||||
@@ -1077,7 +1064,7 @@ void EQ::Net::DaybreakConnection::Decompress(Packet &p, size_t offset, size_t le
|
||||
|
||||
void EQ::Net::DaybreakConnection::Compress(Packet &p, size_t offset, size_t length)
|
||||
{
|
||||
static thread_local uint8_t new_buffer[2048] = { 0 };
|
||||
uint8_t new_buffer[2048] = { 0 };
|
||||
uint8_t *buffer = (uint8_t*)p.Data() + offset;
|
||||
uint32_t new_length = 0;
|
||||
bool send_uncompressed = true;
|
||||
@@ -1104,6 +1091,10 @@ void EQ::Net::DaybreakConnection::ProcessResend()
|
||||
}
|
||||
}
|
||||
|
||||
// observed client receive window is 300 packets, 140KB
|
||||
constexpr size_t MAX_CLIENT_RECV_PACKETS_PER_WINDOW = 300;
|
||||
constexpr size_t MAX_CLIENT_RECV_BYTES_PER_WINDOW = 140 * 1024;
|
||||
|
||||
void EQ::Net::DaybreakConnection::ProcessResend(int stream)
|
||||
{
|
||||
if (m_status == DbProtocolStatus::StatusDisconnected) {
|
||||
@@ -1126,57 +1117,34 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream)
|
||||
auto &first_packet = s->sent_packets.begin()->second;
|
||||
auto time_since_first_sent = std::chrono::duration_cast<std::chrono::milliseconds>(now - first_packet.first_sent).count();
|
||||
|
||||
if (time_since_first_sent >= m_owner->m_options.resend_timeout) {
|
||||
auto now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();
|
||||
auto first_sent_ms = std::chrono::duration_cast<std::chrono::milliseconds>(first_packet.first_sent.time_since_epoch()).count();
|
||||
LogNetClient(
|
||||
"Closing connection for m_endpoint [{}] m_port [{}] time_since_first_sent [{}] >= m_owner->m_options.resend_timeout [{}] now [{}] first_packet.first_sent [{}]",
|
||||
m_endpoint,
|
||||
m_port,
|
||||
time_since_first_sent,
|
||||
m_owner->m_options.resend_timeout,
|
||||
now_ms,
|
||||
first_sent_ms
|
||||
);
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_last_ack - now > std::chrono::milliseconds(1000)) {
|
||||
LogNetClient(
|
||||
"Resetting m_acked_since_last_resend flag for m_endpoint [{}] m_port [{}]",
|
||||
m_endpoint,
|
||||
m_port
|
||||
);
|
||||
m_acked_since_last_resend = true;
|
||||
}
|
||||
|
||||
// make sure that the first_packet in the list first_sent time is within the resend_delay and now
|
||||
// if it is not, then we need to resend all packets in the list
|
||||
if (time_since_first_sent <= first_packet.resend_delay && !m_acked_since_last_resend) {
|
||||
LogNetClientDetail(
|
||||
"Not resending packets for m_endpoint [{}] m_port [{}] packets [{}] time_first_sent [{}] resend_delay [{}] m_acked_since_last_resend [{}]",
|
||||
m_endpoint,
|
||||
m_port,
|
||||
s->sent_packets.size(),
|
||||
LogNetcodeDetail(
|
||||
"Not resending packets for stream [{}] time since first sent [{}] resend delay [{}] m_acked_since_last_resend [{}]",
|
||||
stream,
|
||||
time_since_first_sent,
|
||||
first_packet.resend_delay,
|
||||
m_acked_since_last_resend
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (time_since_first_sent >= m_owner->m_options.resend_timeout) {
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (EQEmuLogSys::Instance()->IsLogEnabled(Logs::General, Logs::NetClient)) {
|
||||
if (LogSys.IsLogEnabled(Logs::Detail, Logs::Netcode)) {
|
||||
size_t total_size = 0;
|
||||
for (auto &e: s->sent_packets) {
|
||||
total_size += e.second.packet.Length();
|
||||
}
|
||||
|
||||
LogNetClientDetail(
|
||||
"Resending packets for m_endpoint [{}] m_port [{}] packet count [{}] total packet size [{}] m_acked_since_last_resend [{}]",
|
||||
m_endpoint,
|
||||
m_port,
|
||||
LogNetcodeDetail(
|
||||
"Resending packets for stream [{}] packet count [{}] total packet size [{}] m_acked_since_last_resend [{}]",
|
||||
stream,
|
||||
s->sent_packets.size(),
|
||||
total_size,
|
||||
m_acked_since_last_resend
|
||||
@@ -1186,13 +1154,10 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream)
|
||||
for (auto &e: s->sent_packets) {
|
||||
if (m_resend_packets_sent >= MAX_CLIENT_RECV_PACKETS_PER_WINDOW ||
|
||||
m_resend_bytes_sent >= MAX_CLIENT_RECV_BYTES_PER_WINDOW) {
|
||||
LogNetClient(
|
||||
"Stopping resend because we hit thresholds for m_endpoint [{}] m_port [{}] m_resend_packets_sent [{}] max [{}] in_queue [{}] m_resend_bytes_sent [{}] max [{}]",
|
||||
m_endpoint,
|
||||
m_port,
|
||||
LogNetcodeDetail(
|
||||
"Stopping resend because we hit thresholds m_resend_packets_sent [{}] max [{}] m_resend_bytes_sent [{}] max [{}]",
|
||||
m_resend_packets_sent,
|
||||
MAX_CLIENT_RECV_PACKETS_PER_WINDOW,
|
||||
s->sent_packets.size(),
|
||||
m_resend_bytes_sent,
|
||||
MAX_CLIENT_RECV_BYTES_PER_WINDOW
|
||||
);
|
||||
@@ -1229,11 +1194,11 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream)
|
||||
}
|
||||
|
||||
m_acked_since_last_resend = false;
|
||||
m_last_ack = now;
|
||||
}
|
||||
|
||||
void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq)
|
||||
{
|
||||
|
||||
auto now = Clock::now();
|
||||
auto s = &m_streams[stream];
|
||||
auto iter = s->sent_packets.begin();
|
||||
@@ -1249,14 +1214,12 @@ void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq)
|
||||
m_rolling_ping = (m_rolling_ping * 2 + round_time) / 3;
|
||||
|
||||
iter = s->sent_packets.erase(iter);
|
||||
m_acked_since_last_resend = true;
|
||||
}
|
||||
else {
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
m_acked_since_last_resend = true;
|
||||
m_last_ack = now;
|
||||
}
|
||||
|
||||
void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq)
|
||||
@@ -1274,9 +1237,6 @@ void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq)
|
||||
|
||||
s->sent_packets.erase(iter);
|
||||
}
|
||||
|
||||
m_acked_since_last_resend = true;
|
||||
m_last_ack = now;
|
||||
}
|
||||
|
||||
void EQ::Net::DaybreakConnection::UpdateDataBudget(double budget_add)
|
||||
@@ -1373,97 +1333,99 @@ void EQ::Net::DaybreakConnection::SendKeepAlive()
|
||||
InternalSend(p);
|
||||
}
|
||||
|
||||
void EQ::Net::DaybreakConnection::InternalSend(Packet &p) {
|
||||
void EQ::Net::DaybreakConnection::InternalSend(Packet &p)
|
||||
{
|
||||
if (m_owner->m_options.outgoing_data_rate > 0.0) {
|
||||
auto new_budget = m_outgoing_budget - (p.Length() / 1024.0);
|
||||
if (new_budget <= 0.0) {
|
||||
m_stats.dropped_datarate_packets++;
|
||||
return;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
m_outgoing_budget = new_budget;
|
||||
}
|
||||
}
|
||||
|
||||
m_last_send = Clock::now();
|
||||
|
||||
auto pooled_opt = send_buffer_pool.acquire();
|
||||
if (!pooled_opt) {
|
||||
m_stats.dropped_datarate_packets++;
|
||||
return;
|
||||
}
|
||||
|
||||
auto [send_req, data, ctx] = *pooled_opt;
|
||||
ctx->pool = &send_buffer_pool; // set pool pointer
|
||||
|
||||
sockaddr_in send_addr{};
|
||||
uv_ip4_addr(m_endpoint.c_str(), m_port, &send_addr);
|
||||
uv_buf_t send_buffers[1];
|
||||
auto send_func = [](uv_udp_send_t* req, int status) {
|
||||
delete[](char*)req->data;
|
||||
delete req;
|
||||
};
|
||||
|
||||
if (PacketCanBeEncoded(p)) {
|
||||
|
||||
m_stats.bytes_before_encode += p.Length();
|
||||
|
||||
DynamicPacket out;
|
||||
out.PutPacket(0, p);
|
||||
|
||||
for (auto &m_encode_passe: m_encode_passes) {
|
||||
switch (m_encode_passe) {
|
||||
case EncodeCompression:
|
||||
if (out.GetInt8(0) == 0) {
|
||||
Compress(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size());
|
||||
} else {
|
||||
Compress(out, 1, out.Length() - 1);
|
||||
}
|
||||
break;
|
||||
case EncodeXOR:
|
||||
if (out.GetInt8(0) == 0) {
|
||||
Encode(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size());
|
||||
} else {
|
||||
Encode(out, 1, out.Length() - 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
switch (m_encode_passes[i]) {
|
||||
case EncodeCompression:
|
||||
if (out.GetInt8(0) == 0)
|
||||
Compress(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size());
|
||||
else
|
||||
Compress(out, 1, out.Length() - 1);
|
||||
break;
|
||||
case EncodeXOR:
|
||||
if (out.GetInt8(0) == 0)
|
||||
Encode(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size());
|
||||
else
|
||||
Encode(out, 1, out.Length() - 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
AppendCRC(out);
|
||||
|
||||
uv_udp_send_t *send_req = new uv_udp_send_t;
|
||||
memset(send_req, 0, sizeof(*send_req));
|
||||
sockaddr_in send_addr;
|
||||
uv_ip4_addr(m_endpoint.c_str(), m_port, &send_addr);
|
||||
uv_buf_t send_buffers[1];
|
||||
|
||||
char *data = new char[out.Length()];
|
||||
memcpy(data, out.Data(), out.Length());
|
||||
send_buffers[0] = uv_buf_init(data, out.Length());
|
||||
} else {
|
||||
memcpy(data, p.Data(), p.Length());
|
||||
send_buffers[0] = uv_buf_init(data, p.Length());
|
||||
send_req->data = send_buffers[0].base;
|
||||
|
||||
m_stats.sent_bytes += out.Length();
|
||||
m_stats.sent_packets++;
|
||||
if (m_owner->m_options.simulated_out_packet_loss && m_owner->m_options.simulated_out_packet_loss >= m_owner->m_rand.Int(0, 100)) {
|
||||
delete[](char*)send_req->data;
|
||||
delete send_req;
|
||||
return;
|
||||
}
|
||||
|
||||
uv_udp_send(send_req, &m_owner->m_socket, send_buffers, 1, (sockaddr*)&send_addr, send_func);
|
||||
return;
|
||||
}
|
||||
|
||||
m_stats.bytes_before_encode += p.Length();
|
||||
|
||||
uv_udp_send_t *send_req = new uv_udp_send_t;
|
||||
sockaddr_in send_addr;
|
||||
uv_ip4_addr(m_endpoint.c_str(), m_port, &send_addr);
|
||||
uv_buf_t send_buffers[1];
|
||||
|
||||
char *data = new char[p.Length()];
|
||||
memcpy(data, p.Data(), p.Length());
|
||||
send_buffers[0] = uv_buf_init(data, p.Length());
|
||||
send_req->data = send_buffers[0].base;
|
||||
|
||||
m_stats.sent_bytes += p.Length();
|
||||
m_stats.sent_packets++;
|
||||
|
||||
if (m_owner->m_options.simulated_out_packet_loss &&
|
||||
m_owner->m_options.simulated_out_packet_loss >= m_owner->m_rand.Int(0, 100)) {
|
||||
send_buffer_pool.release(ctx);
|
||||
if (m_owner->m_options.simulated_out_packet_loss && m_owner->m_options.simulated_out_packet_loss >= m_owner->m_rand.Int(0, 100)) {
|
||||
delete[](char*)send_req->data;
|
||||
delete send_req;
|
||||
return;
|
||||
}
|
||||
|
||||
int send_result = uv_udp_send(
|
||||
send_req, &m_owner->m_socket, send_buffers, 1, (sockaddr *)&send_addr,
|
||||
[](uv_udp_send_t *req, int status) {
|
||||
auto *ctx = reinterpret_cast<EmbeddedContext *>(req->data);
|
||||
if (!ctx) {
|
||||
std::cerr << "Error: send_req->data is null in callback!" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (status < 0) {
|
||||
std::cerr << "uv_udp_send failed: " << uv_strerror(status) << std::endl;
|
||||
}
|
||||
|
||||
ctx->pool->release(ctx);
|
||||
}
|
||||
);
|
||||
|
||||
if (send_result < 0) {
|
||||
std::cerr << "uv_udp_send() failed: " << uv_strerror(send_result) << std::endl;
|
||||
send_buffer_pool.release(ctx);
|
||||
}
|
||||
uv_udp_send(send_req, &m_owner->m_socket, send_buffers, 1, (sockaddr*)&send_addr, send_func);
|
||||
}
|
||||
|
||||
void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id, bool reliable)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "../random.h"
|
||||
#include "packet.h"
|
||||
#include "daybreak_structs.h"
|
||||
#include "daybreak_pooling.h"
|
||||
#include <uv.h>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
@@ -186,7 +185,6 @@ namespace EQ
|
||||
size_t m_resend_packets_sent = 0;
|
||||
size_t m_resend_bytes_sent = 0;
|
||||
bool m_acked_since_last_resend = false;
|
||||
Timestamp m_last_ack;
|
||||
|
||||
struct DaybreakSentPacket
|
||||
{
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
#include <iostream>
|
||||
#include "../eqemu_logsys.h"
|
||||
#include <uv.h>
|
||||
|
||||
constexpr size_t UDP_BUFFER_SIZE = 512;
|
||||
|
||||
struct EmbeddedContext {
|
||||
size_t pool_index;
|
||||
class SendBufferPool* pool;
|
||||
};
|
||||
|
||||
class SendBufferPool {
|
||||
public:
|
||||
explicit SendBufferPool(size_t initial_capacity = 64)
|
||||
: m_capacity(initial_capacity), m_head(0)
|
||||
{
|
||||
LogNetClient("[SendBufferPool] Initializing with capacity [{}]", (int)m_capacity);
|
||||
|
||||
m_pool.reserve(m_capacity);
|
||||
m_locks = std::make_unique<std::atomic_bool[]>(m_capacity);
|
||||
|
||||
for (size_t i = 0; i < m_capacity; ++i) {
|
||||
auto* req = new PooledUdpSend();
|
||||
req->context.pool_index = i;
|
||||
req->context.pool = this;
|
||||
req->uv_req.data = &req->context;
|
||||
|
||||
m_pool.emplace_back(std::unique_ptr<PooledUdpSend>(req));
|
||||
m_locks[i].store(false, std::memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<std::tuple<uv_udp_send_t*, char*, EmbeddedContext*>> acquire() {
|
||||
size_t cap = m_capacity.load(std::memory_order_acquire);
|
||||
for (size_t i = 0; i < cap; ++i) {
|
||||
size_t index = m_head.fetch_add(1, std::memory_order_relaxed) % cap;
|
||||
bool expected = false;
|
||||
if (m_locks[index].compare_exchange_strong(expected, true)) {
|
||||
auto* req = m_pool[index].get();
|
||||
LogNetClientDetail("[SendBufferPool] Acquired [{}]", index);
|
||||
return std::make_tuple(&req->uv_req, req->buffer.data(), &req->context);
|
||||
}
|
||||
}
|
||||
|
||||
LogNetClient("[SendBufferPool] Growing from [{}] to [{}]", cap, cap * 2);
|
||||
grow();
|
||||
return acquireAfterGrowth();
|
||||
}
|
||||
|
||||
void release(EmbeddedContext* ctx) {
|
||||
if (!ctx || ctx->pool != this || ctx->pool_index >= m_capacity.load(std::memory_order_acquire)) {
|
||||
LogNetClient("[SendBufferPool] Invalid context release [{}]", ctx ? ctx->pool_index : -1);
|
||||
return;
|
||||
}
|
||||
m_locks[ctx->pool_index].store(false, std::memory_order_release);
|
||||
LogNetClientDetail("[SendBufferPool] Released [{}]", ctx->pool_index);
|
||||
}
|
||||
|
||||
private:
|
||||
struct PooledUdpSend {
|
||||
uv_udp_send_t uv_req;
|
||||
std::array<char, UDP_BUFFER_SIZE> buffer;
|
||||
EmbeddedContext context;
|
||||
};
|
||||
|
||||
std::vector<std::unique_ptr<PooledUdpSend>> m_pool;
|
||||
std::unique_ptr<std::atomic_bool[]> m_locks;
|
||||
std::atomic<size_t> m_capacity;
|
||||
std::atomic<size_t> m_head;
|
||||
std::mutex m_grow_mutex;
|
||||
|
||||
void grow() {
|
||||
std::lock_guard<std::mutex> lock(m_grow_mutex);
|
||||
|
||||
size_t old_cap = m_capacity.load(std::memory_order_acquire);
|
||||
size_t new_cap = old_cap * 2;
|
||||
|
||||
m_pool.reserve(new_cap);
|
||||
for (size_t i = old_cap; i < new_cap; ++i) {
|
||||
auto* req = new PooledUdpSend();
|
||||
req->context.pool_index = i;
|
||||
req->context.pool = this;
|
||||
req->uv_req.data = &req->context;
|
||||
|
||||
m_pool.emplace_back(std::unique_ptr<PooledUdpSend>(req));
|
||||
}
|
||||
|
||||
auto new_locks = std::make_unique<std::atomic_bool[]>(new_cap);
|
||||
for (size_t i = 0; i < old_cap; ++i) {
|
||||
new_locks[i].store(m_locks[i].load(std::memory_order_acquire));
|
||||
}
|
||||
for (size_t i = old_cap; i < new_cap; ++i) {
|
||||
new_locks[i].store(false, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
m_locks = std::move(new_locks);
|
||||
m_capacity.store(new_cap, std::memory_order_release);
|
||||
|
||||
LogNetClient("[SendBufferPool] Grew to [{}] from [{}]", new_cap, old_cap);
|
||||
}
|
||||
|
||||
std::optional<std::tuple<uv_udp_send_t*, char*, EmbeddedContext*>> acquireAfterGrowth() {
|
||||
size_t cap = m_capacity.load(std::memory_order_acquire);
|
||||
for (size_t i = 0; i < cap; ++i) {
|
||||
size_t index = m_head.fetch_add(1, std::memory_order_relaxed) % cap;
|
||||
bool expected = false;
|
||||
if (m_locks[index].compare_exchange_strong(expected, true)) {
|
||||
auto* req = m_pool[index].get();
|
||||
LogNetClient("[SendBufferPool] Acquired after grow [{}]", index);
|
||||
return std::make_tuple(&req->uv_req, req->buffer.data(), &req->context);
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
};
|
||||
@@ -171,4 +171,3 @@ namespace EQ
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ void EQ::Net::EQStream::QueuePacket(const EQApplicationPacket *p, bool ack_req)
|
||||
OpcodeManager::EmuToName(p->GetOpcode()),
|
||||
(*m_opcode_manager)->EmuToEQ(p->GetOpcode()),
|
||||
p->Size(),
|
||||
(EQEmuLogSys::Instance()->IsLogEnabled(Logs::Detail, Logs::PacketServerClient) ? DumpPacketToString(p) : "")
|
||||
(LogSys.IsLogEnabled(Logs::Detail, Logs::PacketServerClient) ? DumpPacketToString(p) : "")
|
||||
);
|
||||
|
||||
if (m_opcode_manager && *m_opcode_manager) {
|
||||
|
||||
@@ -62,15 +62,15 @@ void EQ::Net::ServertalkClient::Connect()
|
||||
m_connecting = true;
|
||||
EQ::Net::TCPConnection::Connect(m_addr, m_port, false, [this](std::shared_ptr<EQ::Net::TCPConnection> connection) {
|
||||
if (connection == nullptr) {
|
||||
LogNetTCP("Error connecting to {0}:{1}, attempting to reconnect...", m_addr, m_port);
|
||||
LogF(Logs::General, Logs::TCPConnection, "Error connecting to {0}:{1}, attempting to reconnect...", m_addr, m_port);
|
||||
m_connecting = false;
|
||||
return;
|
||||
}
|
||||
|
||||
LogNetTCP("Connected to {0}:{1}", m_addr, m_port);
|
||||
LogF(Logs::General, Logs::TCPConnection, "Connected to {0}:{1}", m_addr, m_port);
|
||||
m_connection = connection;
|
||||
m_connection->OnDisconnect([this](EQ::Net::TCPConnection *c) {
|
||||
LogNetTCP("Connection lost to {0}:{1}, attempting to reconnect...", m_addr, m_port);
|
||||
LogF(Logs::General, Logs::TCPConnection, "Connection lost to {0}:{1}, attempting to reconnect...", m_addr, m_port);
|
||||
m_connection.reset();
|
||||
});
|
||||
|
||||
|
||||
@@ -58,15 +58,15 @@ void EQ::Net::ServertalkLegacyClient::Connect()
|
||||
m_connecting = true;
|
||||
EQ::Net::TCPConnection::Connect(m_addr, m_port, false, [this](std::shared_ptr<EQ::Net::TCPConnection> connection) {
|
||||
if (connection == nullptr) {
|
||||
LogNetTCP("Error connecting to {0}:{1}, attempting to reconnect...", m_addr, m_port);
|
||||
LogF(Logs::General, Logs::TCPConnection, "Error connecting to {0}:{1}, attempting to reconnect...", m_addr, m_port);
|
||||
m_connecting = false;
|
||||
return;
|
||||
}
|
||||
|
||||
LogNetTCP("Connected to {0}:{1}", m_addr, m_port);
|
||||
LogF(Logs::General, Logs::TCPConnection, "Connected to {0}:{1}", m_addr, m_port);
|
||||
m_connection = connection;
|
||||
m_connection->OnDisconnect([this](EQ::Net::TCPConnection *c) {
|
||||
LogNetTCP("Connection lost to {0}:{1}, attempting to reconnect...", m_addr, m_port);
|
||||
LogF(Logs::General, Logs::TCPConnection, "Connection lost to {0}:{1}, attempting to reconnect...", m_addr, m_port);
|
||||
m_connection.reset();
|
||||
});
|
||||
|
||||
@@ -131,7 +131,7 @@ void EQ::Net::ServertalkLegacyClient::ProcessReadBuffer()
|
||||
}
|
||||
else {
|
||||
EQ::Net::StaticPacket p(&m_buffer[current + 4], length);
|
||||
|
||||
|
||||
auto cb = m_message_callbacks.find(opcode);
|
||||
if (cb != m_message_callbacks.end()) {
|
||||
cb->second(opcode, p);
|
||||
|
||||
@@ -25,7 +25,7 @@ void EQ::Net::ServertalkServerConnection::Send(uint16_t opcode, EQ::Net::Packet
|
||||
return;
|
||||
|
||||
if (opcode == ServerOP_UsertoWorldReq) {
|
||||
auto req_in = (UsertoWorldRequest*)p.Data();
|
||||
auto req_in = (UsertoWorldRequest_Struct*)p.Data();
|
||||
|
||||
EQ::Net::DynamicPacket req;
|
||||
size_t i = 0;
|
||||
@@ -45,7 +45,7 @@ void EQ::Net::ServertalkServerConnection::Send(uint16_t opcode, EQ::Net::Packet
|
||||
}
|
||||
|
||||
if (opcode == ServerOP_LSClientAuth) {
|
||||
auto req_in = (ClientAuth*)p.Data();
|
||||
auto req_in = (ClientAuth_Struct*)p.Data();
|
||||
|
||||
EQ::Net::DynamicPacket req;
|
||||
size_t i = 0;
|
||||
@@ -54,7 +54,7 @@ void EQ::Net::ServertalkServerConnection::Send(uint16_t opcode, EQ::Net::Packet
|
||||
req.PutData(i, req_in->key, 30); i += 30;
|
||||
req.PutUInt8(i, req_in->lsadmin); i += 1;
|
||||
req.PutUInt16(i, req_in->is_world_admin); i += 2;
|
||||
req.PutUInt32(i, req_in->ip_address); i += 4;
|
||||
req.PutUInt32(i, req_in->ip); i += 4;
|
||||
req.PutUInt8(i, req_in->is_client_from_local_network); i += 1;
|
||||
|
||||
EQ::Net::DynamicPacket out;
|
||||
@@ -319,7 +319,7 @@ void EQ::Net::ServertalkServerConnection::ProcessMessage(EQ::Net::Packet &p)
|
||||
size_t message_len = length;
|
||||
EQ::Net::StaticPacket packet(&data[0], message_len);
|
||||
|
||||
const auto is_detail_enabled = EQEmuLogSys::Instance()->IsLogEnabled(Logs::Detail, Logs::PacketServerToServer);
|
||||
const auto is_detail_enabled = LogSys.IsLogEnabled(Logs::Detail, Logs::PacketServerToServer);
|
||||
if (opcode != ServerOP_KeepAlive || is_detail_enabled) {
|
||||
LogPacketServerToServer(
|
||||
"[{:#06x}] Size [{}] {}",
|
||||
|
||||
+55
-108
@@ -1,8 +1,5 @@
|
||||
#include "tcp_connection.h"
|
||||
#include "../event/event_loop.h"
|
||||
#include <iostream>
|
||||
|
||||
WriteReqPool tcp_write_pool;
|
||||
|
||||
void on_close_handle(uv_handle_t* handle) {
|
||||
delete (uv_tcp_t *)handle;
|
||||
@@ -67,37 +64,36 @@ void EQ::Net::TCPConnection::Connect(const std::string &addr, int port, bool ipv
|
||||
});
|
||||
}
|
||||
|
||||
void EQ::Net::TCPConnection::Start()
|
||||
{
|
||||
uv_read_start(
|
||||
(uv_stream_t *) m_socket, [](uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
|
||||
if (suggested_size > 65536) {
|
||||
buf->base = new char[suggested_size];
|
||||
buf->len = suggested_size;
|
||||
return;
|
||||
}
|
||||
void EQ::Net::TCPConnection::Start() {
|
||||
uv_read_start((uv_stream_t*)m_socket, [](uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
|
||||
buf->base = new char[suggested_size];
|
||||
buf->len = suggested_size;
|
||||
}, [](uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
|
||||
|
||||
static thread_local char temp_buf[65536];
|
||||
buf->base = temp_buf;
|
||||
buf->len = 65536;
|
||||
}, [](uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) {
|
||||
auto *connection = (TCPConnection *) stream->data;
|
||||
TCPConnection *connection = (TCPConnection*)stream->data;
|
||||
|
||||
if (nread > 0) {
|
||||
connection->Read(buf->base, nread);
|
||||
}
|
||||
else if (nread == UV_EOF) {
|
||||
connection->Disconnect();
|
||||
}
|
||||
else if (nread < 0) {
|
||||
connection->Disconnect();
|
||||
}
|
||||
if (nread > 0) {
|
||||
connection->Read(buf->base, nread);
|
||||
|
||||
if (buf->len > 65536) {
|
||||
delete [] buf->base;
|
||||
if (buf->base) {
|
||||
delete[] buf->base;
|
||||
}
|
||||
}
|
||||
);
|
||||
else if (nread == UV_EOF) {
|
||||
connection->Disconnect();
|
||||
|
||||
if (buf->base) {
|
||||
delete[] buf->base;
|
||||
}
|
||||
}
|
||||
else if (nread < 0) {
|
||||
connection->Disconnect();
|
||||
|
||||
if (buf->base) {
|
||||
delete[] buf->base;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void EQ::Net::TCPConnection::OnRead(std::function<void(TCPConnection*, const unsigned char*, size_t)> cb)
|
||||
@@ -134,92 +130,43 @@ void EQ::Net::TCPConnection::Read(const char *data, size_t count)
|
||||
}
|
||||
}
|
||||
|
||||
void EQ::Net::TCPConnection::Write(const char* data, size_t count) {
|
||||
if (!m_socket || !data || count == 0) {
|
||||
std::cerr << "TCPConnection::Write - Invalid socket or data\n";
|
||||
void EQ::Net::TCPConnection::Write(const char *data, size_t count)
|
||||
{
|
||||
if (!m_socket) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (count <= TCP_BUFFER_SIZE) {
|
||||
// Fast path: use pooled request with embedded buffer
|
||||
auto req_opt = tcp_write_pool.acquire();
|
||||
if (!req_opt) {
|
||||
std::cerr << "TCPConnection::Write - Out of write requests\n";
|
||||
return;
|
||||
struct WriteBaton
|
||||
{
|
||||
TCPConnection *connection;
|
||||
char *buffer;
|
||||
};
|
||||
|
||||
WriteBaton *baton = new WriteBaton;
|
||||
baton->connection = this;
|
||||
baton->buffer = new char[count];
|
||||
|
||||
uv_write_t *write_req = new uv_write_t;
|
||||
memset(write_req, 0, sizeof(uv_write_t));
|
||||
write_req->data = baton;
|
||||
uv_buf_t send_buffers[1];
|
||||
|
||||
memcpy(baton->buffer, data, count);
|
||||
send_buffers[0] = uv_buf_init(baton->buffer, count);
|
||||
|
||||
uv_write(write_req, (uv_stream_t*)m_socket, send_buffers, 1, [](uv_write_t* req, int status) {
|
||||
WriteBaton *baton = (WriteBaton*)req->data;
|
||||
delete[] baton->buffer;
|
||||
delete req;
|
||||
|
||||
if (status < 0) {
|
||||
baton->connection->Disconnect();
|
||||
}
|
||||
|
||||
TCPWriteReq* write_req = *req_opt;
|
||||
|
||||
// Fill buffer and set context
|
||||
memcpy(write_req->buffer.data(), data, count);
|
||||
write_req->connection = this;
|
||||
write_req->magic = 0xC0FFEE;
|
||||
|
||||
uv_buf_t buf = uv_buf_init(write_req->buffer.data(), static_cast<unsigned int>(count));
|
||||
|
||||
int result = uv_write(
|
||||
&write_req->req,
|
||||
reinterpret_cast<uv_stream_t*>(m_socket),
|
||||
&buf,
|
||||
1,
|
||||
[](uv_write_t* req, int status) {
|
||||
auto* full_req = reinterpret_cast<TCPWriteReq*>(req);
|
||||
if (full_req->magic != 0xC0FFEE) {
|
||||
std::cerr << "uv_write callback - invalid magic, skipping release\n";
|
||||
return;
|
||||
}
|
||||
|
||||
tcp_write_pool.release(full_req);
|
||||
|
||||
if (status < 0 && full_req->connection) {
|
||||
std::cerr << "uv_write failed: " << uv_strerror(status) << std::endl;
|
||||
full_req->connection->Disconnect();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (result < 0) {
|
||||
std::cerr << "uv_write() failed immediately: " << uv_strerror(result) << std::endl;
|
||||
tcp_write_pool.release(write_req);
|
||||
}
|
||||
|
||||
} else {
|
||||
// Slow path: allocate heap buffer for large write
|
||||
LogNetTCP("[TCPConnection] Large write of [{}] bytes, using heap buffer", count);
|
||||
|
||||
char* heap_buffer = new char[count];
|
||||
memcpy(heap_buffer, data, count);
|
||||
|
||||
uv_write_t* write_req = new uv_write_t;
|
||||
write_req->data = heap_buffer;
|
||||
|
||||
uv_buf_t buf = uv_buf_init(heap_buffer, static_cast<unsigned int>(count));
|
||||
|
||||
int result = uv_write(
|
||||
write_req,
|
||||
reinterpret_cast<uv_stream_t*>(m_socket),
|
||||
&buf,
|
||||
1,
|
||||
[](uv_write_t* req, int status) {
|
||||
char* data = static_cast<char*>(req->data);
|
||||
delete[] data;
|
||||
delete req;
|
||||
|
||||
if (status < 0) {
|
||||
std::cerr << "uv_write (large) failed: " << uv_strerror(status) << std::endl;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (result < 0) {
|
||||
std::cerr << "uv_write() (large) failed immediately: " << uv_strerror(result) << std::endl;
|
||||
delete[] heap_buffer;
|
||||
delete write_req;
|
||||
}
|
||||
}
|
||||
delete baton;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
std::string EQ::Net::TCPConnection::LocalIP() const
|
||||
{
|
||||
sockaddr_storage addr;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "tcp_connection_pooling.h"
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
@@ -17,7 +16,7 @@ namespace EQ
|
||||
~TCPConnection();
|
||||
|
||||
static void Connect(const std::string &addr, int port, bool ipv6, std::function<void(std::shared_ptr<TCPConnection>)> cb);
|
||||
|
||||
|
||||
void Start();
|
||||
void OnRead(std::function<void(TCPConnection*, const unsigned char *, size_t)> cb);
|
||||
void OnDisconnect(std::function<void(TCPConnection*)> cb);
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "../eqemu_logsys.h"
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <mutex>
|
||||
#include <uv.h>
|
||||
#include <iostream>
|
||||
|
||||
namespace EQ { namespace Net { class TCPConnection; } }
|
||||
|
||||
constexpr size_t TCP_BUFFER_SIZE = 8192;
|
||||
|
||||
struct TCPWriteReq {
|
||||
uv_write_t req{};
|
||||
std::array<char, TCP_BUFFER_SIZE> buffer{};
|
||||
size_t buffer_index{};
|
||||
EQ::Net::TCPConnection* connection{};
|
||||
uint32_t magic = 0xC0FFEE;
|
||||
};
|
||||
|
||||
class WriteReqPool {
|
||||
public:
|
||||
explicit WriteReqPool(size_t initial_capacity = 512)
|
||||
: m_capacity(initial_capacity), m_head(0) {
|
||||
initialize_pool(m_capacity);
|
||||
}
|
||||
|
||||
std::optional<TCPWriteReq*> acquire() {
|
||||
size_t cap = m_capacity.load(std::memory_order_acquire);
|
||||
|
||||
for (size_t i = 0; i < cap; ++i) {
|
||||
size_t index = m_head.fetch_add(1, std::memory_order_relaxed) % cap;
|
||||
|
||||
bool expected = false;
|
||||
if (m_locks[index].compare_exchange_strong(expected, true, std::memory_order_acquire)) {
|
||||
LogNetTCPDetail("[WriteReqPool] Acquired buffer index [{}]", index);
|
||||
return m_reqs[index].get();
|
||||
}
|
||||
}
|
||||
|
||||
LogNetTCP("[WriteReqPool] Growing from [{}] to [{}]", cap, cap * 2);
|
||||
grow();
|
||||
return acquireAfterGrow();
|
||||
}
|
||||
|
||||
void release(TCPWriteReq* req) {
|
||||
if (!req) return;
|
||||
|
||||
const size_t index = req->buffer_index;
|
||||
const size_t cap = m_capacity.load(std::memory_order_acquire);
|
||||
|
||||
if (index >= cap || m_reqs[index].get() != req) {
|
||||
std::cerr << "WriteReqPool::release - Invalid or stale pointer (index=" << index << ")\n";
|
||||
return;
|
||||
}
|
||||
|
||||
m_locks[index].store(false, std::memory_order_release);
|
||||
LogNetTCPDetail("[WriteReqPool] Released buffer index [{}]", index);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<TCPWriteReq>> m_reqs;
|
||||
std::unique_ptr<std::atomic_bool[]> m_locks;
|
||||
std::atomic<size_t> m_capacity;
|
||||
std::atomic<size_t> m_head;
|
||||
std::mutex m_grow_mutex;
|
||||
|
||||
void initialize_pool(size_t count) {
|
||||
m_reqs.reserve(count);
|
||||
m_locks = std::make_unique<std::atomic_bool[]>(count);
|
||||
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
auto req = std::make_unique<TCPWriteReq>();
|
||||
req->buffer_index = i;
|
||||
req->req.data = req.get(); // optional: for use in libuv callbacks
|
||||
m_locks[i].store(false, std::memory_order_relaxed);
|
||||
m_reqs.emplace_back(std::move(req));
|
||||
}
|
||||
|
||||
m_capacity.store(count, std::memory_order_release);
|
||||
}
|
||||
|
||||
void grow() {
|
||||
std::lock_guard<std::mutex> lock(m_grow_mutex);
|
||||
|
||||
const size_t old_cap = m_capacity.load(std::memory_order_acquire);
|
||||
const size_t new_cap = old_cap * 2;
|
||||
|
||||
m_reqs.reserve(new_cap);
|
||||
for (size_t i = old_cap; i < new_cap; ++i) {
|
||||
auto req = std::make_unique<TCPWriteReq>();
|
||||
req->buffer_index = i;
|
||||
req->req.data = req.get(); // optional
|
||||
m_reqs.emplace_back(std::move(req));
|
||||
}
|
||||
|
||||
auto new_locks = std::make_unique<std::atomic_bool[]>(new_cap);
|
||||
for (size_t i = 0; i < old_cap; ++i) {
|
||||
new_locks[i].store(m_locks[i].load(std::memory_order_acquire));
|
||||
}
|
||||
for (size_t i = old_cap; i < new_cap; ++i) {
|
||||
new_locks[i].store(false, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
m_locks = std::move(new_locks);
|
||||
m_capacity.store(new_cap, std::memory_order_release);
|
||||
}
|
||||
|
||||
std::optional<TCPWriteReq*> acquireAfterGrow() {
|
||||
const size_t cap = m_capacity.load(std::memory_order_acquire);
|
||||
|
||||
for (size_t i = 0; i < cap; ++i) {
|
||||
bool expected = false;
|
||||
if (m_locks[i].compare_exchange_strong(expected, true, std::memory_order_acquire)) {
|
||||
LogNetTCP("[WriteReqPool] Acquired buffer index [{}] after grow", i);
|
||||
return m_reqs[i].get();
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
};
|
||||
+18
-18
@@ -78,7 +78,7 @@ namespace RoF
|
||||
{
|
||||
//create our opcode manager if we havent already
|
||||
if (opcodes == nullptr) {
|
||||
std::string opfile = fmt::format("{}/patch_{}.conf", PathManager::Instance()->GetPatchPath(), name);
|
||||
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
|
||||
|
||||
//load up the opcode manager.
|
||||
//TODO: figure out how to support shared memory with multiple patches...
|
||||
@@ -117,7 +117,7 @@ namespace RoF
|
||||
//we need to go to every stream and replace it's manager.
|
||||
|
||||
if (opcodes != nullptr) {
|
||||
std::string opfile = fmt::format("{}/patch_{}.conf", PathManager::Instance()->GetPatchPath(), name);
|
||||
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
|
||||
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
|
||||
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
|
||||
return;
|
||||
@@ -1213,22 +1213,22 @@ namespace RoF
|
||||
case 1: { // GuildBankItemUpdate
|
||||
auto emu = (GuildBankItemUpdate_Struct *)in->pBuffer;
|
||||
auto eq = (structs::GuildBankItemUpdate_Struct *)outapp->pBuffer;
|
||||
eq->action = 0;
|
||||
OUT(unknown004);
|
||||
eq->unknown008 = 0;
|
||||
OUT(slot_id);
|
||||
OUT(area);
|
||||
OUT(display);
|
||||
OUT(item_id);
|
||||
OUT(icon_id);
|
||||
OUT(quantity);
|
||||
OUT(permissions);
|
||||
OUT(allow_merge);
|
||||
OUT(is_useable);
|
||||
OUT_str(item_name);
|
||||
OUT_str(donator);
|
||||
OUT_str(who_for);
|
||||
OUT(unknown226);
|
||||
eq->Action = 0;
|
||||
OUT(Unknown004);
|
||||
eq->Unknown08 = 0;
|
||||
OUT(SlotID);
|
||||
OUT(Area);
|
||||
OUT(Unknown012);
|
||||
OUT(ItemID);
|
||||
OUT(Icon);
|
||||
OUT(Quantity);
|
||||
OUT(Permissions);
|
||||
OUT(AllowMerge);
|
||||
OUT(Useable);
|
||||
OUT_str(ItemName);
|
||||
OUT_str(Donator);
|
||||
OUT_str(WhoFor);
|
||||
OUT(Unknown226);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
+25
-22
@@ -81,7 +81,7 @@ namespace RoF2
|
||||
//create our opcode manager if we havent already
|
||||
if (opcodes == nullptr) {
|
||||
|
||||
std::string opfile = fmt::format("{}/patch_{}.conf", PathManager::Instance()->GetPatchPath(), name);
|
||||
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
|
||||
|
||||
//load up the opcode manager.
|
||||
//TODO: figure out how to support shared memory with multiple patches...
|
||||
@@ -123,7 +123,7 @@ namespace RoF2
|
||||
//we need to go to every stream and replace it's manager.
|
||||
|
||||
if (opcodes != nullptr) {
|
||||
std::string opfile = fmt::format("{}/patch_{}.conf", PathManager::Instance()->GetPatchPath(), name);
|
||||
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
|
||||
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
|
||||
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
|
||||
return;
|
||||
@@ -1743,19 +1743,22 @@ namespace RoF2
|
||||
case 1: { // GuildBankItemUpdate
|
||||
auto emu = (GuildBankItemUpdate_Struct *)in->pBuffer;
|
||||
auto eq = (structs::GuildBankItemUpdate_Struct *)outapp->pBuffer;
|
||||
eq->action = 0;
|
||||
OUT(display);
|
||||
OUT(slot_id);
|
||||
OUT(area);
|
||||
OUT(item_id);
|
||||
OUT(icon_id);
|
||||
OUT(quantity);
|
||||
OUT(permissions);
|
||||
OUT(allow_merge);
|
||||
OUT(is_useable);
|
||||
OUT_str(item_name);
|
||||
OUT_str(donator);
|
||||
OUT_str(who_for);
|
||||
eq->Action = 0;
|
||||
OUT(Unknown004);
|
||||
eq->Unknown08 = 0;
|
||||
OUT(SlotID);
|
||||
OUT(Area);
|
||||
OUT(Unknown012);
|
||||
OUT(ItemID);
|
||||
OUT(Icon);
|
||||
OUT(Quantity);
|
||||
OUT(Permissions);
|
||||
OUT(AllowMerge);
|
||||
OUT(Useable);
|
||||
OUT_str(ItemName);
|
||||
OUT_str(Donator);
|
||||
OUT_str(WhoFor);
|
||||
OUT(Unknown226);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -4688,7 +4691,7 @@ namespace RoF2
|
||||
Bitfields->linkdead = 0;
|
||||
Bitfields->showhelm = emu->showhelm;
|
||||
Bitfields->trader = emu->trader ? 1 : 0;
|
||||
Bitfields->targetable = emu->NPC ? emu->untargetable : 1;
|
||||
Bitfields->targetable = 1;
|
||||
Bitfields->targetable_with_hotkey = emu->targetable_with_hotkey ? 1 : 0;
|
||||
Bitfields->showname = ShowName;
|
||||
|
||||
@@ -4839,13 +4842,13 @@ namespace RoF2
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->petOwnerId);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // FindBits MQ2 name
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // FindBits MQ2 name
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->PlayerState);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->npc_tint_id); // NpcTintIndex
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // PrimaryTintIndex
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // SecondaryTintIndex
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // These do something with OP_WeaponEquip1
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // ^
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // NpcTintIndex
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // PrimaryTintIndex
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // SecondaryTintIndex
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // These do something with OP_WeaponEquip1
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // ^
|
||||
|
||||
if ((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) ||
|
||||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin)
|
||||
|
||||
@@ -101,8 +101,6 @@ namespace RoF2
|
||||
const int16 MAIL_SIZE = 0;//unknown
|
||||
const int16 GUILD_TROPHY_TRIBUTE_SIZE = 0;//unknown
|
||||
const int16 KRONO_SIZE = 0;//unknown
|
||||
const int16 GUILD_BANK_MAIN_SIZE = 200;
|
||||
const int16 GUILD_BANK_DEPOSIT_SIZE = 40;
|
||||
const int16 OTHER_SIZE = 0;//unknown
|
||||
|
||||
const int16 TRADE_NPC_SIZE = 4; // defined by implication
|
||||
|
||||
@@ -1965,39 +1965,41 @@ struct GuildBankWithdrawItem_Struct
|
||||
|
||||
struct GuildBankItemUpdate_Struct
|
||||
{
|
||||
void Init(uint32 inAction, uint32 inUnknown004, uint16 inSlotID, uint16 inArea, uint16 inUnknown016, uint32 inItemID, uint32 inIcon, uint32 inQuantity,
|
||||
void Init(uint32 inAction, uint32 inUnknown004, uint16 inSlotID, uint16 inArea, uint16 inUnknown012, uint32 inItemID, uint32 inIcon, uint32 inQuantity,
|
||||
uint32 inPermissions, uint32 inAllowMerge, bool inUseable)
|
||||
{
|
||||
action = inAction;
|
||||
slot_id = inSlotID;
|
||||
area = inArea;
|
||||
display = inUnknown016;
|
||||
item_id = inItemID;
|
||||
icon_id = inIcon;
|
||||
quantity = inQuantity;
|
||||
permissions = inPermissions;
|
||||
allow_merge = inAllowMerge;
|
||||
is_useable = inUseable;
|
||||
item_name[0] = '\0';
|
||||
donator[0] = '\0';
|
||||
who_for[0] = '\0';
|
||||
Action = inAction;
|
||||
Unknown004 = inUnknown004;
|
||||
SlotID = inSlotID;
|
||||
Area = inArea;
|
||||
Unknown012 = inUnknown012;
|
||||
ItemID = inItemID;
|
||||
Icon = inIcon;
|
||||
Quantity = inQuantity;
|
||||
Permissions = inPermissions;
|
||||
AllowMerge = inAllowMerge;
|
||||
Useable = inUseable;
|
||||
ItemName[0] = '\0';
|
||||
Donator[0] = '\0';
|
||||
WhoFor[0] = '\0';
|
||||
};
|
||||
|
||||
/*000*/ uint32 action;
|
||||
/*004*/ uint32 not_used004; //disassemble of client did not use this
|
||||
/*008*/ uint32 not_used008; //disassemble of client did not use this
|
||||
/*012*/ uint16 slot_id;
|
||||
/*014*/ uint16 area;
|
||||
/*016*/ uint32 display;
|
||||
/*020*/ uint32 item_id;
|
||||
/*024*/ uint32 icon_id;
|
||||
/*028*/ uint32 quantity;
|
||||
/*032*/ uint32 permissions;
|
||||
/*036*/ uint8 allow_merge;
|
||||
/*037*/ uint8 is_useable; // Used in conjunction with the Public-if-useable permission.
|
||||
/*038*/ char item_name[64];
|
||||
/*102*/ char donator[64];
|
||||
/*166*/ char who_for[64];
|
||||
/*000*/ uint32 Action;
|
||||
/*004*/ uint32 Unknown004;
|
||||
/*008*/ uint32 Unknown08;
|
||||
/*012*/ uint16 SlotID;
|
||||
/*014*/ uint16 Area;
|
||||
/*016*/ uint32 Unknown012;
|
||||
/*020*/ uint32 ItemID;
|
||||
/*024*/ uint32 Icon;
|
||||
/*028*/ uint32 Quantity;
|
||||
/*032*/ uint32 Permissions;
|
||||
/*036*/ uint8 AllowMerge;
|
||||
/*037*/ uint8 Useable; // Used in conjunction with the Public-if-useable permission.
|
||||
/*038*/ char ItemName[64];
|
||||
/*102*/ char Donator[64];
|
||||
/*166*/ char WhoFor[64];
|
||||
/*230*/ uint16 Unknown226;
|
||||
};
|
||||
|
||||
struct GuildBankClear_Struct
|
||||
|
||||
@@ -1946,38 +1946,38 @@ struct GuildBankItemUpdate_Struct
|
||||
void Init(uint32 inAction, uint32 inUnknown004, uint16 inSlotID, uint16 inArea, uint16 inUnknown012, uint32 inItemID, uint32 inIcon, uint32 inQuantity,
|
||||
uint32 inPermissions, uint32 inAllowMerge, bool inUseable)
|
||||
{
|
||||
action = inAction;
|
||||
unknown004 = inUnknown004;
|
||||
slot_id = inSlotID;
|
||||
area = inArea;
|
||||
display = inUnknown012;
|
||||
item_id = inItemID;
|
||||
icon_id = inIcon;
|
||||
quantity = inQuantity;
|
||||
permissions = inPermissions;
|
||||
allow_merge = inAllowMerge;
|
||||
is_useable = inUseable;
|
||||
item_name[0] = '\0';
|
||||
donator[0] = '\0';
|
||||
who_for[0] = '\0';
|
||||
Action = inAction;
|
||||
Unknown004 = inUnknown004;
|
||||
SlotID = inSlotID;
|
||||
Area = inArea;
|
||||
Unknown012 = inUnknown012;
|
||||
ItemID = inItemID;
|
||||
Icon = inIcon;
|
||||
Quantity = inQuantity;
|
||||
Permissions = inPermissions;
|
||||
AllowMerge = inAllowMerge;
|
||||
Useable = inUseable;
|
||||
ItemName[0] = '\0';
|
||||
Donator[0] = '\0';
|
||||
WhoFor[0] = '\0';
|
||||
};
|
||||
|
||||
/*000*/ uint32 action;
|
||||
/*004*/ uint32 unknown004;
|
||||
/*008*/ uint32 unknown008;
|
||||
/*012*/ uint16 slot_id;
|
||||
/*014*/ uint16 area;
|
||||
/*016*/ uint32 display;
|
||||
/*020*/ uint32 item_id;
|
||||
/*024*/ uint32 icon_id;
|
||||
/*028*/ uint32 quantity;
|
||||
/*032*/ uint32 permissions;
|
||||
/*036*/ uint8 allow_merge;
|
||||
/*037*/ uint8 is_useable; // Used in conjunction with the Public-if-useable permission.
|
||||
/*038*/ char item_name[64];
|
||||
/*102*/ char donator[64];
|
||||
/*166*/ char who_for[64];
|
||||
/*230*/ uint16 unknown226;
|
||||
/*000*/ uint32 Action;
|
||||
/*004*/ uint32 Unknown004;
|
||||
/*008*/ uint32 Unknown08;
|
||||
/*012*/ uint16 SlotID;
|
||||
/*014*/ uint16 Area;
|
||||
/*016*/ uint32 Unknown012;
|
||||
/*020*/ uint32 ItemID;
|
||||
/*024*/ uint32 Icon;
|
||||
/*028*/ uint32 Quantity;
|
||||
/*032*/ uint32 Permissions;
|
||||
/*036*/ uint8 AllowMerge;
|
||||
/*037*/ uint8 Useable; // Used in conjunction with the Public-if-useable permission.
|
||||
/*038*/ char ItemName[64];
|
||||
/*102*/ char Donator[64];
|
||||
/*166*/ char WhoFor[64];
|
||||
/*230*/ uint16 Unknown226;
|
||||
};
|
||||
|
||||
struct GuildBankClear_Struct
|
||||
|
||||
+13
-13
@@ -72,7 +72,7 @@ namespace SoD
|
||||
{
|
||||
//create our opcode manager if we havent already
|
||||
if (opcodes == nullptr) {
|
||||
std::string opfile = fmt::format("{}/patch_{}.conf", PathManager::Instance()->GetPatchPath(), name);
|
||||
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
|
||||
//load up the opcode manager.
|
||||
//TODO: figure out how to support shared memory with multiple patches...
|
||||
opcodes = new RegularOpcodeManager();
|
||||
@@ -113,7 +113,7 @@ namespace SoD
|
||||
//we need to go to every stream and replace it's manager.
|
||||
|
||||
if (opcodes != nullptr) {
|
||||
std::string opfile = fmt::format("{}/patch_{}.conf", PathManager::Instance()->GetPatchPath(), name);
|
||||
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
|
||||
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
|
||||
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
|
||||
return;
|
||||
@@ -3966,12 +3966,12 @@ namespace SoD
|
||||
SoDSlot = serverSlot - 2;
|
||||
}
|
||||
|
||||
else if (serverSlot <= EQ::invbag::GENERAL_BAGS_END && serverSlot >= EQ::invbag::GENERAL_BAGS_BEGIN) {
|
||||
SoDSlot = serverSlot - (EQ::invbag::GENERAL_BAGS_BEGIN - invbag::GENERAL_BAGS_BEGIN) - ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((serverSlot - EQ::invbag::GENERAL_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT));;
|
||||
else if (serverSlot <= EQ::invbag::GENERAL_BAGS_8_END && serverSlot >= EQ::invbag::GENERAL_BAGS_BEGIN) {
|
||||
SoDSlot = serverSlot + 11;
|
||||
}
|
||||
|
||||
else if (serverSlot <= EQ::invbag::CURSOR_BAG_END && serverSlot >= EQ::invbag::CURSOR_BAG_BEGIN) {
|
||||
SoDSlot = serverSlot - (EQ::invbag::CURSOR_BAG_BEGIN - invbag::CURSOR_BAG_BEGIN);
|
||||
SoDSlot = serverSlot - 9;
|
||||
}
|
||||
|
||||
else if (serverSlot <= EQ::invslot::TRIBUTE_END && serverSlot >= EQ::invslot::TRIBUTE_BEGIN) {
|
||||
@@ -3991,7 +3991,7 @@ namespace SoD
|
||||
}
|
||||
|
||||
else if (serverSlot <= EQ::invbag::BANK_BAGS_END && serverSlot >= EQ::invbag::BANK_BAGS_BEGIN) {
|
||||
SoDSlot = serverSlot - (EQ::invbag::BANK_BAGS_BEGIN - invbag::BANK_BAGS_BEGIN) - ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((serverSlot - EQ::invbag::BANK_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT));;
|
||||
SoDSlot = serverSlot + 1;
|
||||
}
|
||||
|
||||
else if (serverSlot <= EQ::invslot::SHARED_BANK_END && serverSlot >= EQ::invslot::SHARED_BANK_BEGIN) {
|
||||
@@ -3999,7 +3999,7 @@ namespace SoD
|
||||
}
|
||||
|
||||
else if (serverSlot <= EQ::invbag::SHARED_BANK_BAGS_END && serverSlot >= EQ::invbag::SHARED_BANK_BAGS_BEGIN) {
|
||||
SoDSlot = serverSlot - (EQ::invbag::SHARED_BANK_BAGS_BEGIN - invbag::SHARED_BANK_BAGS_BEGIN) - ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((serverSlot - EQ::invbag::SHARED_BANK_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT));
|
||||
SoDSlot = serverSlot + 1;
|
||||
}
|
||||
|
||||
else if (serverSlot <= EQ::invslot::TRADE_END && serverSlot >= EQ::invslot::TRADE_BEGIN) {
|
||||
@@ -4007,7 +4007,7 @@ namespace SoD
|
||||
}
|
||||
|
||||
else if (serverSlot <= EQ::invbag::TRADE_BAGS_END && serverSlot >= EQ::invbag::TRADE_BAGS_BEGIN) {
|
||||
SoDSlot = serverSlot - (EQ::invbag::TRADE_BAGS_BEGIN - invbag::TRADE_BAGS_BEGIN) - ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((serverSlot - EQ::invbag::TRADE_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT));
|
||||
SoDSlot = serverSlot;
|
||||
}
|
||||
|
||||
else if (serverSlot <= EQ::invslot::WORLD_END && serverSlot >= EQ::invslot::WORLD_BEGIN) {
|
||||
@@ -4049,11 +4049,11 @@ namespace SoD
|
||||
}
|
||||
|
||||
else if (sod_slot <= invbag::GENERAL_BAGS_END && sod_slot >= invbag::GENERAL_BAGS_BEGIN) {
|
||||
server_slot = sod_slot + (EQ::invbag::GENERAL_BAGS_BEGIN - invbag::GENERAL_BAGS_BEGIN) + ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((sod_slot - invbag::GENERAL_BAGS_BEGIN) / invbag::SLOT_COUNT));
|
||||
server_slot = sod_slot - 11;
|
||||
}
|
||||
|
||||
else if (sod_slot <= invbag::CURSOR_BAG_END && sod_slot >= invbag::CURSOR_BAG_BEGIN) {
|
||||
server_slot = sod_slot + (EQ::invbag::CURSOR_BAG_BEGIN - invbag::CURSOR_BAG_BEGIN);
|
||||
server_slot = sod_slot + 9;
|
||||
}
|
||||
|
||||
else if (sod_slot <= invslot::TRIBUTE_END && sod_slot >= invslot::TRIBUTE_BEGIN) {
|
||||
@@ -4073,7 +4073,7 @@ namespace SoD
|
||||
}
|
||||
|
||||
else if (sod_slot <= invbag::BANK_BAGS_END && sod_slot >= invbag::BANK_BAGS_BEGIN) {
|
||||
server_slot = sod_slot + (EQ::invbag::BANK_BAGS_BEGIN - invbag::BANK_BAGS_BEGIN) + ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((sod_slot - invbag::BANK_BAGS_BEGIN) / invbag::SLOT_COUNT));
|
||||
server_slot = sod_slot - 1;
|
||||
}
|
||||
|
||||
else if (sod_slot <= invslot::SHARED_BANK_END && sod_slot >= invslot::SHARED_BANK_BEGIN) {
|
||||
@@ -4081,7 +4081,7 @@ namespace SoD
|
||||
}
|
||||
|
||||
else if (sod_slot <= invbag::SHARED_BANK_BAGS_END && sod_slot >= invbag::SHARED_BANK_BAGS_BEGIN) {
|
||||
server_slot = sod_slot + (EQ::invbag::SHARED_BANK_BAGS_BEGIN - invbag::SHARED_BANK_BAGS_BEGIN) + ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((sod_slot - invbag::SHARED_BANK_BAGS_BEGIN) / invbag::SLOT_COUNT));
|
||||
server_slot = sod_slot - 1;
|
||||
}
|
||||
|
||||
else if (sod_slot <= invslot::TRADE_END && sod_slot >= invslot::TRADE_BEGIN) {
|
||||
@@ -4089,7 +4089,7 @@ namespace SoD
|
||||
}
|
||||
|
||||
else if (sod_slot <= invbag::TRADE_BAGS_END && sod_slot >= invbag::TRADE_BAGS_BEGIN) {
|
||||
server_slot = sod_slot + (EQ::invbag::TRADE_BAGS_BEGIN - invbag::TRADE_BAGS_BEGIN) + ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((sod_slot - invbag::TRADE_BAGS_BEGIN) / invbag::SLOT_COUNT));
|
||||
server_slot = sod_slot;
|
||||
}
|
||||
|
||||
else if (sod_slot <= invslot::WORLD_END && sod_slot >= invslot::WORLD_BEGIN) {
|
||||
|
||||
+13
-13
@@ -71,7 +71,7 @@ namespace SoF
|
||||
{
|
||||
//create our opcode manager if we havent already
|
||||
if (opcodes == nullptr) {
|
||||
std::string opfile = fmt::format("{}/patch_{}.conf", PathManager::Instance()->GetPatchPath(), name);
|
||||
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
|
||||
//load up the opcode manager.
|
||||
//TODO: figure out how to support shared memory with multiple patches...
|
||||
opcodes = new RegularOpcodeManager();
|
||||
@@ -110,7 +110,7 @@ namespace SoF
|
||||
//we need to go to every stream and replace it's manager.
|
||||
|
||||
if (opcodes != nullptr) {
|
||||
std::string opfile = fmt::format("{}/patch_{}.conf", PathManager::Instance()->GetPatchPath(), name);
|
||||
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
|
||||
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
|
||||
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
|
||||
return;
|
||||
@@ -3355,12 +3355,12 @@ namespace SoF
|
||||
sof_slot = server_slot - 2;
|
||||
}
|
||||
|
||||
else if (server_slot <= EQ::invbag::GENERAL_BAGS_END && server_slot >= EQ::invbag::GENERAL_BAGS_BEGIN) {
|
||||
sof_slot = server_slot - (EQ::invbag::GENERAL_BAGS_BEGIN - invbag::GENERAL_BAGS_BEGIN) - ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((server_slot - EQ::invbag::GENERAL_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT));;
|
||||
else if (server_slot <= EQ::invbag::GENERAL_BAGS_8_END && server_slot >= EQ::invbag::GENERAL_BAGS_BEGIN) {
|
||||
sof_slot = server_slot + 11;
|
||||
}
|
||||
|
||||
else if (server_slot <= EQ::invbag::CURSOR_BAG_END && server_slot >= EQ::invbag::CURSOR_BAG_BEGIN) {
|
||||
sof_slot = server_slot - (EQ::invbag::CURSOR_BAG_BEGIN - invbag::CURSOR_BAG_BEGIN);
|
||||
sof_slot = server_slot - 9;
|
||||
}
|
||||
|
||||
else if (server_slot <= EQ::invslot::TRIBUTE_END && server_slot >= EQ::invslot::TRIBUTE_BEGIN) {
|
||||
@@ -3380,7 +3380,7 @@ namespace SoF
|
||||
}
|
||||
|
||||
else if (server_slot <= EQ::invbag::BANK_BAGS_END && server_slot >= EQ::invbag::BANK_BAGS_BEGIN) {
|
||||
sof_slot = server_slot - (EQ::invbag::BANK_BAGS_BEGIN - invbag::BANK_BAGS_BEGIN) - ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((server_slot - EQ::invbag::BANK_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT));
|
||||
sof_slot = server_slot + 1;
|
||||
}
|
||||
|
||||
else if (server_slot <= EQ::invslot::SHARED_BANK_END && server_slot >= EQ::invslot::SHARED_BANK_BEGIN) {
|
||||
@@ -3388,7 +3388,7 @@ namespace SoF
|
||||
}
|
||||
|
||||
else if (server_slot <= EQ::invbag::SHARED_BANK_BAGS_END && server_slot >= EQ::invbag::SHARED_BANK_BAGS_BEGIN) {
|
||||
sof_slot = server_slot - (EQ::invbag::SHARED_BANK_BAGS_BEGIN - invbag::SHARED_BANK_BAGS_BEGIN) - ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((server_slot - EQ::invbag::SHARED_BANK_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT));
|
||||
sof_slot = server_slot + 1;
|
||||
}
|
||||
|
||||
else if (server_slot <= EQ::invslot::TRADE_END && server_slot >= EQ::invslot::TRADE_BEGIN) {
|
||||
@@ -3396,7 +3396,7 @@ namespace SoF
|
||||
}
|
||||
|
||||
else if (server_slot <= EQ::invbag::TRADE_BAGS_END && server_slot >= EQ::invbag::TRADE_BAGS_BEGIN) {
|
||||
sof_slot = server_slot - (EQ::invbag::TRADE_BAGS_BEGIN - invbag::TRADE_BAGS_BEGIN) - ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((server_slot - EQ::invbag::TRADE_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT));
|
||||
sof_slot = server_slot;
|
||||
}
|
||||
|
||||
else if (server_slot <= EQ::invslot::WORLD_END && server_slot >= EQ::invslot::WORLD_BEGIN) {
|
||||
@@ -3442,11 +3442,11 @@ namespace SoF
|
||||
}
|
||||
|
||||
else if (sof_slot <= invbag::GENERAL_BAGS_END && sof_slot >= invbag::GENERAL_BAGS_BEGIN) {
|
||||
server_slot = sof_slot + (EQ::invbag::GENERAL_BAGS_BEGIN - invbag::GENERAL_BAGS_BEGIN) + ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((sof_slot - invbag::GENERAL_BAGS_BEGIN) / invbag::SLOT_COUNT));;
|
||||
server_slot = sof_slot - 11;
|
||||
}
|
||||
|
||||
else if (sof_slot <= invbag::CURSOR_BAG_END && sof_slot >= invbag::CURSOR_BAG_BEGIN) {
|
||||
server_slot = sof_slot + (EQ::invbag::CURSOR_BAG_BEGIN - invbag::CURSOR_BAG_BEGIN);
|
||||
server_slot = sof_slot + 9;
|
||||
}
|
||||
|
||||
else if (sof_slot <= invslot::TRIBUTE_END && sof_slot >= invslot::TRIBUTE_BEGIN) {
|
||||
@@ -3466,7 +3466,7 @@ namespace SoF
|
||||
}
|
||||
|
||||
else if (sof_slot <= invbag::BANK_BAGS_END && sof_slot >= invbag::BANK_BAGS_BEGIN) {
|
||||
server_slot = sof_slot + (EQ::invbag::BANK_BAGS_BEGIN - invbag::BANK_BAGS_BEGIN) + ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((sof_slot - invbag::BANK_BAGS_BEGIN) / invbag::SLOT_COUNT));;
|
||||
server_slot = sof_slot - 1;
|
||||
}
|
||||
|
||||
else if (sof_slot <= invslot::SHARED_BANK_END && sof_slot >= invslot::SHARED_BANK_BEGIN) {
|
||||
@@ -3474,7 +3474,7 @@ namespace SoF
|
||||
}
|
||||
|
||||
else if (sof_slot <= invbag::SHARED_BANK_BAGS_END && sof_slot >= invbag::SHARED_BANK_BAGS_BEGIN) {
|
||||
server_slot = sof_slot + (EQ::invbag::SHARED_BANK_BAGS_BEGIN - invbag::SHARED_BANK_BAGS_BEGIN) + ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((sof_slot - invbag::SHARED_BANK_BAGS_BEGIN) / invbag::SLOT_COUNT));;
|
||||
server_slot = sof_slot - 1;
|
||||
}
|
||||
|
||||
else if (sof_slot <= invslot::TRADE_END && sof_slot >= invslot::TRADE_BEGIN) {
|
||||
@@ -3482,7 +3482,7 @@ namespace SoF
|
||||
}
|
||||
|
||||
else if (sof_slot <= invbag::TRADE_BAGS_END && sof_slot >= invbag::TRADE_BAGS_BEGIN) {
|
||||
server_slot = sof_slot + (EQ::invbag::TRADE_BAGS_BEGIN - invbag::TRADE_BAGS_BEGIN) + ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((sof_slot - invbag::TRADE_BAGS_BEGIN) / invbag::SLOT_COUNT));;
|
||||
server_slot = sof_slot;
|
||||
}
|
||||
|
||||
else if (sof_slot <= invslot::WORLD_END && sof_slot >= invslot::WORLD_BEGIN) {
|
||||
|
||||
+14
-14
@@ -73,7 +73,7 @@ namespace Titanium
|
||||
auto Config = EQEmuConfig::get();
|
||||
//create our opcode manager if we havent already
|
||||
if (opcodes == nullptr) {
|
||||
std::string opfile = fmt::format("{}/patch_{}.conf", PathManager::Instance()->GetPatchPath(), name);
|
||||
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
|
||||
//load up the opcode manager.
|
||||
//TODO: figure out how to support shared memory with multiple patches...
|
||||
opcodes = new RegularOpcodeManager();
|
||||
@@ -114,7 +114,7 @@ namespace Titanium
|
||||
//we need to go to every stream and replace it's manager.
|
||||
|
||||
if (opcodes != nullptr) {
|
||||
std::string opfile = fmt::format("{}/patch_{}.conf", PathManager::Instance()->GetPatchPath(), name);
|
||||
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
|
||||
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
|
||||
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
|
||||
return;
|
||||
@@ -3596,12 +3596,12 @@ namespace Titanium
|
||||
else if (server_slot == (EQ::invslot::POSSESSIONS_COUNT + EQ::invslot::slotAmmo)) {
|
||||
titanium_slot = server_slot - 4;
|
||||
}
|
||||
else if (server_slot <= EQ::invbag::GENERAL_BAGS_END &&
|
||||
else if (server_slot <= EQ::invbag::GENERAL_BAGS_8_END &&
|
||||
server_slot >= EQ::invbag::GENERAL_BAGS_BEGIN) {
|
||||
titanium_slot = server_slot - (EQ::invbag::GENERAL_BAGS_BEGIN - invbag::GENERAL_BAGS_BEGIN) - ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((server_slot - EQ::invbag::GENERAL_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT));
|
||||
titanium_slot = server_slot;
|
||||
}
|
||||
else if (server_slot <= EQ::invbag::CURSOR_BAG_END && server_slot >= EQ::invbag::CURSOR_BAG_BEGIN) {
|
||||
titanium_slot = server_slot - (EQ::invbag::CURSOR_BAG_BEGIN - invbag::CURSOR_BAG_BEGIN);
|
||||
titanium_slot = server_slot - 20;
|
||||
}
|
||||
else if (server_slot <= EQ::invslot::TRIBUTE_END && server_slot >= EQ::invslot::TRIBUTE_BEGIN) {
|
||||
titanium_slot = server_slot;
|
||||
@@ -3616,21 +3616,21 @@ namespace Titanium
|
||||
else if (server_slot <= EQ::invslot::BANK_END && server_slot >= EQ::invslot::BANK_BEGIN) {
|
||||
titanium_slot = server_slot;
|
||||
}
|
||||
else if (server_slot <= EQ::invbag::BANK_BAGS_END && server_slot >= EQ::invbag::BANK_BAGS_BEGIN) {
|
||||
titanium_slot = server_slot - (EQ::invbag::BANK_BAGS_BEGIN - invbag::BANK_BAGS_BEGIN) - ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((server_slot - EQ::invbag::BANK_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT));
|
||||
else if (server_slot <= EQ::invbag::BANK_BAGS_16_END && server_slot >= EQ::invbag::BANK_BAGS_BEGIN) {
|
||||
titanium_slot = server_slot;
|
||||
}
|
||||
else if (server_slot <= EQ::invslot::SHARED_BANK_END && server_slot >= EQ::invslot::SHARED_BANK_BEGIN) {
|
||||
titanium_slot = server_slot;
|
||||
}
|
||||
else if (server_slot <= EQ::invbag::SHARED_BANK_BAGS_END &&
|
||||
server_slot >= EQ::invbag::SHARED_BANK_BAGS_BEGIN) {
|
||||
titanium_slot = server_slot - (EQ::invbag::SHARED_BANK_BAGS_BEGIN - invbag::SHARED_BANK_BAGS_BEGIN) - ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((server_slot - EQ::invbag::SHARED_BANK_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT));
|
||||
titanium_slot = server_slot;
|
||||
}
|
||||
else if (server_slot <= EQ::invslot::TRADE_END && server_slot >= EQ::invslot::TRADE_BEGIN) {
|
||||
titanium_slot = server_slot;
|
||||
}
|
||||
else if (server_slot <= EQ::invbag::TRADE_BAGS_END && server_slot >= EQ::invbag::TRADE_BAGS_BEGIN) {
|
||||
titanium_slot = server_slot - (EQ::invbag::TRADE_BAGS_BEGIN - invbag::TRADE_BAGS_BEGIN) - ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((server_slot - EQ::invbag::TRADE_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT));
|
||||
titanium_slot = server_slot;
|
||||
}
|
||||
else if (server_slot <= EQ::invslot::WORLD_END && server_slot >= EQ::invslot::WORLD_BEGIN) {
|
||||
titanium_slot = server_slot;
|
||||
@@ -3687,10 +3687,10 @@ namespace Titanium
|
||||
server_slot = titanium_slot + 4;
|
||||
}
|
||||
else if (titanium_slot <= invbag::GENERAL_BAGS_END && titanium_slot >= invbag::GENERAL_BAGS_BEGIN) {
|
||||
server_slot = titanium_slot + (EQ::invbag::GENERAL_BAGS_BEGIN - invbag::GENERAL_BAGS_BEGIN) + ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((titanium_slot - invbag::GENERAL_BAGS_BEGIN) / invbag::SLOT_COUNT));
|
||||
server_slot = titanium_slot;
|
||||
}
|
||||
else if (titanium_slot <= invbag::CURSOR_BAG_END && titanium_slot >= invbag::CURSOR_BAG_BEGIN) {
|
||||
server_slot = titanium_slot + (EQ::invbag::CURSOR_BAG_BEGIN - invbag::CURSOR_BAG_BEGIN);
|
||||
server_slot = titanium_slot + 20;
|
||||
}
|
||||
else if (titanium_slot <= invslot::TRIBUTE_END && titanium_slot >= invslot::TRIBUTE_BEGIN) {
|
||||
server_slot = titanium_slot;
|
||||
@@ -3705,19 +3705,19 @@ namespace Titanium
|
||||
server_slot = titanium_slot;
|
||||
}
|
||||
else if (titanium_slot <= invbag::BANK_BAGS_END && titanium_slot >= invbag::BANK_BAGS_BEGIN) {
|
||||
server_slot = titanium_slot + (EQ::invbag::BANK_BAGS_BEGIN - invbag::BANK_BAGS_BEGIN) + ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((titanium_slot - invbag::BANK_BAGS_BEGIN) / invbag::SLOT_COUNT));
|
||||
server_slot = titanium_slot;
|
||||
}
|
||||
else if (titanium_slot <= invslot::SHARED_BANK_END && titanium_slot >= invslot::SHARED_BANK_BEGIN) {
|
||||
server_slot = titanium_slot;
|
||||
}
|
||||
else if (titanium_slot <= invbag::SHARED_BANK_BAGS_END && titanium_slot >= invbag::SHARED_BANK_BAGS_BEGIN) {
|
||||
server_slot = titanium_slot + (EQ::invbag::SHARED_BANK_BAGS_BEGIN - invbag::SHARED_BANK_BAGS_BEGIN) + ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((titanium_slot - invbag::SHARED_BANK_BAGS_BEGIN) / invbag::SLOT_COUNT));
|
||||
server_slot = titanium_slot;
|
||||
}
|
||||
else if (titanium_slot <= invslot::TRADE_END && titanium_slot >= invslot::TRADE_BEGIN) {
|
||||
server_slot = titanium_slot;
|
||||
}
|
||||
else if (titanium_slot <= invbag::TRADE_BAGS_END && titanium_slot >= invbag::TRADE_BAGS_BEGIN) {
|
||||
server_slot = titanium_slot + (EQ::invbag::TRADE_BAGS_BEGIN - invbag::TRADE_BAGS_BEGIN) + ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((titanium_slot - invbag::TRADE_BAGS_BEGIN) / invbag::SLOT_COUNT));
|
||||
server_slot = titanium_slot;
|
||||
}
|
||||
else if (titanium_slot <= invslot::WORLD_END && titanium_slot >= invslot::WORLD_BEGIN) {
|
||||
server_slot = titanium_slot;
|
||||
|
||||
+13
-13
@@ -76,7 +76,7 @@ namespace UF
|
||||
{
|
||||
//create our opcode manager if we havent already
|
||||
if (opcodes == nullptr) {
|
||||
std::string opfile = fmt::format("{}/patch_{}.conf", PathManager::Instance()->GetPatchPath(), name);
|
||||
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
|
||||
//load up the opcode manager.
|
||||
//TODO: figure out how to support shared memory with multiple patches...
|
||||
opcodes = new RegularOpcodeManager();
|
||||
@@ -117,7 +117,7 @@ namespace UF
|
||||
//we need to go to every stream and replace it's manager.
|
||||
|
||||
if (opcodes != nullptr) {
|
||||
std::string opfile = fmt::format("{}/patch_{}.conf", PathManager::Instance()->GetPatchPath(), name);
|
||||
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
|
||||
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
|
||||
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
|
||||
return;
|
||||
@@ -4908,12 +4908,12 @@ namespace UF
|
||||
UFSlot = serverSlot - 2;
|
||||
}
|
||||
|
||||
else if (serverSlot <= EQ::invbag::GENERAL_BAGS_END && serverSlot >= EQ::invbag::GENERAL_BAGS_BEGIN) {
|
||||
UFSlot = serverSlot - (EQ::invbag::GENERAL_BAGS_BEGIN - invbag::GENERAL_BAGS_BEGIN)/*3748*/ - ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((serverSlot - EQ::invbag::GENERAL_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT)); // + 11;
|
||||
else if (serverSlot <= EQ::invbag::GENERAL_BAGS_8_END && serverSlot >= EQ::invbag::GENERAL_BAGS_BEGIN) {
|
||||
UFSlot = serverSlot + 11;
|
||||
}
|
||||
|
||||
else if (serverSlot <= EQ::invbag::CURSOR_BAG_END && serverSlot >= EQ::invbag::CURSOR_BAG_BEGIN) {
|
||||
UFSlot = serverSlot - (EQ::invbag::CURSOR_BAG_BEGIN - invbag::CURSOR_BAG_BEGIN)/*5668*/; // - 9;
|
||||
UFSlot = serverSlot - 9;
|
||||
}
|
||||
|
||||
else if (serverSlot <= EQ::invslot::TRIBUTE_END && serverSlot >= EQ::invslot::TRIBUTE_BEGIN) {
|
||||
@@ -4933,7 +4933,7 @@ namespace UF
|
||||
}
|
||||
|
||||
else if (serverSlot <= EQ::invbag::BANK_BAGS_END && serverSlot >= EQ::invbag::BANK_BAGS_BEGIN) {
|
||||
UFSlot = serverSlot - (EQ::invbag::BANK_BAGS_BEGIN - invbag::BANK_BAGS_BEGIN) - ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((serverSlot - EQ::invbag::BANK_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT)); // + 1;
|
||||
UFSlot = serverSlot + 1;
|
||||
}
|
||||
|
||||
else if (serverSlot <= EQ::invslot::SHARED_BANK_END && serverSlot >= EQ::invslot::SHARED_BANK_BEGIN) {
|
||||
@@ -4941,7 +4941,7 @@ namespace UF
|
||||
}
|
||||
|
||||
else if (serverSlot <= EQ::invbag::SHARED_BANK_BAGS_END && serverSlot >= EQ::invbag::SHARED_BANK_BAGS_BEGIN) {
|
||||
UFSlot = serverSlot - (EQ::invbag::SHARED_BANK_BAGS_BEGIN - invbag::SHARED_BANK_BAGS_BEGIN) - ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((serverSlot - EQ::invbag::SHARED_BANK_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT)); // + 1;
|
||||
UFSlot = serverSlot + 1;
|
||||
}
|
||||
|
||||
else if (serverSlot <= EQ::invslot::TRADE_END && serverSlot >= EQ::invslot::TRADE_BEGIN) {
|
||||
@@ -4949,7 +4949,7 @@ namespace UF
|
||||
}
|
||||
|
||||
else if (serverSlot <= EQ::invbag::TRADE_BAGS_END && serverSlot >= EQ::invbag::TRADE_BAGS_BEGIN) {
|
||||
UFSlot = serverSlot - (EQ::invbag::TRADE_BAGS_BEGIN - invbag::TRADE_BAGS_BEGIN) - ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((serverSlot - EQ::invbag::TRADE_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT)); // + 0;
|
||||
UFSlot = serverSlot;
|
||||
}
|
||||
|
||||
else if (serverSlot <= EQ::invslot::WORLD_END && serverSlot >= EQ::invslot::WORLD_BEGIN) {
|
||||
@@ -4991,11 +4991,11 @@ namespace UF
|
||||
}
|
||||
|
||||
else if (ufSlot <= invbag::GENERAL_BAGS_END && ufSlot >= invbag::GENERAL_BAGS_BEGIN) {
|
||||
ServerSlot = ufSlot + (EQ::invbag::GENERAL_BAGS_BEGIN - invbag::GENERAL_BAGS_BEGIN)/*3748*/ + ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((ufSlot - invbag::GENERAL_BAGS_BEGIN) / invbag::SLOT_COUNT)); // - 11;
|
||||
ServerSlot = ufSlot - 11;
|
||||
}
|
||||
|
||||
else if (ufSlot <= invbag::CURSOR_BAG_END && ufSlot >= invbag::CURSOR_BAG_BEGIN) {
|
||||
ServerSlot = ufSlot + (EQ::invbag::CURSOR_BAG_BEGIN - invbag::CURSOR_BAG_BEGIN)/*5668*/; // + 9;
|
||||
ServerSlot = ufSlot + 9;
|
||||
}
|
||||
|
||||
else if (ufSlot <= invslot::TRIBUTE_END && ufSlot >= invslot::TRIBUTE_BEGIN) {
|
||||
@@ -5015,7 +5015,7 @@ namespace UF
|
||||
}
|
||||
|
||||
else if (ufSlot <= invbag::BANK_BAGS_END && ufSlot >= invbag::BANK_BAGS_BEGIN) {
|
||||
ServerSlot = ufSlot + (EQ::invbag::BANK_BAGS_BEGIN - invbag::BANK_BAGS_BEGIN) + ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((ufSlot - invbag::BANK_BAGS_BEGIN) / invbag::SLOT_COUNT)); // - 1;
|
||||
ServerSlot = ufSlot - 1;
|
||||
}
|
||||
|
||||
else if (ufSlot <= invslot::SHARED_BANK_END && ufSlot >= invslot::SHARED_BANK_BEGIN) {
|
||||
@@ -5023,7 +5023,7 @@ namespace UF
|
||||
}
|
||||
|
||||
else if (ufSlot <= invbag::SHARED_BANK_BAGS_END && ufSlot >= invbag::SHARED_BANK_BAGS_BEGIN) {
|
||||
ServerSlot = ufSlot + (EQ::invbag::SHARED_BANK_BAGS_BEGIN - invbag::SHARED_BANK_BAGS_BEGIN) + ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((ufSlot - invbag::SHARED_BANK_BAGS_BEGIN) / invbag::SLOT_COUNT)); // - 1;
|
||||
ServerSlot = ufSlot - 1;
|
||||
}
|
||||
|
||||
else if (ufSlot <= invslot::TRADE_END && ufSlot >= invslot::TRADE_BEGIN) {
|
||||
@@ -5031,7 +5031,7 @@ namespace UF
|
||||
}
|
||||
|
||||
else if (ufSlot <= invbag::TRADE_BAGS_END && ufSlot >= invbag::TRADE_BAGS_BEGIN) {
|
||||
ServerSlot = ufSlot + (EQ::invbag::TRADE_BAGS_BEGIN - invbag::TRADE_BAGS_BEGIN) + ((EQ::invbag::SLOT_COUNT - invbag::SLOT_COUNT) * ((ufSlot - invbag::TRADE_BAGS_BEGIN) / invbag::SLOT_COUNT)); // - 0;
|
||||
ServerSlot = ufSlot;
|
||||
}
|
||||
|
||||
else if (ufSlot <= invslot::WORLD_END && ufSlot >= invslot::WORLD_BEGIN) {
|
||||
|
||||
+24
-45
@@ -8,7 +8,7 @@
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
void PathManager::Init()
|
||||
void PathManager::LoadPaths()
|
||||
{
|
||||
m_server_path = File::FindEqemuConfigPath();
|
||||
|
||||
@@ -48,23 +48,10 @@ void PathManager::Init()
|
||||
return dir;
|
||||
};
|
||||
|
||||
auto load_many_paths_fallback = [&](const std::vector<std::string>& dirs, const std::string& fallback, std::vector<std::string>& target) {
|
||||
target.clear();
|
||||
if (!dirs.empty()) {
|
||||
for (const auto& path : dirs) {
|
||||
target.push_back(resolve_path(path));
|
||||
}
|
||||
} else {
|
||||
target.push_back(resolve_path(fallback));
|
||||
}
|
||||
};
|
||||
|
||||
load_many_paths_fallback(c->GetQuestDirectories(), c->QuestDir, m_quests_paths);
|
||||
load_many_paths_fallback(c->GetPluginsDirectories(), c->PluginDir, m_plugin_paths);
|
||||
load_many_paths_fallback(c->GetLuaModuleDirectories(), c->LuaModuleDir, m_lua_module_paths);
|
||||
|
||||
// resolve all paths
|
||||
m_maps_path = resolve_path(c->MapDir, {"maps", "Maps"});
|
||||
m_quests_path = resolve_path(c->QuestDir);
|
||||
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);
|
||||
@@ -75,10 +62,13 @@ void PathManager::Init()
|
||||
std::vector<std::pair<std::string, std::string>> paths = {
|
||||
{"server", m_server_path},
|
||||
{"logs", m_log_path},
|
||||
{"maps", m_maps_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}
|
||||
};
|
||||
|
||||
@@ -86,24 +76,13 @@ void PathManager::Init()
|
||||
constexpr int path_width = 0;
|
||||
constexpr int break_length = 70;
|
||||
|
||||
LogInfo("Loading server paths");
|
||||
std::cout << std::endl;
|
||||
LogInfo("{}", Strings::Repeat("-", break_length));
|
||||
for (const auto& [name, in_path] : paths) {
|
||||
if (!in_path.empty()) {
|
||||
LogInfo("{:>{}} > [{:<{}}]", name, name_width, in_path, path_width);
|
||||
}
|
||||
}
|
||||
|
||||
auto log_paths = [&](const std::string& label, const std::vector<std::string>& paths) {
|
||||
if (!paths.empty()) {
|
||||
LogInfo("{:>{}} > [{:<{}}]", label, name_width - 1, Strings::Join(paths, ";"), path_width);
|
||||
}
|
||||
};
|
||||
|
||||
log_paths("quests", m_quests_paths);
|
||||
log_paths("plugins", m_plugin_paths);
|
||||
log_paths("lua_modules", m_lua_module_paths);
|
||||
|
||||
LogInfo("{}", Strings::Repeat("-", break_length));
|
||||
}
|
||||
|
||||
@@ -117,26 +96,21 @@ const std::string &PathManager::GetMapsPath() const
|
||||
return m_maps_path;
|
||||
}
|
||||
|
||||
const std::string &PathManager::GetQuestsPath() const
|
||||
{
|
||||
return m_quests_path;
|
||||
}
|
||||
|
||||
const std::string &PathManager::GetPluginsPath() const
|
||||
{
|
||||
return m_plugins_path;
|
||||
}
|
||||
|
||||
const std::string &PathManager::GetSharedMemoryPath() const
|
||||
{
|
||||
return m_shared_memory_path;
|
||||
}
|
||||
|
||||
std::vector<std::string> PathManager::GetQuestPaths() const
|
||||
{
|
||||
return m_quests_paths;
|
||||
}
|
||||
|
||||
std::vector<std::string> PathManager::GetPluginPaths() const
|
||||
{
|
||||
return m_plugin_paths;
|
||||
}
|
||||
|
||||
std::vector<std::string> PathManager::GetLuaModulePaths() const
|
||||
{
|
||||
return m_lua_module_paths;
|
||||
}
|
||||
|
||||
const std::string &PathManager::GetLogPath() const
|
||||
{
|
||||
return m_log_path;
|
||||
@@ -152,6 +126,11 @@ const std::string &PathManager::GetOpcodePath() const
|
||||
return m_opcode_path;
|
||||
}
|
||||
|
||||
const std::string &PathManager::GetLuaModulesPath() const
|
||||
{
|
||||
return m_lua_modules_path;
|
||||
}
|
||||
|
||||
const std::string &PathManager::GetLuaModsPath() const
|
||||
{
|
||||
return m_lua_mods_path;
|
||||
|
||||
+15
-25
@@ -3,17 +3,10 @@
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class PathManager {
|
||||
public:
|
||||
void Init();
|
||||
|
||||
static PathManager *Instance()
|
||||
{
|
||||
static PathManager instance;
|
||||
return &instance;
|
||||
}
|
||||
void LoadPaths();
|
||||
|
||||
[[nodiscard]] const std::string &GetLogPath() const;
|
||||
[[nodiscard]] const std::string &GetLuaModsPath() const;
|
||||
@@ -21,27 +14,24 @@ public:
|
||||
[[nodiscard]] const std::string &GetMapsPath() const;
|
||||
[[nodiscard]] const std::string &GetPatchPath() const;
|
||||
[[nodiscard]] const std::string &GetOpcodePath() const;
|
||||
[[nodiscard]] const std::string &GetPluginsPath() const;
|
||||
[[nodiscard]] const std::string &GetQuestsPath() const;
|
||||
[[nodiscard]] const std::string &GetServerPath() const;
|
||||
[[nodiscard]] const std::string &GetSharedMemoryPath() const;
|
||||
[[nodiscard]] std::vector<std::string> GetQuestPaths() const;
|
||||
[[nodiscard]] std::vector<std::string> GetPluginPaths() const;
|
||||
[[nodiscard]] std::vector<std::string> GetLuaModulePaths() const;
|
||||
|
||||
private:
|
||||
std::string m_log_path;
|
||||
std::string m_lua_mods_path;
|
||||
std::string m_maps_path;
|
||||
std::string m_patch_path;
|
||||
std::string m_opcode_path;
|
||||
std::string m_quests_path;
|
||||
std::vector<std::string> m_quests_paths;
|
||||
std::vector<std::string> m_plugin_paths;
|
||||
std::vector<std::string> m_lua_module_paths;
|
||||
|
||||
|
||||
private:
|
||||
std::string m_server_path;
|
||||
std::string m_shared_memory_path;
|
||||
std::string m_log_path;
|
||||
std::string m_lua_mods_path;
|
||||
std::string m_lua_modules_path;
|
||||
std::string m_maps_path;
|
||||
std::string m_patch_path;
|
||||
std::string m_opcode_path;
|
||||
std::string m_plugins_path;
|
||||
std::string m_quests_path;
|
||||
std::string m_server_path;
|
||||
std::string m_shared_memory_path;
|
||||
};
|
||||
|
||||
extern PathManager path;
|
||||
|
||||
#endif //EQEMU_PATH_MANAGER_H
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "../types.h"
|
||||
#include "../database.h"
|
||||
#include "../strings.h"
|
||||
#include "../eqemu_logsys.h"
|
||||
#include "../eqemu_logsys_log_aliases.h"
|
||||
#include "../features.h"
|
||||
#include "../global_define.h"
|
||||
@@ -1,7 +1,6 @@
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include "process.h"
|
||||
#include <fmt/format.h>
|
||||
|
||||
std::string Process::execute(const std::string &cmd)
|
||||
{
|
||||
|
||||
@@ -116,12 +116,6 @@ namespace EQ {
|
||||
Reseed();
|
||||
}
|
||||
|
||||
static Random* Instance()
|
||||
{
|
||||
static Random instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
private:
|
||||
#ifndef BIASED_INT_DIST
|
||||
typedef std::uniform_int_distribution<int>::param_type int_param_t;
|
||||
|
||||
@@ -70,7 +70,6 @@ public:
|
||||
uint32_t gm_exp;
|
||||
uint32_t killed_by;
|
||||
uint8_t rezzable;
|
||||
std::string entity_variables;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
@@ -132,7 +131,6 @@ public:
|
||||
"gm_exp",
|
||||
"killed_by",
|
||||
"rezzable",
|
||||
"entity_variables",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -190,7 +188,6 @@ public:
|
||||
"gm_exp",
|
||||
"killed_by",
|
||||
"rezzable",
|
||||
"entity_variables",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -282,7 +279,6 @@ public:
|
||||
e.gm_exp = 0;
|
||||
e.killed_by = 0;
|
||||
e.rezzable = 0;
|
||||
e.entity_variables = "";
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -370,7 +366,6 @@ public:
|
||||
e.gm_exp = row[48] ? static_cast<uint32_t>(strtoul(row[48], nullptr, 10)) : 0;
|
||||
e.killed_by = row[49] ? static_cast<uint32_t>(strtoul(row[49], nullptr, 10)) : 0;
|
||||
e.rezzable = row[50] ? static_cast<uint8_t>(strtoul(row[50], nullptr, 10)) : 0;
|
||||
e.entity_variables = row[51] ? row[51] : "";
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -454,7 +449,6 @@ public:
|
||||
v.push_back(columns[48] + " = " + std::to_string(e.gm_exp));
|
||||
v.push_back(columns[49] + " = " + std::to_string(e.killed_by));
|
||||
v.push_back(columns[50] + " = " + std::to_string(e.rezzable));
|
||||
v.push_back(columns[51] + " = '" + Strings::Escape(e.entity_variables) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -527,7 +521,6 @@ public:
|
||||
v.push_back(std::to_string(e.gm_exp));
|
||||
v.push_back(std::to_string(e.killed_by));
|
||||
v.push_back(std::to_string(e.rezzable));
|
||||
v.push_back("'" + Strings::Escape(e.entity_variables) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -608,7 +601,6 @@ public:
|
||||
v.push_back(std::to_string(e.gm_exp));
|
||||
v.push_back(std::to_string(e.killed_by));
|
||||
v.push_back(std::to_string(e.rezzable));
|
||||
v.push_back("'" + Strings::Escape(e.entity_variables) + "'");
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
@@ -693,7 +685,6 @@ public:
|
||||
e.gm_exp = row[48] ? static_cast<uint32_t>(strtoul(row[48], nullptr, 10)) : 0;
|
||||
e.killed_by = row[49] ? static_cast<uint32_t>(strtoul(row[49], nullptr, 10)) : 0;
|
||||
e.rezzable = row[50] ? static_cast<uint8_t>(strtoul(row[50], nullptr, 10)) : 0;
|
||||
e.entity_variables = row[51] ? row[51] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -769,7 +760,6 @@ public:
|
||||
e.gm_exp = row[48] ? static_cast<uint32_t>(strtoul(row[48], nullptr, 10)) : 0;
|
||||
e.killed_by = row[49] ? static_cast<uint32_t>(strtoul(row[49], nullptr, 10)) : 0;
|
||||
e.rezzable = row[50] ? static_cast<uint8_t>(strtoul(row[50], nullptr, 10)) : 0;
|
||||
e.entity_variables = row[51] ? row[51] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -895,7 +885,6 @@ public:
|
||||
v.push_back(std::to_string(e.gm_exp));
|
||||
v.push_back(std::to_string(e.killed_by));
|
||||
v.push_back(std::to_string(e.rezzable));
|
||||
v.push_back("'" + Strings::Escape(e.entity_variables) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -969,7 +958,6 @@ public:
|
||||
v.push_back(std::to_string(e.gm_exp));
|
||||
v.push_back(std::to_string(e.killed_by));
|
||||
v.push_back(std::to_string(e.rezzable));
|
||||
v.push_back("'" + Strings::Escape(e.entity_variables) + "'");
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
@@ -115,8 +115,7 @@ public:
|
||||
uint8_t lfg;
|
||||
std::string mailkey;
|
||||
uint8_t xtargets;
|
||||
uint8_t ingame;
|
||||
uint32_t first_login;
|
||||
int8_t firstlogon;
|
||||
uint32_t e_aa_effects;
|
||||
uint32_t e_percent_to_aa;
|
||||
uint32_t e_expended_aa_spent;
|
||||
@@ -231,8 +230,7 @@ public:
|
||||
"lfg",
|
||||
"mailkey",
|
||||
"xtargets",
|
||||
"ingame",
|
||||
"first_login",
|
||||
"firstlogon",
|
||||
"e_aa_effects",
|
||||
"e_percent_to_aa",
|
||||
"e_expended_aa_spent",
|
||||
@@ -343,8 +341,7 @@ public:
|
||||
"lfg",
|
||||
"mailkey",
|
||||
"xtargets",
|
||||
"ingame",
|
||||
"first_login",
|
||||
"firstlogon",
|
||||
"e_aa_effects",
|
||||
"e_percent_to_aa",
|
||||
"e_expended_aa_spent",
|
||||
@@ -489,8 +486,7 @@ public:
|
||||
e.lfg = 0;
|
||||
e.mailkey = "";
|
||||
e.xtargets = 5;
|
||||
e.ingame = 0;
|
||||
e.first_login = 0;
|
||||
e.firstlogon = 0;
|
||||
e.e_aa_effects = 0;
|
||||
e.e_percent_to_aa = 0;
|
||||
e.e_expended_aa_spent = 0;
|
||||
@@ -631,16 +627,15 @@ public:
|
||||
e.lfg = row[93] ? static_cast<uint8_t>(strtoul(row[93], nullptr, 10)) : 0;
|
||||
e.mailkey = row[94] ? row[94] : "";
|
||||
e.xtargets = row[95] ? static_cast<uint8_t>(strtoul(row[95], nullptr, 10)) : 5;
|
||||
e.ingame = row[96] ? static_cast<uint8_t>(strtoul(row[96], nullptr, 10)) : 0;
|
||||
e.first_login = row[97] ? static_cast<uint32_t>(strtoul(row[97], nullptr, 10)) : 0;
|
||||
e.e_aa_effects = row[98] ? static_cast<uint32_t>(strtoul(row[98], nullptr, 10)) : 0;
|
||||
e.e_percent_to_aa = row[99] ? static_cast<uint32_t>(strtoul(row[99], nullptr, 10)) : 0;
|
||||
e.e_expended_aa_spent = row[100] ? static_cast<uint32_t>(strtoul(row[100], nullptr, 10)) : 0;
|
||||
e.aa_points_spent_old = row[101] ? static_cast<uint32_t>(strtoul(row[101], nullptr, 10)) : 0;
|
||||
e.aa_points_old = row[102] ? static_cast<uint32_t>(strtoul(row[102], nullptr, 10)) : 0;
|
||||
e.e_last_invsnapshot = row[103] ? static_cast<uint32_t>(strtoul(row[103], nullptr, 10)) : 0;
|
||||
e.deleted_at = strtoll(row[104] ? row[104] : "-1", nullptr, 10);
|
||||
e.illusion_block = row[105] ? static_cast<uint8_t>(strtoul(row[105], nullptr, 10)) : 0;
|
||||
e.firstlogon = row[96] ? static_cast<int8_t>(atoi(row[96])) : 0;
|
||||
e.e_aa_effects = row[97] ? static_cast<uint32_t>(strtoul(row[97], nullptr, 10)) : 0;
|
||||
e.e_percent_to_aa = row[98] ? static_cast<uint32_t>(strtoul(row[98], nullptr, 10)) : 0;
|
||||
e.e_expended_aa_spent = row[99] ? static_cast<uint32_t>(strtoul(row[99], nullptr, 10)) : 0;
|
||||
e.aa_points_spent_old = row[100] ? static_cast<uint32_t>(strtoul(row[100], nullptr, 10)) : 0;
|
||||
e.aa_points_old = row[101] ? static_cast<uint32_t>(strtoul(row[101], nullptr, 10)) : 0;
|
||||
e.e_last_invsnapshot = row[102] ? static_cast<uint32_t>(strtoul(row[102], nullptr, 10)) : 0;
|
||||
e.deleted_at = strtoll(row[103] ? row[103] : "-1", nullptr, 10);
|
||||
e.illusion_block = row[104] ? static_cast<uint8_t>(strtoul(row[104], nullptr, 10)) : 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -769,16 +764,15 @@ public:
|
||||
v.push_back(columns[93] + " = " + std::to_string(e.lfg));
|
||||
v.push_back(columns[94] + " = '" + Strings::Escape(e.mailkey) + "'");
|
||||
v.push_back(columns[95] + " = " + std::to_string(e.xtargets));
|
||||
v.push_back(columns[96] + " = " + std::to_string(e.ingame));
|
||||
v.push_back(columns[97] + " = " + std::to_string(e.first_login));
|
||||
v.push_back(columns[98] + " = " + std::to_string(e.e_aa_effects));
|
||||
v.push_back(columns[99] + " = " + std::to_string(e.e_percent_to_aa));
|
||||
v.push_back(columns[100] + " = " + std::to_string(e.e_expended_aa_spent));
|
||||
v.push_back(columns[101] + " = " + std::to_string(e.aa_points_spent_old));
|
||||
v.push_back(columns[102] + " = " + std::to_string(e.aa_points_old));
|
||||
v.push_back(columns[103] + " = " + std::to_string(e.e_last_invsnapshot));
|
||||
v.push_back(columns[104] + " = FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")");
|
||||
v.push_back(columns[105] + " = " + std::to_string(e.illusion_block));
|
||||
v.push_back(columns[96] + " = " + std::to_string(e.firstlogon));
|
||||
v.push_back(columns[97] + " = " + std::to_string(e.e_aa_effects));
|
||||
v.push_back(columns[98] + " = " + std::to_string(e.e_percent_to_aa));
|
||||
v.push_back(columns[99] + " = " + std::to_string(e.e_expended_aa_spent));
|
||||
v.push_back(columns[100] + " = " + std::to_string(e.aa_points_spent_old));
|
||||
v.push_back(columns[101] + " = " + std::to_string(e.aa_points_old));
|
||||
v.push_back(columns[102] + " = " + std::to_string(e.e_last_invsnapshot));
|
||||
v.push_back(columns[103] + " = FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")");
|
||||
v.push_back(columns[104] + " = " + std::to_string(e.illusion_block));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -896,8 +890,7 @@ public:
|
||||
v.push_back(std::to_string(e.lfg));
|
||||
v.push_back("'" + Strings::Escape(e.mailkey) + "'");
|
||||
v.push_back(std::to_string(e.xtargets));
|
||||
v.push_back(std::to_string(e.ingame));
|
||||
v.push_back(std::to_string(e.first_login));
|
||||
v.push_back(std::to_string(e.firstlogon));
|
||||
v.push_back(std::to_string(e.e_aa_effects));
|
||||
v.push_back(std::to_string(e.e_percent_to_aa));
|
||||
v.push_back(std::to_string(e.e_expended_aa_spent));
|
||||
@@ -1031,8 +1024,7 @@ public:
|
||||
v.push_back(std::to_string(e.lfg));
|
||||
v.push_back("'" + Strings::Escape(e.mailkey) + "'");
|
||||
v.push_back(std::to_string(e.xtargets));
|
||||
v.push_back(std::to_string(e.ingame));
|
||||
v.push_back(std::to_string(e.first_login));
|
||||
v.push_back(std::to_string(e.firstlogon));
|
||||
v.push_back(std::to_string(e.e_aa_effects));
|
||||
v.push_back(std::to_string(e.e_percent_to_aa));
|
||||
v.push_back(std::to_string(e.e_expended_aa_spent));
|
||||
@@ -1170,16 +1162,15 @@ public:
|
||||
e.lfg = row[93] ? static_cast<uint8_t>(strtoul(row[93], nullptr, 10)) : 0;
|
||||
e.mailkey = row[94] ? row[94] : "";
|
||||
e.xtargets = row[95] ? static_cast<uint8_t>(strtoul(row[95], nullptr, 10)) : 5;
|
||||
e.ingame = row[96] ? static_cast<uint8_t>(strtoul(row[96], nullptr, 10)) : 0;
|
||||
e.first_login = row[97] ? static_cast<uint32_t>(strtoul(row[97], nullptr, 10)) : 0;
|
||||
e.e_aa_effects = row[98] ? static_cast<uint32_t>(strtoul(row[98], nullptr, 10)) : 0;
|
||||
e.e_percent_to_aa = row[99] ? static_cast<uint32_t>(strtoul(row[99], nullptr, 10)) : 0;
|
||||
e.e_expended_aa_spent = row[100] ? static_cast<uint32_t>(strtoul(row[100], nullptr, 10)) : 0;
|
||||
e.aa_points_spent_old = row[101] ? static_cast<uint32_t>(strtoul(row[101], nullptr, 10)) : 0;
|
||||
e.aa_points_old = row[102] ? static_cast<uint32_t>(strtoul(row[102], nullptr, 10)) : 0;
|
||||
e.e_last_invsnapshot = row[103] ? static_cast<uint32_t>(strtoul(row[103], nullptr, 10)) : 0;
|
||||
e.deleted_at = strtoll(row[104] ? row[104] : "-1", nullptr, 10);
|
||||
e.illusion_block = row[105] ? static_cast<uint8_t>(strtoul(row[105], nullptr, 10)) : 0;
|
||||
e.firstlogon = row[96] ? static_cast<int8_t>(atoi(row[96])) : 0;
|
||||
e.e_aa_effects = row[97] ? static_cast<uint32_t>(strtoul(row[97], nullptr, 10)) : 0;
|
||||
e.e_percent_to_aa = row[98] ? static_cast<uint32_t>(strtoul(row[98], nullptr, 10)) : 0;
|
||||
e.e_expended_aa_spent = row[99] ? static_cast<uint32_t>(strtoul(row[99], nullptr, 10)) : 0;
|
||||
e.aa_points_spent_old = row[100] ? static_cast<uint32_t>(strtoul(row[100], nullptr, 10)) : 0;
|
||||
e.aa_points_old = row[101] ? static_cast<uint32_t>(strtoul(row[101], nullptr, 10)) : 0;
|
||||
e.e_last_invsnapshot = row[102] ? static_cast<uint32_t>(strtoul(row[102], nullptr, 10)) : 0;
|
||||
e.deleted_at = strtoll(row[103] ? row[103] : "-1", nullptr, 10);
|
||||
e.illusion_block = row[104] ? static_cast<uint8_t>(strtoul(row[104], nullptr, 10)) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -1300,16 +1291,15 @@ public:
|
||||
e.lfg = row[93] ? static_cast<uint8_t>(strtoul(row[93], nullptr, 10)) : 0;
|
||||
e.mailkey = row[94] ? row[94] : "";
|
||||
e.xtargets = row[95] ? static_cast<uint8_t>(strtoul(row[95], nullptr, 10)) : 5;
|
||||
e.ingame = row[96] ? static_cast<uint8_t>(strtoul(row[96], nullptr, 10)) : 0;
|
||||
e.first_login = row[97] ? static_cast<uint32_t>(strtoul(row[97], nullptr, 10)) : 0;
|
||||
e.e_aa_effects = row[98] ? static_cast<uint32_t>(strtoul(row[98], nullptr, 10)) : 0;
|
||||
e.e_percent_to_aa = row[99] ? static_cast<uint32_t>(strtoul(row[99], nullptr, 10)) : 0;
|
||||
e.e_expended_aa_spent = row[100] ? static_cast<uint32_t>(strtoul(row[100], nullptr, 10)) : 0;
|
||||
e.aa_points_spent_old = row[101] ? static_cast<uint32_t>(strtoul(row[101], nullptr, 10)) : 0;
|
||||
e.aa_points_old = row[102] ? static_cast<uint32_t>(strtoul(row[102], nullptr, 10)) : 0;
|
||||
e.e_last_invsnapshot = row[103] ? static_cast<uint32_t>(strtoul(row[103], nullptr, 10)) : 0;
|
||||
e.deleted_at = strtoll(row[104] ? row[104] : "-1", nullptr, 10);
|
||||
e.illusion_block = row[105] ? static_cast<uint8_t>(strtoul(row[105], nullptr, 10)) : 0;
|
||||
e.firstlogon = row[96] ? static_cast<int8_t>(atoi(row[96])) : 0;
|
||||
e.e_aa_effects = row[97] ? static_cast<uint32_t>(strtoul(row[97], nullptr, 10)) : 0;
|
||||
e.e_percent_to_aa = row[98] ? static_cast<uint32_t>(strtoul(row[98], nullptr, 10)) : 0;
|
||||
e.e_expended_aa_spent = row[99] ? static_cast<uint32_t>(strtoul(row[99], nullptr, 10)) : 0;
|
||||
e.aa_points_spent_old = row[100] ? static_cast<uint32_t>(strtoul(row[100], nullptr, 10)) : 0;
|
||||
e.aa_points_old = row[101] ? static_cast<uint32_t>(strtoul(row[101], nullptr, 10)) : 0;
|
||||
e.e_last_invsnapshot = row[102] ? static_cast<uint32_t>(strtoul(row[102], nullptr, 10)) : 0;
|
||||
e.deleted_at = strtoll(row[103] ? row[103] : "-1", nullptr, 10);
|
||||
e.illusion_block = row[104] ? static_cast<uint8_t>(strtoul(row[104], nullptr, 10)) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -1480,8 +1470,7 @@ public:
|
||||
v.push_back(std::to_string(e.lfg));
|
||||
v.push_back("'" + Strings::Escape(e.mailkey) + "'");
|
||||
v.push_back(std::to_string(e.xtargets));
|
||||
v.push_back(std::to_string(e.ingame));
|
||||
v.push_back(std::to_string(e.first_login));
|
||||
v.push_back(std::to_string(e.firstlogon));
|
||||
v.push_back(std::to_string(e.e_aa_effects));
|
||||
v.push_back(std::to_string(e.e_percent_to_aa));
|
||||
v.push_back(std::to_string(e.e_expended_aa_spent));
|
||||
@@ -1608,8 +1597,7 @@ public:
|
||||
v.push_back(std::to_string(e.lfg));
|
||||
v.push_back("'" + Strings::Escape(e.mailkey) + "'");
|
||||
v.push_back(std::to_string(e.xtargets));
|
||||
v.push_back(std::to_string(e.ingame));
|
||||
v.push_back(std::to_string(e.first_login));
|
||||
v.push_back(std::to_string(e.firstlogon));
|
||||
v.push_back(std::to_string(e.e_aa_effects));
|
||||
v.push_back(std::to_string(e.e_percent_to_aa));
|
||||
v.push_back(std::to_string(e.e_expended_aa_spent));
|
||||
|
||||
@@ -23,12 +23,10 @@ public:
|
||||
std::string key_;
|
||||
std::string value;
|
||||
uint32_t expires;
|
||||
uint64_t account_id;
|
||||
uint64_t character_id;
|
||||
uint32_t npc_id;
|
||||
uint32_t bot_id;
|
||||
uint16_t zone_id;
|
||||
uint16_t instance_id;
|
||||
int64_t account_id;
|
||||
int64_t character_id;
|
||||
int64_t npc_id;
|
||||
int64_t bot_id;
|
||||
|
||||
// cereal
|
||||
template<class Archive>
|
||||
@@ -42,9 +40,7 @@ public:
|
||||
CEREAL_NVP(account_id),
|
||||
CEREAL_NVP(character_id),
|
||||
CEREAL_NVP(npc_id),
|
||||
CEREAL_NVP(bot_id),
|
||||
CEREAL_NVP(zone_id),
|
||||
CEREAL_NVP(instance_id)
|
||||
CEREAL_NVP(bot_id)
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -65,8 +61,6 @@ public:
|
||||
"character_id",
|
||||
"npc_id",
|
||||
"bot_id",
|
||||
"zone_id",
|
||||
"instance_id",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -81,8 +75,6 @@ public:
|
||||
"character_id",
|
||||
"npc_id",
|
||||
"bot_id",
|
||||
"zone_id",
|
||||
"instance_id",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -131,8 +123,6 @@ public:
|
||||
e.character_id = 0;
|
||||
e.npc_id = 0;
|
||||
e.bot_id = 0;
|
||||
e.zone_id = 0;
|
||||
e.instance_id = 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -173,12 +163,10 @@ public:
|
||||
e.key_ = row[1] ? row[1] : "";
|
||||
e.value = row[2] ? row[2] : "";
|
||||
e.expires = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.account_id = row[4] ? strtoull(row[4], nullptr, 10) : 0;
|
||||
e.character_id = row[5] ? strtoull(row[5], nullptr, 10) : 0;
|
||||
e.npc_id = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.bot_id = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.zone_id = row[8] ? static_cast<uint16_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.instance_id = row[9] ? static_cast<uint16_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.account_id = row[4] ? strtoll(row[4], nullptr, 10) : 0;
|
||||
e.character_id = row[5] ? strtoll(row[5], nullptr, 10) : 0;
|
||||
e.npc_id = row[6] ? strtoll(row[6], nullptr, 10) : 0;
|
||||
e.bot_id = row[7] ? strtoll(row[7], nullptr, 10) : 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -219,8 +207,6 @@ public:
|
||||
v.push_back(columns[5] + " = " + std::to_string(e.character_id));
|
||||
v.push_back(columns[6] + " = " + std::to_string(e.npc_id));
|
||||
v.push_back(columns[7] + " = " + std::to_string(e.bot_id));
|
||||
v.push_back(columns[8] + " = " + std::to_string(e.zone_id));
|
||||
v.push_back(columns[9] + " = " + std::to_string(e.instance_id));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -250,8 +236,6 @@ public:
|
||||
v.push_back(std::to_string(e.character_id));
|
||||
v.push_back(std::to_string(e.npc_id));
|
||||
v.push_back(std::to_string(e.bot_id));
|
||||
v.push_back(std::to_string(e.zone_id));
|
||||
v.push_back(std::to_string(e.instance_id));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -289,8 +273,6 @@ public:
|
||||
v.push_back(std::to_string(e.character_id));
|
||||
v.push_back(std::to_string(e.npc_id));
|
||||
v.push_back(std::to_string(e.bot_id));
|
||||
v.push_back(std::to_string(e.zone_id));
|
||||
v.push_back(std::to_string(e.instance_id));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
@@ -328,12 +310,10 @@ public:
|
||||
e.key_ = row[1] ? row[1] : "";
|
||||
e.value = row[2] ? row[2] : "";
|
||||
e.expires = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.account_id = row[4] ? strtoull(row[4], nullptr, 10) : 0;
|
||||
e.character_id = row[5] ? strtoull(row[5], nullptr, 10) : 0;
|
||||
e.npc_id = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.bot_id = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.zone_id = row[8] ? static_cast<uint16_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.instance_id = row[9] ? static_cast<uint16_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.account_id = row[4] ? strtoll(row[4], nullptr, 10) : 0;
|
||||
e.character_id = row[5] ? strtoll(row[5], nullptr, 10) : 0;
|
||||
e.npc_id = row[6] ? strtoll(row[6], nullptr, 10) : 0;
|
||||
e.bot_id = row[7] ? strtoll(row[7], nullptr, 10) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -362,12 +342,10 @@ public:
|
||||
e.key_ = row[1] ? row[1] : "";
|
||||
e.value = row[2] ? row[2] : "";
|
||||
e.expires = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.account_id = row[4] ? strtoull(row[4], nullptr, 10) : 0;
|
||||
e.character_id = row[5] ? strtoull(row[5], nullptr, 10) : 0;
|
||||
e.npc_id = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.bot_id = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.zone_id = row[8] ? static_cast<uint16_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.instance_id = row[9] ? static_cast<uint16_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.account_id = row[4] ? strtoll(row[4], nullptr, 10) : 0;
|
||||
e.character_id = row[5] ? strtoll(row[5], nullptr, 10) : 0;
|
||||
e.npc_id = row[6] ? strtoll(row[6], nullptr, 10) : 0;
|
||||
e.bot_id = row[7] ? strtoll(row[7], nullptr, 10) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -450,8 +428,6 @@ public:
|
||||
v.push_back(std::to_string(e.character_id));
|
||||
v.push_back(std::to_string(e.npc_id));
|
||||
v.push_back(std::to_string(e.bot_id));
|
||||
v.push_back(std::to_string(e.zone_id));
|
||||
v.push_back(std::to_string(e.instance_id));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -482,8 +458,6 @@ public:
|
||||
v.push_back(std::to_string(e.character_id));
|
||||
v.push_back(std::to_string(e.npc_id));
|
||||
v.push_back(std::to_string(e.bot_id));
|
||||
v.push_back(std::to_string(e.zone_id));
|
||||
v.push_back(std::to_string(e.instance_id));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
@@ -42,8 +42,6 @@ public:
|
||||
float zone_in_z;
|
||||
float zone_in_heading;
|
||||
uint8_t has_zone_in;
|
||||
int8_t is_locked;
|
||||
int8_t add_replay;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
@@ -77,8 +75,6 @@ public:
|
||||
"zone_in_z",
|
||||
"zone_in_heading",
|
||||
"has_zone_in",
|
||||
"is_locked",
|
||||
"add_replay",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -108,8 +104,6 @@ public:
|
||||
"zone_in_z",
|
||||
"zone_in_heading",
|
||||
"has_zone_in",
|
||||
"is_locked",
|
||||
"add_replay",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -173,8 +167,6 @@ public:
|
||||
e.zone_in_z = 0;
|
||||
e.zone_in_heading = 0;
|
||||
e.has_zone_in = 0;
|
||||
e.is_locked = 0;
|
||||
e.add_replay = 1;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -234,8 +226,6 @@ public:
|
||||
e.zone_in_z = row[20] ? strtof(row[20], nullptr) : 0;
|
||||
e.zone_in_heading = row[21] ? strtof(row[21], nullptr) : 0;
|
||||
e.has_zone_in = row[22] ? static_cast<uint8_t>(strtoul(row[22], nullptr, 10)) : 0;
|
||||
e.is_locked = row[23] ? static_cast<int8_t>(atoi(row[23])) : 0;
|
||||
e.add_replay = row[24] ? static_cast<int8_t>(atoi(row[24])) : 1;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -291,8 +281,6 @@ public:
|
||||
v.push_back(columns[20] + " = " + std::to_string(e.zone_in_z));
|
||||
v.push_back(columns[21] + " = " + std::to_string(e.zone_in_heading));
|
||||
v.push_back(columns[22] + " = " + std::to_string(e.has_zone_in));
|
||||
v.push_back(columns[23] + " = " + std::to_string(e.is_locked));
|
||||
v.push_back(columns[24] + " = " + std::to_string(e.add_replay));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -337,8 +325,6 @@ public:
|
||||
v.push_back(std::to_string(e.zone_in_z));
|
||||
v.push_back(std::to_string(e.zone_in_heading));
|
||||
v.push_back(std::to_string(e.has_zone_in));
|
||||
v.push_back(std::to_string(e.is_locked));
|
||||
v.push_back(std::to_string(e.add_replay));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -391,8 +377,6 @@ public:
|
||||
v.push_back(std::to_string(e.zone_in_z));
|
||||
v.push_back(std::to_string(e.zone_in_heading));
|
||||
v.push_back(std::to_string(e.has_zone_in));
|
||||
v.push_back(std::to_string(e.is_locked));
|
||||
v.push_back(std::to_string(e.add_replay));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
@@ -449,8 +433,6 @@ public:
|
||||
e.zone_in_z = row[20] ? strtof(row[20], nullptr) : 0;
|
||||
e.zone_in_heading = row[21] ? strtof(row[21], nullptr) : 0;
|
||||
e.has_zone_in = row[22] ? static_cast<uint8_t>(strtoul(row[22], nullptr, 10)) : 0;
|
||||
e.is_locked = row[23] ? static_cast<int8_t>(atoi(row[23])) : 0;
|
||||
e.add_replay = row[24] ? static_cast<int8_t>(atoi(row[24])) : 1;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -498,8 +480,6 @@ public:
|
||||
e.zone_in_z = row[20] ? strtof(row[20], nullptr) : 0;
|
||||
e.zone_in_heading = row[21] ? strtof(row[21], nullptr) : 0;
|
||||
e.has_zone_in = row[22] ? static_cast<uint8_t>(strtoul(row[22], nullptr, 10)) : 0;
|
||||
e.is_locked = row[23] ? static_cast<int8_t>(atoi(row[23])) : 0;
|
||||
e.add_replay = row[24] ? static_cast<int8_t>(atoi(row[24])) : 1;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -597,8 +577,6 @@ public:
|
||||
v.push_back(std::to_string(e.zone_in_z));
|
||||
v.push_back(std::to_string(e.zone_in_heading));
|
||||
v.push_back(std::to_string(e.has_zone_in));
|
||||
v.push_back(std::to_string(e.is_locked));
|
||||
v.push_back(std::to_string(e.add_replay));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -644,8 +622,6 @@ public:
|
||||
v.push_back(std::to_string(e.zone_in_z));
|
||||
v.push_back(std::to_string(e.zone_in_heading));
|
||||
v.push_back(std::to_string(e.has_zone_in));
|
||||
v.push_back(std::to_string(e.is_locked));
|
||||
v.push_back(std::to_string(e.add_replay));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
+44
-44
@@ -9,18 +9,18 @@
|
||||
* @docs https://docs.eqemu.io/developer/repositories
|
||||
*/
|
||||
|
||||
#ifndef EQEMU_BASE_DYNAMIC_ZONE_LOCKOUTS_REPOSITORY_H
|
||||
#define EQEMU_BASE_DYNAMIC_ZONE_LOCKOUTS_REPOSITORY_H
|
||||
#ifndef EQEMU_BASE_EXPEDITION_LOCKOUTS_REPOSITORY_H
|
||||
#define EQEMU_BASE_EXPEDITION_LOCKOUTS_REPOSITORY_H
|
||||
|
||||
#include "../../database.h"
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
class BaseDynamicZoneLockoutsRepository {
|
||||
class BaseExpeditionLockoutsRepository {
|
||||
public:
|
||||
struct DynamicZoneLockouts {
|
||||
struct ExpeditionLockouts {
|
||||
uint32_t id;
|
||||
uint32_t dynamic_zone_id;
|
||||
uint32_t expedition_id;
|
||||
std::string event_name;
|
||||
time_t expire_time;
|
||||
uint32_t duration;
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"dynamic_zone_id",
|
||||
"expedition_id",
|
||||
"event_name",
|
||||
"expire_time",
|
||||
"duration",
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"dynamic_zone_id",
|
||||
"expedition_id",
|
||||
"event_name",
|
||||
"UNIX_TIMESTAMP(expire_time)",
|
||||
"duration",
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
|
||||
static std::string TableName()
|
||||
{
|
||||
return std::string("dynamic_zone_lockouts");
|
||||
return std::string("expedition_lockouts");
|
||||
}
|
||||
|
||||
static std::string BaseSelect()
|
||||
@@ -89,12 +89,12 @@ public:
|
||||
);
|
||||
}
|
||||
|
||||
static DynamicZoneLockouts NewEntity()
|
||||
static ExpeditionLockouts NewEntity()
|
||||
{
|
||||
DynamicZoneLockouts e{};
|
||||
ExpeditionLockouts e{};
|
||||
|
||||
e.id = 0;
|
||||
e.dynamic_zone_id = 0;
|
||||
e.expedition_id = 0;
|
||||
e.event_name = "";
|
||||
e.expire_time = std::time(nullptr);
|
||||
e.duration = 0;
|
||||
@@ -103,23 +103,23 @@ public:
|
||||
return e;
|
||||
}
|
||||
|
||||
static DynamicZoneLockouts GetDynamicZoneLockouts(
|
||||
const std::vector<DynamicZoneLockouts> &dynamic_zone_lockoutss,
|
||||
int dynamic_zone_lockouts_id
|
||||
static ExpeditionLockouts GetExpeditionLockouts(
|
||||
const std::vector<ExpeditionLockouts> &expedition_lockoutss,
|
||||
int expedition_lockouts_id
|
||||
)
|
||||
{
|
||||
for (auto &dynamic_zone_lockouts : dynamic_zone_lockoutss) {
|
||||
if (dynamic_zone_lockouts.id == dynamic_zone_lockouts_id) {
|
||||
return dynamic_zone_lockouts;
|
||||
for (auto &expedition_lockouts : expedition_lockoutss) {
|
||||
if (expedition_lockouts.id == expedition_lockouts_id) {
|
||||
return expedition_lockouts;
|
||||
}
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static DynamicZoneLockouts FindOne(
|
||||
static ExpeditionLockouts FindOne(
|
||||
Database& db,
|
||||
int dynamic_zone_lockouts_id
|
||||
int expedition_lockouts_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
@@ -127,16 +127,16 @@ public:
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
dynamic_zone_lockouts_id
|
||||
expedition_lockouts_id
|
||||
)
|
||||
);
|
||||
|
||||
auto row = results.begin();
|
||||
if (results.RowCount() == 1) {
|
||||
DynamicZoneLockouts e{};
|
||||
ExpeditionLockouts e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.dynamic_zone_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.expedition_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.event_name = row[2] ? row[2] : "";
|
||||
e.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10);
|
||||
e.duration = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
@@ -150,7 +150,7 @@ public:
|
||||
|
||||
static int DeleteOne(
|
||||
Database& db,
|
||||
int dynamic_zone_lockouts_id
|
||||
int expedition_lockouts_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
@@ -158,7 +158,7 @@ public:
|
||||
"DELETE FROM {} WHERE {} = {}",
|
||||
TableName(),
|
||||
PrimaryKey(),
|
||||
dynamic_zone_lockouts_id
|
||||
expedition_lockouts_id
|
||||
)
|
||||
);
|
||||
|
||||
@@ -167,14 +167,14 @@ public:
|
||||
|
||||
static int UpdateOne(
|
||||
Database& db,
|
||||
const DynamicZoneLockouts &e
|
||||
const ExpeditionLockouts &e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto columns = Columns();
|
||||
|
||||
v.push_back(columns[1] + " = " + std::to_string(e.dynamic_zone_id));
|
||||
v.push_back(columns[1] + " = " + std::to_string(e.expedition_id));
|
||||
v.push_back(columns[2] + " = '" + Strings::Escape(e.event_name) + "'");
|
||||
v.push_back(columns[3] + " = FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")");
|
||||
v.push_back(columns[4] + " = " + std::to_string(e.duration));
|
||||
@@ -193,15 +193,15 @@ public:
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static DynamicZoneLockouts InsertOne(
|
||||
static ExpeditionLockouts InsertOne(
|
||||
Database& db,
|
||||
DynamicZoneLockouts e
|
||||
ExpeditionLockouts e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.dynamic_zone_id));
|
||||
v.push_back(std::to_string(e.expedition_id));
|
||||
v.push_back("'" + Strings::Escape(e.event_name) + "'");
|
||||
v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")");
|
||||
v.push_back(std::to_string(e.duration));
|
||||
@@ -227,7 +227,7 @@ public:
|
||||
|
||||
static int InsertMany(
|
||||
Database& db,
|
||||
const std::vector<DynamicZoneLockouts> &entries
|
||||
const std::vector<ExpeditionLockouts> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
@@ -236,7 +236,7 @@ public:
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.dynamic_zone_id));
|
||||
v.push_back(std::to_string(e.expedition_id));
|
||||
v.push_back("'" + Strings::Escape(e.event_name) + "'");
|
||||
v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")");
|
||||
v.push_back(std::to_string(e.duration));
|
||||
@@ -258,9 +258,9 @@ public:
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static std::vector<DynamicZoneLockouts> All(Database& db)
|
||||
static std::vector<ExpeditionLockouts> All(Database& db)
|
||||
{
|
||||
std::vector<DynamicZoneLockouts> all_entries;
|
||||
std::vector<ExpeditionLockouts> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -272,10 +272,10 @@ public:
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
DynamicZoneLockouts e{};
|
||||
ExpeditionLockouts e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.dynamic_zone_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.expedition_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.event_name = row[2] ? row[2] : "";
|
||||
e.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10);
|
||||
e.duration = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
@@ -287,9 +287,9 @@ public:
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static std::vector<DynamicZoneLockouts> GetWhere(Database& db, const std::string &where_filter)
|
||||
static std::vector<ExpeditionLockouts> GetWhere(Database& db, const std::string &where_filter)
|
||||
{
|
||||
std::vector<DynamicZoneLockouts> all_entries;
|
||||
std::vector<ExpeditionLockouts> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -302,10 +302,10 @@ public:
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
DynamicZoneLockouts e{};
|
||||
ExpeditionLockouts e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.dynamic_zone_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.expedition_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.event_name = row[2] ? row[2] : "";
|
||||
e.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10);
|
||||
e.duration = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
@@ -379,13 +379,13 @@ public:
|
||||
|
||||
static int ReplaceOne(
|
||||
Database& db,
|
||||
const DynamicZoneLockouts &e
|
||||
const ExpeditionLockouts &e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.dynamic_zone_id));
|
||||
v.push_back(std::to_string(e.expedition_id));
|
||||
v.push_back("'" + Strings::Escape(e.event_name) + "'");
|
||||
v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")");
|
||||
v.push_back(std::to_string(e.duration));
|
||||
@@ -404,7 +404,7 @@ public:
|
||||
|
||||
static int ReplaceMany(
|
||||
Database& db,
|
||||
const std::vector<DynamicZoneLockouts> &entries
|
||||
const std::vector<ExpeditionLockouts> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
@@ -413,7 +413,7 @@ public:
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.dynamic_zone_id));
|
||||
v.push_back(std::to_string(e.expedition_id));
|
||||
v.push_back("'" + Strings::Escape(e.event_name) + "'");
|
||||
v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")");
|
||||
v.push_back(std::to_string(e.duration));
|
||||
@@ -436,4 +436,4 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#endif //EQEMU_BASE_DYNAMIC_ZONE_LOCKOUTS_REPOSITORY_H
|
||||
#endif //EQEMU_BASE_EXPEDITION_LOCKOUTS_REPOSITORY_H
|
||||
@@ -0,0 +1,415 @@
|
||||
/**
|
||||
* DO NOT MODIFY THIS FILE
|
||||
*
|
||||
* This repository was automatically generated and is NOT to be modified directly.
|
||||
* Any repository modifications are meant to be made to the repository extending the base.
|
||||
* Any modifications to base repositories are to be made by the generator only
|
||||
*
|
||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||
* @docs https://docs.eqemu.io/developer/repositories
|
||||
*/
|
||||
|
||||
#ifndef EQEMU_BASE_EXPEDITIONS_REPOSITORY_H
|
||||
#define EQEMU_BASE_EXPEDITIONS_REPOSITORY_H
|
||||
|
||||
#include "../../database.h"
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
class BaseExpeditionsRepository {
|
||||
public:
|
||||
struct Expeditions {
|
||||
uint32_t id;
|
||||
uint32_t dynamic_zone_id;
|
||||
uint8_t add_replay_on_join;
|
||||
uint8_t is_locked;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
{
|
||||
return std::string("id");
|
||||
}
|
||||
|
||||
static std::vector<std::string> Columns()
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"dynamic_zone_id",
|
||||
"add_replay_on_join",
|
||||
"is_locked",
|
||||
};
|
||||
}
|
||||
|
||||
static std::vector<std::string> SelectColumns()
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"dynamic_zone_id",
|
||||
"add_replay_on_join",
|
||||
"is_locked",
|
||||
};
|
||||
}
|
||||
|
||||
static std::string ColumnsRaw()
|
||||
{
|
||||
return std::string(Strings::Implode(", ", Columns()));
|
||||
}
|
||||
|
||||
static std::string SelectColumnsRaw()
|
||||
{
|
||||
return std::string(Strings::Implode(", ", SelectColumns()));
|
||||
}
|
||||
|
||||
static std::string TableName()
|
||||
{
|
||||
return std::string("expeditions");
|
||||
}
|
||||
|
||||
static std::string BaseSelect()
|
||||
{
|
||||
return fmt::format(
|
||||
"SELECT {} FROM {}",
|
||||
SelectColumnsRaw(),
|
||||
TableName()
|
||||
);
|
||||
}
|
||||
|
||||
static std::string BaseInsert()
|
||||
{
|
||||
return fmt::format(
|
||||
"INSERT INTO {} ({}) ",
|
||||
TableName(),
|
||||
ColumnsRaw()
|
||||
);
|
||||
}
|
||||
|
||||
static Expeditions NewEntity()
|
||||
{
|
||||
Expeditions e{};
|
||||
|
||||
e.id = 0;
|
||||
e.dynamic_zone_id = 0;
|
||||
e.add_replay_on_join = 1;
|
||||
e.is_locked = 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static Expeditions GetExpeditions(
|
||||
const std::vector<Expeditions> &expeditionss,
|
||||
int expeditions_id
|
||||
)
|
||||
{
|
||||
for (auto &expeditions : expeditionss) {
|
||||
if (expeditions.id == expeditions_id) {
|
||||
return expeditions;
|
||||
}
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static Expeditions FindOne(
|
||||
Database& db,
|
||||
int expeditions_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
expeditions_id
|
||||
)
|
||||
);
|
||||
|
||||
auto row = results.begin();
|
||||
if (results.RowCount() == 1) {
|
||||
Expeditions e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.dynamic_zone_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.add_replay_on_join = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 1;
|
||||
e.is_locked = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static int DeleteOne(
|
||||
Database& db,
|
||||
int expeditions_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"DELETE FROM {} WHERE {} = {}",
|
||||
TableName(),
|
||||
PrimaryKey(),
|
||||
expeditions_id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int UpdateOne(
|
||||
Database& db,
|
||||
const Expeditions &e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto columns = Columns();
|
||||
|
||||
v.push_back(columns[1] + " = " + std::to_string(e.dynamic_zone_id));
|
||||
v.push_back(columns[2] + " = " + std::to_string(e.add_replay_on_join));
|
||||
v.push_back(columns[3] + " = " + std::to_string(e.is_locked));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"UPDATE {} SET {} WHERE {} = {}",
|
||||
TableName(),
|
||||
Strings::Implode(", ", v),
|
||||
PrimaryKey(),
|
||||
e.id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static Expeditions InsertOne(
|
||||
Database& db,
|
||||
Expeditions e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.dynamic_zone_id));
|
||||
v.push_back(std::to_string(e.add_replay_on_join));
|
||||
v.push_back(std::to_string(e.is_locked));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES ({})",
|
||||
BaseInsert(),
|
||||
Strings::Implode(",", v)
|
||||
)
|
||||
);
|
||||
|
||||
if (results.Success()) {
|
||||
e.id = results.LastInsertedID();
|
||||
return e;
|
||||
}
|
||||
|
||||
e = NewEntity();
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static int InsertMany(
|
||||
Database& db,
|
||||
const std::vector<Expeditions> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &e: entries) {
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.dynamic_zone_id));
|
||||
v.push_back(std::to_string(e.add_replay_on_join));
|
||||
v.push_back(std::to_string(e.is_locked));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES {}",
|
||||
BaseInsert(),
|
||||
Strings::Implode(",", insert_chunks)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static std::vector<Expeditions> All(Database& db)
|
||||
{
|
||||
std::vector<Expeditions> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{}",
|
||||
BaseSelect()
|
||||
)
|
||||
);
|
||||
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
Expeditions e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.dynamic_zone_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.add_replay_on_join = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 1;
|
||||
e.is_locked = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static std::vector<Expeditions> GetWhere(Database& db, const std::string &where_filter)
|
||||
{
|
||||
std::vector<Expeditions> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE {}",
|
||||
BaseSelect(),
|
||||
where_filter
|
||||
)
|
||||
);
|
||||
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
Expeditions e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.dynamic_zone_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.add_replay_on_join = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 1;
|
||||
e.is_locked = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static int DeleteWhere(Database& db, const std::string &where_filter)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"DELETE FROM {} WHERE {}",
|
||||
TableName(),
|
||||
where_filter
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int Truncate(Database& db)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"TRUNCATE TABLE {}",
|
||||
TableName()
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int64 GetMaxId(Database& db)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"SELECT COALESCE(MAX({}), 0) FROM {}",
|
||||
PrimaryKey(),
|
||||
TableName()
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||
}
|
||||
|
||||
static int64 Count(Database& db, const std::string &where_filter = "")
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"SELECT COUNT(*) FROM {} {}",
|
||||
TableName(),
|
||||
(where_filter.empty() ? "" : "WHERE " + where_filter)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||
}
|
||||
|
||||
static std::string BaseReplace()
|
||||
{
|
||||
return fmt::format(
|
||||
"REPLACE INTO {} ({}) ",
|
||||
TableName(),
|
||||
ColumnsRaw()
|
||||
);
|
||||
}
|
||||
|
||||
static int ReplaceOne(
|
||||
Database& db,
|
||||
const Expeditions &e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.dynamic_zone_id));
|
||||
v.push_back(std::to_string(e.add_replay_on_join));
|
||||
v.push_back(std::to_string(e.is_locked));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES ({})",
|
||||
BaseReplace(),
|
||||
Strings::Implode(",", v)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int ReplaceMany(
|
||||
Database& db,
|
||||
const std::vector<Expeditions> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &e: entries) {
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.dynamic_zone_id));
|
||||
v.push_back(std::to_string(e.add_replay_on_join));
|
||||
v.push_back(std::to_string(e.is_locked));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES {}",
|
||||
BaseReplace(),
|
||||
Strings::Implode(",", insert_chunks)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
};
|
||||
|
||||
#endif //EQEMU_BASE_EXPEDITIONS_REPOSITORY_H
|
||||
@@ -6,7 +6,7 @@
|
||||
* Any modifications to base repositories are to be made by the generator only
|
||||
*
|
||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||
* @docs https://docs.eqemu.io/developer/repositories
|
||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
||||
*/
|
||||
|
||||
#ifndef EQEMU_BASE_GUILD_BANK_REPOSITORY_H
|
||||
@@ -16,24 +16,19 @@
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
|
||||
class BaseGuildBankRepository {
|
||||
public:
|
||||
struct GuildBank {
|
||||
uint32_t id;
|
||||
uint32_t guild_id;
|
||||
uint32_t guildid;
|
||||
uint8_t area;
|
||||
uint32_t slot;
|
||||
uint32_t item_id;
|
||||
uint32_t augment_one_id;
|
||||
uint32_t augment_two_id;
|
||||
uint32_t augment_three_id;
|
||||
uint32_t augment_four_id;
|
||||
uint32_t augment_five_id;
|
||||
uint32_t augment_six_id;
|
||||
int32_t quantity;
|
||||
uint32_t itemid;
|
||||
uint32_t qty;
|
||||
std::string donator;
|
||||
uint8_t permissions;
|
||||
std::string who_for;
|
||||
std::string whofor;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
@@ -45,20 +40,14 @@ public:
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"guild_id",
|
||||
"guildid",
|
||||
"area",
|
||||
"slot",
|
||||
"item_id",
|
||||
"augment_one_id",
|
||||
"augment_two_id",
|
||||
"augment_three_id",
|
||||
"augment_four_id",
|
||||
"augment_five_id",
|
||||
"augment_six_id",
|
||||
"quantity",
|
||||
"itemid",
|
||||
"qty",
|
||||
"donator",
|
||||
"permissions",
|
||||
"who_for",
|
||||
"whofor",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -66,20 +55,14 @@ public:
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"guild_id",
|
||||
"guildid",
|
||||
"area",
|
||||
"slot",
|
||||
"item_id",
|
||||
"augment_one_id",
|
||||
"augment_two_id",
|
||||
"augment_three_id",
|
||||
"augment_four_id",
|
||||
"augment_five_id",
|
||||
"augment_six_id",
|
||||
"quantity",
|
||||
"itemid",
|
||||
"qty",
|
||||
"donator",
|
||||
"permissions",
|
||||
"who_for",
|
||||
"whofor",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -120,21 +103,15 @@ public:
|
||||
{
|
||||
GuildBank e{};
|
||||
|
||||
e.id = 0;
|
||||
e.guild_id = 0;
|
||||
e.area = 0;
|
||||
e.slot = 0;
|
||||
e.item_id = 0;
|
||||
e.augment_one_id = 0;
|
||||
e.augment_two_id = 0;
|
||||
e.augment_three_id = 0;
|
||||
e.augment_four_id = 0;
|
||||
e.augment_five_id = 0;
|
||||
e.augment_six_id = 0;
|
||||
e.quantity = 0;
|
||||
e.donator = "";
|
||||
e.permissions = 0;
|
||||
e.who_for = "";
|
||||
e.id = 0;
|
||||
e.guildid = 0;
|
||||
e.area = 0;
|
||||
e.slot = 0;
|
||||
e.itemid = 0;
|
||||
e.qty = 0;
|
||||
e.donator = "";
|
||||
e.permissions = 0;
|
||||
e.whofor = "";
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -171,21 +148,15 @@ public:
|
||||
if (results.RowCount() == 1) {
|
||||
GuildBank e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.guild_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.area = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.slot = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.item_id = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.augment_one_id = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.augment_two_id = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.augment_three_id = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.augment_four_id = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.augment_five_id = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.augment_six_id = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
|
||||
e.quantity = row[11] ? static_cast<int32_t>(atoi(row[11])) : 0;
|
||||
e.donator = row[12] ? row[12] : "";
|
||||
e.permissions = row[13] ? static_cast<uint8_t>(strtoul(row[13], nullptr, 10)) : 0;
|
||||
e.who_for = row[14] ? row[14] : "";
|
||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.guildid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.area = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
|
||||
e.slot = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
e.itemid = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
|
||||
e.qty = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
|
||||
e.donator = row[6] ? row[6] : "";
|
||||
e.permissions = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
|
||||
e.whofor = row[8] ? row[8] : "";
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -219,20 +190,14 @@ public:
|
||||
|
||||
auto columns = Columns();
|
||||
|
||||
v.push_back(columns[1] + " = " + std::to_string(e.guild_id));
|
||||
v.push_back(columns[1] + " = " + std::to_string(e.guildid));
|
||||
v.push_back(columns[2] + " = " + std::to_string(e.area));
|
||||
v.push_back(columns[3] + " = " + std::to_string(e.slot));
|
||||
v.push_back(columns[4] + " = " + std::to_string(e.item_id));
|
||||
v.push_back(columns[5] + " = " + std::to_string(e.augment_one_id));
|
||||
v.push_back(columns[6] + " = " + std::to_string(e.augment_two_id));
|
||||
v.push_back(columns[7] + " = " + std::to_string(e.augment_three_id));
|
||||
v.push_back(columns[8] + " = " + std::to_string(e.augment_four_id));
|
||||
v.push_back(columns[9] + " = " + std::to_string(e.augment_five_id));
|
||||
v.push_back(columns[10] + " = " + std::to_string(e.augment_six_id));
|
||||
v.push_back(columns[11] + " = " + std::to_string(e.quantity));
|
||||
v.push_back(columns[12] + " = '" + Strings::Escape(e.donator) + "'");
|
||||
v.push_back(columns[13] + " = " + std::to_string(e.permissions));
|
||||
v.push_back(columns[14] + " = '" + Strings::Escape(e.who_for) + "'");
|
||||
v.push_back(columns[4] + " = " + std::to_string(e.itemid));
|
||||
v.push_back(columns[5] + " = " + std::to_string(e.qty));
|
||||
v.push_back(columns[6] + " = '" + Strings::Escape(e.donator) + "'");
|
||||
v.push_back(columns[7] + " = " + std::to_string(e.permissions));
|
||||
v.push_back(columns[8] + " = '" + Strings::Escape(e.whofor) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -255,20 +220,14 @@ public:
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.guild_id));
|
||||
v.push_back(std::to_string(e.guildid));
|
||||
v.push_back(std::to_string(e.area));
|
||||
v.push_back(std::to_string(e.slot));
|
||||
v.push_back(std::to_string(e.item_id));
|
||||
v.push_back(std::to_string(e.augment_one_id));
|
||||
v.push_back(std::to_string(e.augment_two_id));
|
||||
v.push_back(std::to_string(e.augment_three_id));
|
||||
v.push_back(std::to_string(e.augment_four_id));
|
||||
v.push_back(std::to_string(e.augment_five_id));
|
||||
v.push_back(std::to_string(e.augment_six_id));
|
||||
v.push_back(std::to_string(e.quantity));
|
||||
v.push_back(std::to_string(e.itemid));
|
||||
v.push_back(std::to_string(e.qty));
|
||||
v.push_back("'" + Strings::Escape(e.donator) + "'");
|
||||
v.push_back(std::to_string(e.permissions));
|
||||
v.push_back("'" + Strings::Escape(e.who_for) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.whofor) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -299,20 +258,14 @@ public:
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.guild_id));
|
||||
v.push_back(std::to_string(e.guildid));
|
||||
v.push_back(std::to_string(e.area));
|
||||
v.push_back(std::to_string(e.slot));
|
||||
v.push_back(std::to_string(e.item_id));
|
||||
v.push_back(std::to_string(e.augment_one_id));
|
||||
v.push_back(std::to_string(e.augment_two_id));
|
||||
v.push_back(std::to_string(e.augment_three_id));
|
||||
v.push_back(std::to_string(e.augment_four_id));
|
||||
v.push_back(std::to_string(e.augment_five_id));
|
||||
v.push_back(std::to_string(e.augment_six_id));
|
||||
v.push_back(std::to_string(e.quantity));
|
||||
v.push_back(std::to_string(e.itemid));
|
||||
v.push_back(std::to_string(e.qty));
|
||||
v.push_back("'" + Strings::Escape(e.donator) + "'");
|
||||
v.push_back(std::to_string(e.permissions));
|
||||
v.push_back("'" + Strings::Escape(e.who_for) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.whofor) + "'");
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
@@ -346,21 +299,15 @@ public:
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
GuildBank e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.guild_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.area = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.slot = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.item_id = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.augment_one_id = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.augment_two_id = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.augment_three_id = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.augment_four_id = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.augment_five_id = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.augment_six_id = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
|
||||
e.quantity = row[11] ? static_cast<int32_t>(atoi(row[11])) : 0;
|
||||
e.donator = row[12] ? row[12] : "";
|
||||
e.permissions = row[13] ? static_cast<uint8_t>(strtoul(row[13], nullptr, 10)) : 0;
|
||||
e.who_for = row[14] ? row[14] : "";
|
||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.guildid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.area = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
|
||||
e.slot = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
e.itemid = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
|
||||
e.qty = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
|
||||
e.donator = row[6] ? row[6] : "";
|
||||
e.permissions = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
|
||||
e.whofor = row[8] ? row[8] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -385,21 +332,15 @@ public:
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
GuildBank e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.guild_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.area = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.slot = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.item_id = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.augment_one_id = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.augment_two_id = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.augment_three_id = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.augment_four_id = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.augment_five_id = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.augment_six_id = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
|
||||
e.quantity = row[11] ? static_cast<int32_t>(atoi(row[11])) : 0;
|
||||
e.donator = row[12] ? row[12] : "";
|
||||
e.permissions = row[13] ? static_cast<uint8_t>(strtoul(row[13], nullptr, 10)) : 0;
|
||||
e.who_for = row[14] ? row[14] : "";
|
||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.guildid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.area = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
|
||||
e.slot = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
e.itemid = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
|
||||
e.qty = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
|
||||
e.donator = row[6] ? row[6] : "";
|
||||
e.permissions = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
|
||||
e.whofor = row[8] ? row[8] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -458,90 +399,6 @@ public:
|
||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||
}
|
||||
|
||||
static std::string BaseReplace()
|
||||
{
|
||||
return fmt::format(
|
||||
"REPLACE INTO {} ({}) ",
|
||||
TableName(),
|
||||
ColumnsRaw()
|
||||
);
|
||||
}
|
||||
|
||||
static int ReplaceOne(
|
||||
Database& db,
|
||||
const GuildBank &e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.guild_id));
|
||||
v.push_back(std::to_string(e.area));
|
||||
v.push_back(std::to_string(e.slot));
|
||||
v.push_back(std::to_string(e.item_id));
|
||||
v.push_back(std::to_string(e.augment_one_id));
|
||||
v.push_back(std::to_string(e.augment_two_id));
|
||||
v.push_back(std::to_string(e.augment_three_id));
|
||||
v.push_back(std::to_string(e.augment_four_id));
|
||||
v.push_back(std::to_string(e.augment_five_id));
|
||||
v.push_back(std::to_string(e.augment_six_id));
|
||||
v.push_back(std::to_string(e.quantity));
|
||||
v.push_back("'" + Strings::Escape(e.donator) + "'");
|
||||
v.push_back(std::to_string(e.permissions));
|
||||
v.push_back("'" + Strings::Escape(e.who_for) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES ({})",
|
||||
BaseReplace(),
|
||||
Strings::Implode(",", v)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int ReplaceMany(
|
||||
Database& db,
|
||||
const std::vector<GuildBank> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &e: entries) {
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.guild_id));
|
||||
v.push_back(std::to_string(e.area));
|
||||
v.push_back(std::to_string(e.slot));
|
||||
v.push_back(std::to_string(e.item_id));
|
||||
v.push_back(std::to_string(e.augment_one_id));
|
||||
v.push_back(std::to_string(e.augment_two_id));
|
||||
v.push_back(std::to_string(e.augment_three_id));
|
||||
v.push_back(std::to_string(e.augment_four_id));
|
||||
v.push_back(std::to_string(e.augment_five_id));
|
||||
v.push_back(std::to_string(e.augment_six_id));
|
||||
v.push_back(std::to_string(e.quantity));
|
||||
v.push_back("'" + Strings::Escape(e.donator) + "'");
|
||||
v.push_back(std::to_string(e.permissions));
|
||||
v.push_back("'" + Strings::Escape(e.who_for) + "'");
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES {}",
|
||||
BaseReplace(),
|
||||
Strings::Implode(",", insert_chunks)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
};
|
||||
|
||||
#endif //EQEMU_BASE_GUILD_BANK_REPOSITORY_H
|
||||
|
||||
@@ -24,7 +24,6 @@ public:
|
||||
int16_t race;
|
||||
int8_t gender;
|
||||
int8_t texture;
|
||||
int8_t helmtexture;
|
||||
float mountspeed;
|
||||
std::string notes;
|
||||
};
|
||||
@@ -42,7 +41,6 @@ public:
|
||||
"race",
|
||||
"gender",
|
||||
"texture",
|
||||
"helmtexture",
|
||||
"mountspeed",
|
||||
"notes",
|
||||
};
|
||||
@@ -56,7 +54,6 @@ public:
|
||||
"race",
|
||||
"gender",
|
||||
"texture",
|
||||
"helmtexture",
|
||||
"mountspeed",
|
||||
"notes",
|
||||
};
|
||||
@@ -99,14 +96,13 @@ public:
|
||||
{
|
||||
Horses e{};
|
||||
|
||||
e.id = 0;
|
||||
e.filename = "";
|
||||
e.race = 216;
|
||||
e.gender = 0;
|
||||
e.texture = 0;
|
||||
e.helmtexture = -1;
|
||||
e.mountspeed = 0.75;
|
||||
e.notes = "Notes";
|
||||
e.id = 0;
|
||||
e.filename = "";
|
||||
e.race = 216;
|
||||
e.gender = 0;
|
||||
e.texture = 0;
|
||||
e.mountspeed = 0.75;
|
||||
e.notes = "Notes";
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -143,14 +139,13 @@ public:
|
||||
if (results.RowCount() == 1) {
|
||||
Horses e{};
|
||||
|
||||
e.id = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
||||
e.filename = row[1] ? row[1] : "";
|
||||
e.race = row[2] ? static_cast<int16_t>(atoi(row[2])) : 216;
|
||||
e.gender = row[3] ? static_cast<int8_t>(atoi(row[3])) : 0;
|
||||
e.texture = row[4] ? static_cast<int8_t>(atoi(row[4])) : 0;
|
||||
e.helmtexture = row[5] ? static_cast<int8_t>(atoi(row[5])) : -1;
|
||||
e.mountspeed = row[6] ? strtof(row[6], nullptr) : 0.75;
|
||||
e.notes = row[7] ? row[7] : "Notes";
|
||||
e.id = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
||||
e.filename = row[1] ? row[1] : "";
|
||||
e.race = row[2] ? static_cast<int16_t>(atoi(row[2])) : 216;
|
||||
e.gender = row[3] ? static_cast<int8_t>(atoi(row[3])) : 0;
|
||||
e.texture = row[4] ? static_cast<int8_t>(atoi(row[4])) : 0;
|
||||
e.mountspeed = row[5] ? strtof(row[5], nullptr) : 0.75;
|
||||
e.notes = row[6] ? row[6] : "Notes";
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -188,9 +183,8 @@ public:
|
||||
v.push_back(columns[2] + " = " + std::to_string(e.race));
|
||||
v.push_back(columns[3] + " = " + std::to_string(e.gender));
|
||||
v.push_back(columns[4] + " = " + std::to_string(e.texture));
|
||||
v.push_back(columns[5] + " = " + std::to_string(e.helmtexture));
|
||||
v.push_back(columns[6] + " = " + std::to_string(e.mountspeed));
|
||||
v.push_back(columns[7] + " = '" + Strings::Escape(e.notes) + "'");
|
||||
v.push_back(columns[5] + " = " + std::to_string(e.mountspeed));
|
||||
v.push_back(columns[6] + " = '" + Strings::Escape(e.notes) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -217,7 +211,6 @@ public:
|
||||
v.push_back(std::to_string(e.race));
|
||||
v.push_back(std::to_string(e.gender));
|
||||
v.push_back(std::to_string(e.texture));
|
||||
v.push_back(std::to_string(e.helmtexture));
|
||||
v.push_back(std::to_string(e.mountspeed));
|
||||
v.push_back("'" + Strings::Escape(e.notes) + "'");
|
||||
|
||||
@@ -254,7 +247,6 @@ public:
|
||||
v.push_back(std::to_string(e.race));
|
||||
v.push_back(std::to_string(e.gender));
|
||||
v.push_back(std::to_string(e.texture));
|
||||
v.push_back(std::to_string(e.helmtexture));
|
||||
v.push_back(std::to_string(e.mountspeed));
|
||||
v.push_back("'" + Strings::Escape(e.notes) + "'");
|
||||
|
||||
@@ -290,14 +282,13 @@ public:
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
Horses e{};
|
||||
|
||||
e.id = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
||||
e.filename = row[1] ? row[1] : "";
|
||||
e.race = row[2] ? static_cast<int16_t>(atoi(row[2])) : 216;
|
||||
e.gender = row[3] ? static_cast<int8_t>(atoi(row[3])) : 0;
|
||||
e.texture = row[4] ? static_cast<int8_t>(atoi(row[4])) : 0;
|
||||
e.helmtexture = row[5] ? static_cast<int8_t>(atoi(row[5])) : -1;
|
||||
e.mountspeed = row[6] ? strtof(row[6], nullptr) : 0.75;
|
||||
e.notes = row[7] ? row[7] : "Notes";
|
||||
e.id = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
||||
e.filename = row[1] ? row[1] : "";
|
||||
e.race = row[2] ? static_cast<int16_t>(atoi(row[2])) : 216;
|
||||
e.gender = row[3] ? static_cast<int8_t>(atoi(row[3])) : 0;
|
||||
e.texture = row[4] ? static_cast<int8_t>(atoi(row[4])) : 0;
|
||||
e.mountspeed = row[5] ? strtof(row[5], nullptr) : 0.75;
|
||||
e.notes = row[6] ? row[6] : "Notes";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -322,14 +313,13 @@ public:
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
Horses e{};
|
||||
|
||||
e.id = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
||||
e.filename = row[1] ? row[1] : "";
|
||||
e.race = row[2] ? static_cast<int16_t>(atoi(row[2])) : 216;
|
||||
e.gender = row[3] ? static_cast<int8_t>(atoi(row[3])) : 0;
|
||||
e.texture = row[4] ? static_cast<int8_t>(atoi(row[4])) : 0;
|
||||
e.helmtexture = row[5] ? static_cast<int8_t>(atoi(row[5])) : -1;
|
||||
e.mountspeed = row[6] ? strtof(row[6], nullptr) : 0.75;
|
||||
e.notes = row[7] ? row[7] : "Notes";
|
||||
e.id = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
||||
e.filename = row[1] ? row[1] : "";
|
||||
e.race = row[2] ? static_cast<int16_t>(atoi(row[2])) : 216;
|
||||
e.gender = row[3] ? static_cast<int8_t>(atoi(row[3])) : 0;
|
||||
e.texture = row[4] ? static_cast<int8_t>(atoi(row[4])) : 0;
|
||||
e.mountspeed = row[5] ? strtof(row[5], nullptr) : 0.75;
|
||||
e.notes = row[6] ? row[6] : "Notes";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -409,7 +399,6 @@ public:
|
||||
v.push_back(std::to_string(e.race));
|
||||
v.push_back(std::to_string(e.gender));
|
||||
v.push_back(std::to_string(e.texture));
|
||||
v.push_back(std::to_string(e.helmtexture));
|
||||
v.push_back(std::to_string(e.mountspeed));
|
||||
v.push_back("'" + Strings::Escape(e.notes) + "'");
|
||||
|
||||
@@ -439,7 +428,6 @@ public:
|
||||
v.push_back(std::to_string(e.race));
|
||||
v.push_back(std::to_string(e.gender));
|
||||
v.push_back(std::to_string(e.texture));
|
||||
v.push_back(std::to_string(e.helmtexture));
|
||||
v.push_back(std::to_string(e.mountspeed));
|
||||
v.push_back("'" + Strings::Escape(e.notes) + "'");
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ public:
|
||||
uint8_t is_global;
|
||||
uint32_t start_time;
|
||||
uint32_t duration;
|
||||
uint64_t expire_at;
|
||||
uint8_t never_expires;
|
||||
std::string notes;
|
||||
};
|
||||
@@ -44,7 +43,6 @@ public:
|
||||
"is_global",
|
||||
"start_time",
|
||||
"duration",
|
||||
"expire_at",
|
||||
"never_expires",
|
||||
"notes",
|
||||
};
|
||||
@@ -59,7 +57,6 @@ public:
|
||||
"is_global",
|
||||
"start_time",
|
||||
"duration",
|
||||
"expire_at",
|
||||
"never_expires",
|
||||
"notes",
|
||||
};
|
||||
@@ -108,7 +105,6 @@ public:
|
||||
e.is_global = 0;
|
||||
e.start_time = 0;
|
||||
e.duration = 0;
|
||||
e.expire_at = 0;
|
||||
e.never_expires = 0;
|
||||
e.notes = "";
|
||||
|
||||
@@ -153,9 +149,8 @@ public:
|
||||
e.is_global = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.start_time = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.duration = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.expire_at = row[6] ? strtoull(row[6], nullptr, 10) : 0;
|
||||
e.never_expires = row[7] ? static_cast<uint8_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.notes = row[8] ? row[8] : "";
|
||||
e.never_expires = row[6] ? static_cast<uint8_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.notes = row[7] ? row[7] : "";
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -194,9 +189,8 @@ public:
|
||||
v.push_back(columns[3] + " = " + std::to_string(e.is_global));
|
||||
v.push_back(columns[4] + " = " + std::to_string(e.start_time));
|
||||
v.push_back(columns[5] + " = " + std::to_string(e.duration));
|
||||
v.push_back(columns[6] + " = " + std::to_string(e.expire_at));
|
||||
v.push_back(columns[7] + " = " + std::to_string(e.never_expires));
|
||||
v.push_back(columns[8] + " = '" + Strings::Escape(e.notes) + "'");
|
||||
v.push_back(columns[6] + " = " + std::to_string(e.never_expires));
|
||||
v.push_back(columns[7] + " = '" + Strings::Escape(e.notes) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -224,7 +218,6 @@ public:
|
||||
v.push_back(std::to_string(e.is_global));
|
||||
v.push_back(std::to_string(e.start_time));
|
||||
v.push_back(std::to_string(e.duration));
|
||||
v.push_back(std::to_string(e.expire_at));
|
||||
v.push_back(std::to_string(e.never_expires));
|
||||
v.push_back("'" + Strings::Escape(e.notes) + "'");
|
||||
|
||||
@@ -262,7 +255,6 @@ public:
|
||||
v.push_back(std::to_string(e.is_global));
|
||||
v.push_back(std::to_string(e.start_time));
|
||||
v.push_back(std::to_string(e.duration));
|
||||
v.push_back(std::to_string(e.expire_at));
|
||||
v.push_back(std::to_string(e.never_expires));
|
||||
v.push_back("'" + Strings::Escape(e.notes) + "'");
|
||||
|
||||
@@ -304,9 +296,8 @@ public:
|
||||
e.is_global = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.start_time = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.duration = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.expire_at = row[6] ? strtoull(row[6], nullptr, 10) : 0;
|
||||
e.never_expires = row[7] ? static_cast<uint8_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.notes = row[8] ? row[8] : "";
|
||||
e.never_expires = row[6] ? static_cast<uint8_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.notes = row[7] ? row[7] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -337,9 +328,8 @@ public:
|
||||
e.is_global = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.start_time = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.duration = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.expire_at = row[6] ? strtoull(row[6], nullptr, 10) : 0;
|
||||
e.never_expires = row[7] ? static_cast<uint8_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.notes = row[8] ? row[8] : "";
|
||||
e.never_expires = row[6] ? static_cast<uint8_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.notes = row[7] ? row[7] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -420,7 +410,6 @@ public:
|
||||
v.push_back(std::to_string(e.is_global));
|
||||
v.push_back(std::to_string(e.start_time));
|
||||
v.push_back(std::to_string(e.duration));
|
||||
v.push_back(std::to_string(e.expire_at));
|
||||
v.push_back(std::to_string(e.never_expires));
|
||||
v.push_back("'" + Strings::Escape(e.notes) + "'");
|
||||
|
||||
@@ -451,7 +440,6 @@ public:
|
||||
v.push_back(std::to_string(e.is_global));
|
||||
v.push_back(std::to_string(e.start_time));
|
||||
v.push_back(std::to_string(e.duration));
|
||||
v.push_back(std::to_string(e.expire_at));
|
||||
v.push_back(std::to_string(e.never_expires));
|
||||
v.push_back("'" + Strings::Escape(e.notes) + "'");
|
||||
|
||||
|
||||
@@ -19,13 +19,13 @@
|
||||
class BaseItemsEvolvingDetailsRepository {
|
||||
public:
|
||||
struct ItemsEvolvingDetails {
|
||||
uint32_t id;
|
||||
uint32_t item_evo_id;
|
||||
uint32_t item_evolve_level;
|
||||
uint32_t item_id;
|
||||
uint32_t type;
|
||||
std::string sub_type;
|
||||
int64_t required_amount;
|
||||
uint32_t id;
|
||||
uint32_t item_evo_id;
|
||||
uint32_t item_evolve_level;
|
||||
uint32_t item_id;
|
||||
uint32_t type;
|
||||
uint32_t sub_type;
|
||||
int64_t required_amount;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
@@ -101,7 +101,7 @@ public:
|
||||
e.item_evolve_level = 0;
|
||||
e.item_id = 0;
|
||||
e.type = 0;
|
||||
e.sub_type = "0";
|
||||
e.sub_type = 0;
|
||||
e.required_amount = 0;
|
||||
|
||||
return e;
|
||||
@@ -144,7 +144,7 @@ public:
|
||||
e.item_evolve_level = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.item_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.type = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.sub_type = row[5] ? row[5] : "0";
|
||||
e.sub_type = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.required_amount = row[6] ? strtoll(row[6], nullptr, 10) : 0;
|
||||
|
||||
return e;
|
||||
@@ -183,7 +183,7 @@ public:
|
||||
v.push_back(columns[2] + " = " + std::to_string(e.item_evolve_level));
|
||||
v.push_back(columns[3] + " = " + std::to_string(e.item_id));
|
||||
v.push_back(columns[4] + " = " + std::to_string(e.type));
|
||||
v.push_back(columns[5] + " = '" + Strings::Escape(e.sub_type) + "'");
|
||||
v.push_back(columns[5] + " = " + std::to_string(e.sub_type));
|
||||
v.push_back(columns[6] + " = " + std::to_string(e.required_amount));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
@@ -211,7 +211,7 @@ public:
|
||||
v.push_back(std::to_string(e.item_evolve_level));
|
||||
v.push_back(std::to_string(e.item_id));
|
||||
v.push_back(std::to_string(e.type));
|
||||
v.push_back("'" + Strings::Escape(e.sub_type) + "'");
|
||||
v.push_back(std::to_string(e.sub_type));
|
||||
v.push_back(std::to_string(e.required_amount));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
@@ -247,7 +247,7 @@ public:
|
||||
v.push_back(std::to_string(e.item_evolve_level));
|
||||
v.push_back(std::to_string(e.item_id));
|
||||
v.push_back(std::to_string(e.type));
|
||||
v.push_back("'" + Strings::Escape(e.sub_type) + "'");
|
||||
v.push_back(std::to_string(e.sub_type));
|
||||
v.push_back(std::to_string(e.required_amount));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
@@ -287,7 +287,7 @@ public:
|
||||
e.item_evolve_level = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.item_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.type = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.sub_type = row[5] ? row[5] : "0";
|
||||
e.sub_type = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.required_amount = row[6] ? strtoll(row[6], nullptr, 10) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
@@ -318,7 +318,7 @@ public:
|
||||
e.item_evolve_level = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.item_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.type = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.sub_type = row[5] ? row[5] : "0";
|
||||
e.sub_type = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.required_amount = row[6] ? strtoll(row[6], nullptr, 10) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
@@ -399,7 +399,7 @@ public:
|
||||
v.push_back(std::to_string(e.item_evolve_level));
|
||||
v.push_back(std::to_string(e.item_id));
|
||||
v.push_back(std::to_string(e.type));
|
||||
v.push_back("'" + Strings::Escape(e.sub_type) + "'");
|
||||
v.push_back(std::to_string(e.sub_type));
|
||||
v.push_back(std::to_string(e.required_amount));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
@@ -428,7 +428,7 @@ public:
|
||||
v.push_back(std::to_string(e.item_evolve_level));
|
||||
v.push_back(std::to_string(e.item_id));
|
||||
v.push_back(std::to_string(e.type));
|
||||
v.push_back("'" + Strings::Escape(e.sub_type) + "'");
|
||||
v.push_back(std::to_string(e.sub_type));
|
||||
v.push_back(std::to_string(e.required_amount));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
|
||||
@@ -149,7 +149,6 @@ public:
|
||||
uint8_t keeps_sold_items;
|
||||
uint8_t is_parcel_merchant;
|
||||
uint8_t multiquest_enabled;
|
||||
uint16_t npc_tint_id;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
@@ -290,7 +289,6 @@ public:
|
||||
"keeps_sold_items",
|
||||
"is_parcel_merchant",
|
||||
"multiquest_enabled",
|
||||
"npc_tint_id",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -427,7 +425,6 @@ public:
|
||||
"keeps_sold_items",
|
||||
"is_parcel_merchant",
|
||||
"multiquest_enabled",
|
||||
"npc_tint_id",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -598,7 +595,6 @@ public:
|
||||
e.keeps_sold_items = 1;
|
||||
e.is_parcel_merchant = 0;
|
||||
e.multiquest_enabled = 0;
|
||||
e.npc_tint_id = 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -765,7 +761,6 @@ public:
|
||||
e.keeps_sold_items = row[127] ? static_cast<uint8_t>(strtoul(row[127], nullptr, 10)) : 1;
|
||||
e.is_parcel_merchant = row[128] ? static_cast<uint8_t>(strtoul(row[128], nullptr, 10)) : 0;
|
||||
e.multiquest_enabled = row[129] ? static_cast<uint8_t>(strtoul(row[129], nullptr, 10)) : 0;
|
||||
e.npc_tint_id = row[130] ? static_cast<uint16_t>(strtoul(row[130], nullptr, 10)) : 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -928,7 +923,6 @@ public:
|
||||
v.push_back(columns[127] + " = " + std::to_string(e.keeps_sold_items));
|
||||
v.push_back(columns[128] + " = " + std::to_string(e.is_parcel_merchant));
|
||||
v.push_back(columns[129] + " = " + std::to_string(e.multiquest_enabled));
|
||||
v.push_back(columns[130] + " = " + std::to_string(e.npc_tint_id));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -1080,7 +1074,6 @@ public:
|
||||
v.push_back(std::to_string(e.keeps_sold_items));
|
||||
v.push_back(std::to_string(e.is_parcel_merchant));
|
||||
v.push_back(std::to_string(e.multiquest_enabled));
|
||||
v.push_back(std::to_string(e.npc_tint_id));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -1240,7 +1233,6 @@ public:
|
||||
v.push_back(std::to_string(e.keeps_sold_items));
|
||||
v.push_back(std::to_string(e.is_parcel_merchant));
|
||||
v.push_back(std::to_string(e.multiquest_enabled));
|
||||
v.push_back(std::to_string(e.npc_tint_id));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
@@ -1404,7 +1396,6 @@ public:
|
||||
e.keeps_sold_items = row[127] ? static_cast<uint8_t>(strtoul(row[127], nullptr, 10)) : 1;
|
||||
e.is_parcel_merchant = row[128] ? static_cast<uint8_t>(strtoul(row[128], nullptr, 10)) : 0;
|
||||
e.multiquest_enabled = row[129] ? static_cast<uint8_t>(strtoul(row[129], nullptr, 10)) : 0;
|
||||
e.npc_tint_id = row[130] ? static_cast<uint16_t>(strtoul(row[130], nullptr, 10)) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -1559,7 +1550,6 @@ public:
|
||||
e.keeps_sold_items = row[127] ? static_cast<uint8_t>(strtoul(row[127], nullptr, 10)) : 1;
|
||||
e.is_parcel_merchant = row[128] ? static_cast<uint8_t>(strtoul(row[128], nullptr, 10)) : 0;
|
||||
e.multiquest_enabled = row[129] ? static_cast<uint8_t>(strtoul(row[129], nullptr, 10)) : 0;
|
||||
e.npc_tint_id = row[130] ? static_cast<uint16_t>(strtoul(row[130], nullptr, 10)) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -1764,7 +1754,6 @@ public:
|
||||
v.push_back(std::to_string(e.keeps_sold_items));
|
||||
v.push_back(std::to_string(e.is_parcel_merchant));
|
||||
v.push_back(std::to_string(e.multiquest_enabled));
|
||||
v.push_back(std::to_string(e.npc_tint_id));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -1917,7 +1906,6 @@ public:
|
||||
v.push_back(std::to_string(e.keeps_sold_items));
|
||||
v.push_back(std::to_string(e.is_parcel_merchant));
|
||||
v.push_back(std::to_string(e.multiquest_enabled));
|
||||
v.push_back(std::to_string(e.npc_tint_id));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "../../database.h"
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
#include <cereal/cereal.hpp>
|
||||
|
||||
class BasePlayerEventLogSettingsRepository {
|
||||
public:
|
||||
struct PlayerEventLogSettings {
|
||||
@@ -25,20 +25,6 @@ public:
|
||||
int32_t retention_days;
|
||||
int32_t discord_webhook_id;
|
||||
uint8_t etl_enabled;
|
||||
|
||||
// cereal
|
||||
template<class Archive>
|
||||
void serialize(Archive &ar)
|
||||
{
|
||||
ar(
|
||||
CEREAL_NVP(id),
|
||||
CEREAL_NVP(event_name),
|
||||
CEREAL_NVP(event_enabled),
|
||||
CEREAL_NVP(retention_days),
|
||||
CEREAL_NVP(discord_webhook_id),
|
||||
CEREAL_NVP(etl_enabled)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
|
||||
@@ -19,11 +19,10 @@
|
||||
class BaseRespawnTimesRepository {
|
||||
public:
|
||||
struct RespawnTimes {
|
||||
int32_t id;
|
||||
int32_t start;
|
||||
int32_t duration;
|
||||
uint32_t expire_at;
|
||||
int16_t instance_id;
|
||||
int32_t id;
|
||||
int32_t start;
|
||||
int32_t duration;
|
||||
int16_t instance_id;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
@@ -37,7 +36,6 @@ public:
|
||||
"id",
|
||||
"start",
|
||||
"duration",
|
||||
"expire_at",
|
||||
"instance_id",
|
||||
};
|
||||
}
|
||||
@@ -48,7 +46,6 @@ public:
|
||||
"id",
|
||||
"start",
|
||||
"duration",
|
||||
"expire_at",
|
||||
"instance_id",
|
||||
};
|
||||
}
|
||||
@@ -93,7 +90,6 @@ public:
|
||||
e.id = 0;
|
||||
e.start = 0;
|
||||
e.duration = 0;
|
||||
e.expire_at = 0;
|
||||
e.instance_id = 0;
|
||||
|
||||
return e;
|
||||
@@ -134,8 +130,7 @@ public:
|
||||
e.id = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
||||
e.start = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
|
||||
e.duration = row[2] ? static_cast<int32_t>(atoi(row[2])) : 0;
|
||||
e.expire_at = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.instance_id = row[4] ? static_cast<int16_t>(atoi(row[4])) : 0;
|
||||
e.instance_id = row[3] ? static_cast<int16_t>(atoi(row[3])) : 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -172,8 +167,7 @@ public:
|
||||
v.push_back(columns[0] + " = " + std::to_string(e.id));
|
||||
v.push_back(columns[1] + " = " + std::to_string(e.start));
|
||||
v.push_back(columns[2] + " = " + std::to_string(e.duration));
|
||||
v.push_back(columns[3] + " = " + std::to_string(e.expire_at));
|
||||
v.push_back(columns[4] + " = " + std::to_string(e.instance_id));
|
||||
v.push_back(columns[3] + " = " + std::to_string(e.instance_id));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -198,7 +192,6 @@ public:
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.start));
|
||||
v.push_back(std::to_string(e.duration));
|
||||
v.push_back(std::to_string(e.expire_at));
|
||||
v.push_back(std::to_string(e.instance_id));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
@@ -232,7 +225,6 @@ public:
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.start));
|
||||
v.push_back(std::to_string(e.duration));
|
||||
v.push_back(std::to_string(e.expire_at));
|
||||
v.push_back(std::to_string(e.instance_id));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
@@ -270,8 +262,7 @@ public:
|
||||
e.id = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
||||
e.start = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
|
||||
e.duration = row[2] ? static_cast<int32_t>(atoi(row[2])) : 0;
|
||||
e.expire_at = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.instance_id = row[4] ? static_cast<int16_t>(atoi(row[4])) : 0;
|
||||
e.instance_id = row[3] ? static_cast<int16_t>(atoi(row[3])) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -299,8 +290,7 @@ public:
|
||||
e.id = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
||||
e.start = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
|
||||
e.duration = row[2] ? static_cast<int32_t>(atoi(row[2])) : 0;
|
||||
e.expire_at = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.instance_id = row[4] ? static_cast<int16_t>(atoi(row[4])) : 0;
|
||||
e.instance_id = row[3] ? static_cast<int16_t>(atoi(row[3])) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -378,7 +368,6 @@ public:
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.start));
|
||||
v.push_back(std::to_string(e.duration));
|
||||
v.push_back(std::to_string(e.expire_at));
|
||||
v.push_back(std::to_string(e.instance_id));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
@@ -405,7 +394,6 @@ public:
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.start));
|
||||
v.push_back(std::to_string(e.duration));
|
||||
v.push_back(std::to_string(e.expire_at));
|
||||
v.push_back(std::to_string(e.instance_id));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
|
||||
@@ -1,715 +0,0 @@
|
||||
/**
|
||||
* DO NOT MODIFY THIS FILE
|
||||
*
|
||||
* This repository was automatically generated and is NOT to be modified directly.
|
||||
* Any repository modifications are meant to be made to the repository extending the base.
|
||||
* Any modifications to base repositories are to be made by the generator only
|
||||
*
|
||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||
* @docs https://docs.eqemu.io/developer/repositories
|
||||
*/
|
||||
|
||||
#ifndef EQEMU_BASE_ZONE_STATE_SPAWNS_REPOSITORY_H
|
||||
#define EQEMU_BASE_ZONE_STATE_SPAWNS_REPOSITORY_H
|
||||
|
||||
#include "../../database.h"
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
class BaseZoneStateSpawnsRepository {
|
||||
public:
|
||||
struct ZoneStateSpawns {
|
||||
int64_t id;
|
||||
uint32_t zone_id;
|
||||
uint32_t instance_id;
|
||||
int8_t is_corpse;
|
||||
int8_t is_zone;
|
||||
int32_t decay_in_seconds;
|
||||
uint32_t npc_id;
|
||||
uint32_t spawn2_id;
|
||||
uint32_t spawngroup_id;
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float heading;
|
||||
uint32_t respawn_time;
|
||||
uint32_t variance;
|
||||
uint32_t grid;
|
||||
int32_t current_waypoint;
|
||||
int16_t path_when_zone_idle;
|
||||
uint16_t condition_id;
|
||||
int16_t condition_min_value;
|
||||
int16_t enabled;
|
||||
uint16_t anim;
|
||||
std::string loot_data;
|
||||
std::string entity_variables;
|
||||
std::string buffs;
|
||||
int64_t hp;
|
||||
int64_t mana;
|
||||
int64_t endurance;
|
||||
time_t created_at;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
{
|
||||
return std::string("id");
|
||||
}
|
||||
|
||||
static std::vector<std::string> Columns()
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"zone_id",
|
||||
"instance_id",
|
||||
"is_corpse",
|
||||
"is_zone",
|
||||
"decay_in_seconds",
|
||||
"npc_id",
|
||||
"spawn2_id",
|
||||
"spawngroup_id",
|
||||
"x",
|
||||
"y",
|
||||
"z",
|
||||
"heading",
|
||||
"respawn_time",
|
||||
"variance",
|
||||
"grid",
|
||||
"current_waypoint",
|
||||
"path_when_zone_idle",
|
||||
"condition_id",
|
||||
"condition_min_value",
|
||||
"enabled",
|
||||
"anim",
|
||||
"loot_data",
|
||||
"entity_variables",
|
||||
"buffs",
|
||||
"hp",
|
||||
"mana",
|
||||
"endurance",
|
||||
"created_at",
|
||||
};
|
||||
}
|
||||
|
||||
static std::vector<std::string> SelectColumns()
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"zone_id",
|
||||
"instance_id",
|
||||
"is_corpse",
|
||||
"is_zone",
|
||||
"decay_in_seconds",
|
||||
"npc_id",
|
||||
"spawn2_id",
|
||||
"spawngroup_id",
|
||||
"x",
|
||||
"y",
|
||||
"z",
|
||||
"heading",
|
||||
"respawn_time",
|
||||
"variance",
|
||||
"grid",
|
||||
"current_waypoint",
|
||||
"path_when_zone_idle",
|
||||
"condition_id",
|
||||
"condition_min_value",
|
||||
"enabled",
|
||||
"anim",
|
||||
"loot_data",
|
||||
"entity_variables",
|
||||
"buffs",
|
||||
"hp",
|
||||
"mana",
|
||||
"endurance",
|
||||
"UNIX_TIMESTAMP(created_at)",
|
||||
};
|
||||
}
|
||||
|
||||
static std::string ColumnsRaw()
|
||||
{
|
||||
return std::string(Strings::Implode(", ", Columns()));
|
||||
}
|
||||
|
||||
static std::string SelectColumnsRaw()
|
||||
{
|
||||
return std::string(Strings::Implode(", ", SelectColumns()));
|
||||
}
|
||||
|
||||
static std::string TableName()
|
||||
{
|
||||
return std::string("zone_state_spawns");
|
||||
}
|
||||
|
||||
static std::string BaseSelect()
|
||||
{
|
||||
return fmt::format(
|
||||
"SELECT {} FROM {}",
|
||||
SelectColumnsRaw(),
|
||||
TableName()
|
||||
);
|
||||
}
|
||||
|
||||
static std::string BaseInsert()
|
||||
{
|
||||
return fmt::format(
|
||||
"INSERT INTO {} ({}) ",
|
||||
TableName(),
|
||||
ColumnsRaw()
|
||||
);
|
||||
}
|
||||
|
||||
static ZoneStateSpawns NewEntity()
|
||||
{
|
||||
ZoneStateSpawns e{};
|
||||
|
||||
e.id = 0;
|
||||
e.zone_id = 0;
|
||||
e.instance_id = 0;
|
||||
e.is_corpse = 0;
|
||||
e.is_zone = 0;
|
||||
e.decay_in_seconds = 0;
|
||||
e.npc_id = 0;
|
||||
e.spawn2_id = 0;
|
||||
e.spawngroup_id = 0;
|
||||
e.x = 0;
|
||||
e.y = 0;
|
||||
e.z = 0;
|
||||
e.heading = 0;
|
||||
e.respawn_time = 0;
|
||||
e.variance = 0;
|
||||
e.grid = 0;
|
||||
e.current_waypoint = 0;
|
||||
e.path_when_zone_idle = 0;
|
||||
e.condition_id = 0;
|
||||
e.condition_min_value = 0;
|
||||
e.enabled = 1;
|
||||
e.anim = 0;
|
||||
e.loot_data = "";
|
||||
e.entity_variables = "";
|
||||
e.buffs = "";
|
||||
e.hp = 0;
|
||||
e.mana = 0;
|
||||
e.endurance = 0;
|
||||
e.created_at = 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static ZoneStateSpawns GetZoneStateSpawns(
|
||||
const std::vector<ZoneStateSpawns> &zone_state_spawnss,
|
||||
int zone_state_spawns_id
|
||||
)
|
||||
{
|
||||
for (auto &zone_state_spawns : zone_state_spawnss) {
|
||||
if (zone_state_spawns.id == zone_state_spawns_id) {
|
||||
return zone_state_spawns;
|
||||
}
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static ZoneStateSpawns FindOne(
|
||||
Database& db,
|
||||
int zone_state_spawns_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
zone_state_spawns_id
|
||||
)
|
||||
);
|
||||
|
||||
auto row = results.begin();
|
||||
if (results.RowCount() == 1) {
|
||||
ZoneStateSpawns e{};
|
||||
|
||||
e.id = row[0] ? strtoll(row[0], nullptr, 10) : 0;
|
||||
e.zone_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.instance_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.is_corpse = row[3] ? static_cast<int8_t>(atoi(row[3])) : 0;
|
||||
e.is_zone = row[4] ? static_cast<int8_t>(atoi(row[4])) : 0;
|
||||
e.decay_in_seconds = row[5] ? static_cast<int32_t>(atoi(row[5])) : 0;
|
||||
e.npc_id = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.spawn2_id = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.spawngroup_id = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.x = row[9] ? strtof(row[9], nullptr) : 0;
|
||||
e.y = row[10] ? strtof(row[10], nullptr) : 0;
|
||||
e.z = row[11] ? strtof(row[11], nullptr) : 0;
|
||||
e.heading = row[12] ? strtof(row[12], nullptr) : 0;
|
||||
e.respawn_time = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
|
||||
e.variance = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
||||
e.grid = row[15] ? static_cast<uint32_t>(strtoul(row[15], nullptr, 10)) : 0;
|
||||
e.current_waypoint = row[16] ? static_cast<int32_t>(atoi(row[16])) : 0;
|
||||
e.path_when_zone_idle = row[17] ? static_cast<int16_t>(atoi(row[17])) : 0;
|
||||
e.condition_id = row[18] ? static_cast<uint16_t>(strtoul(row[18], nullptr, 10)) : 0;
|
||||
e.condition_min_value = row[19] ? static_cast<int16_t>(atoi(row[19])) : 0;
|
||||
e.enabled = row[20] ? static_cast<int16_t>(atoi(row[20])) : 1;
|
||||
e.anim = row[21] ? static_cast<uint16_t>(strtoul(row[21], nullptr, 10)) : 0;
|
||||
e.loot_data = row[22] ? row[22] : "";
|
||||
e.entity_variables = row[23] ? row[23] : "";
|
||||
e.buffs = row[24] ? row[24] : "";
|
||||
e.hp = row[25] ? strtoll(row[25], nullptr, 10) : 0;
|
||||
e.mana = row[26] ? strtoll(row[26], nullptr, 10) : 0;
|
||||
e.endurance = row[27] ? strtoll(row[27], nullptr, 10) : 0;
|
||||
e.created_at = strtoll(row[28] ? row[28] : "-1", nullptr, 10);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static int DeleteOne(
|
||||
Database& db,
|
||||
int zone_state_spawns_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"DELETE FROM {} WHERE {} = {}",
|
||||
TableName(),
|
||||
PrimaryKey(),
|
||||
zone_state_spawns_id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int UpdateOne(
|
||||
Database& db,
|
||||
const ZoneStateSpawns &e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto columns = Columns();
|
||||
|
||||
v.push_back(columns[1] + " = " + std::to_string(e.zone_id));
|
||||
v.push_back(columns[2] + " = " + std::to_string(e.instance_id));
|
||||
v.push_back(columns[3] + " = " + std::to_string(e.is_corpse));
|
||||
v.push_back(columns[4] + " = " + std::to_string(e.is_zone));
|
||||
v.push_back(columns[5] + " = " + std::to_string(e.decay_in_seconds));
|
||||
v.push_back(columns[6] + " = " + std::to_string(e.npc_id));
|
||||
v.push_back(columns[7] + " = " + std::to_string(e.spawn2_id));
|
||||
v.push_back(columns[8] + " = " + std::to_string(e.spawngroup_id));
|
||||
v.push_back(columns[9] + " = " + std::to_string(e.x));
|
||||
v.push_back(columns[10] + " = " + std::to_string(e.y));
|
||||
v.push_back(columns[11] + " = " + std::to_string(e.z));
|
||||
v.push_back(columns[12] + " = " + std::to_string(e.heading));
|
||||
v.push_back(columns[13] + " = " + std::to_string(e.respawn_time));
|
||||
v.push_back(columns[14] + " = " + std::to_string(e.variance));
|
||||
v.push_back(columns[15] + " = " + std::to_string(e.grid));
|
||||
v.push_back(columns[16] + " = " + std::to_string(e.current_waypoint));
|
||||
v.push_back(columns[17] + " = " + std::to_string(e.path_when_zone_idle));
|
||||
v.push_back(columns[18] + " = " + std::to_string(e.condition_id));
|
||||
v.push_back(columns[19] + " = " + std::to_string(e.condition_min_value));
|
||||
v.push_back(columns[20] + " = " + std::to_string(e.enabled));
|
||||
v.push_back(columns[21] + " = " + std::to_string(e.anim));
|
||||
v.push_back(columns[22] + " = '" + Strings::Escape(e.loot_data) + "'");
|
||||
v.push_back(columns[23] + " = '" + Strings::Escape(e.entity_variables) + "'");
|
||||
v.push_back(columns[24] + " = '" + Strings::Escape(e.buffs) + "'");
|
||||
v.push_back(columns[25] + " = " + std::to_string(e.hp));
|
||||
v.push_back(columns[26] + " = " + std::to_string(e.mana));
|
||||
v.push_back(columns[27] + " = " + std::to_string(e.endurance));
|
||||
v.push_back(columns[28] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"UPDATE {} SET {} WHERE {} = {}",
|
||||
TableName(),
|
||||
Strings::Implode(", ", v),
|
||||
PrimaryKey(),
|
||||
e.id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static ZoneStateSpawns InsertOne(
|
||||
Database& db,
|
||||
ZoneStateSpawns e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.zone_id));
|
||||
v.push_back(std::to_string(e.instance_id));
|
||||
v.push_back(std::to_string(e.is_corpse));
|
||||
v.push_back(std::to_string(e.is_zone));
|
||||
v.push_back(std::to_string(e.decay_in_seconds));
|
||||
v.push_back(std::to_string(e.npc_id));
|
||||
v.push_back(std::to_string(e.spawn2_id));
|
||||
v.push_back(std::to_string(e.spawngroup_id));
|
||||
v.push_back(std::to_string(e.x));
|
||||
v.push_back(std::to_string(e.y));
|
||||
v.push_back(std::to_string(e.z));
|
||||
v.push_back(std::to_string(e.heading));
|
||||
v.push_back(std::to_string(e.respawn_time));
|
||||
v.push_back(std::to_string(e.variance));
|
||||
v.push_back(std::to_string(e.grid));
|
||||
v.push_back(std::to_string(e.current_waypoint));
|
||||
v.push_back(std::to_string(e.path_when_zone_idle));
|
||||
v.push_back(std::to_string(e.condition_id));
|
||||
v.push_back(std::to_string(e.condition_min_value));
|
||||
v.push_back(std::to_string(e.enabled));
|
||||
v.push_back(std::to_string(e.anim));
|
||||
v.push_back("'" + Strings::Escape(e.loot_data) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.entity_variables) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.buffs) + "'");
|
||||
v.push_back(std::to_string(e.hp));
|
||||
v.push_back(std::to_string(e.mana));
|
||||
v.push_back(std::to_string(e.endurance));
|
||||
v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES ({})",
|
||||
BaseInsert(),
|
||||
Strings::Implode(",", v)
|
||||
)
|
||||
);
|
||||
|
||||
if (results.Success()) {
|
||||
e.id = results.LastInsertedID();
|
||||
return e;
|
||||
}
|
||||
|
||||
e = NewEntity();
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static int InsertMany(
|
||||
Database& db,
|
||||
const std::vector<ZoneStateSpawns> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &e: entries) {
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.zone_id));
|
||||
v.push_back(std::to_string(e.instance_id));
|
||||
v.push_back(std::to_string(e.is_corpse));
|
||||
v.push_back(std::to_string(e.is_zone));
|
||||
v.push_back(std::to_string(e.decay_in_seconds));
|
||||
v.push_back(std::to_string(e.npc_id));
|
||||
v.push_back(std::to_string(e.spawn2_id));
|
||||
v.push_back(std::to_string(e.spawngroup_id));
|
||||
v.push_back(std::to_string(e.x));
|
||||
v.push_back(std::to_string(e.y));
|
||||
v.push_back(std::to_string(e.z));
|
||||
v.push_back(std::to_string(e.heading));
|
||||
v.push_back(std::to_string(e.respawn_time));
|
||||
v.push_back(std::to_string(e.variance));
|
||||
v.push_back(std::to_string(e.grid));
|
||||
v.push_back(std::to_string(e.current_waypoint));
|
||||
v.push_back(std::to_string(e.path_when_zone_idle));
|
||||
v.push_back(std::to_string(e.condition_id));
|
||||
v.push_back(std::to_string(e.condition_min_value));
|
||||
v.push_back(std::to_string(e.enabled));
|
||||
v.push_back(std::to_string(e.anim));
|
||||
v.push_back("'" + Strings::Escape(e.loot_data) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.entity_variables) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.buffs) + "'");
|
||||
v.push_back(std::to_string(e.hp));
|
||||
v.push_back(std::to_string(e.mana));
|
||||
v.push_back(std::to_string(e.endurance));
|
||||
v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")");
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES {}",
|
||||
BaseInsert(),
|
||||
Strings::Implode(",", insert_chunks)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static std::vector<ZoneStateSpawns> All(Database& db)
|
||||
{
|
||||
std::vector<ZoneStateSpawns> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{}",
|
||||
BaseSelect()
|
||||
)
|
||||
);
|
||||
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
ZoneStateSpawns e{};
|
||||
|
||||
e.id = row[0] ? strtoll(row[0], nullptr, 10) : 0;
|
||||
e.zone_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.instance_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.is_corpse = row[3] ? static_cast<int8_t>(atoi(row[3])) : 0;
|
||||
e.is_zone = row[4] ? static_cast<int8_t>(atoi(row[4])) : 0;
|
||||
e.decay_in_seconds = row[5] ? static_cast<int32_t>(atoi(row[5])) : 0;
|
||||
e.npc_id = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.spawn2_id = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.spawngroup_id = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.x = row[9] ? strtof(row[9], nullptr) : 0;
|
||||
e.y = row[10] ? strtof(row[10], nullptr) : 0;
|
||||
e.z = row[11] ? strtof(row[11], nullptr) : 0;
|
||||
e.heading = row[12] ? strtof(row[12], nullptr) : 0;
|
||||
e.respawn_time = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
|
||||
e.variance = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
||||
e.grid = row[15] ? static_cast<uint32_t>(strtoul(row[15], nullptr, 10)) : 0;
|
||||
e.current_waypoint = row[16] ? static_cast<int32_t>(atoi(row[16])) : 0;
|
||||
e.path_when_zone_idle = row[17] ? static_cast<int16_t>(atoi(row[17])) : 0;
|
||||
e.condition_id = row[18] ? static_cast<uint16_t>(strtoul(row[18], nullptr, 10)) : 0;
|
||||
e.condition_min_value = row[19] ? static_cast<int16_t>(atoi(row[19])) : 0;
|
||||
e.enabled = row[20] ? static_cast<int16_t>(atoi(row[20])) : 1;
|
||||
e.anim = row[21] ? static_cast<uint16_t>(strtoul(row[21], nullptr, 10)) : 0;
|
||||
e.loot_data = row[22] ? row[22] : "";
|
||||
e.entity_variables = row[23] ? row[23] : "";
|
||||
e.buffs = row[24] ? row[24] : "";
|
||||
e.hp = row[25] ? strtoll(row[25], nullptr, 10) : 0;
|
||||
e.mana = row[26] ? strtoll(row[26], nullptr, 10) : 0;
|
||||
e.endurance = row[27] ? strtoll(row[27], nullptr, 10) : 0;
|
||||
e.created_at = strtoll(row[28] ? row[28] : "-1", nullptr, 10);
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static std::vector<ZoneStateSpawns> GetWhere(Database& db, const std::string &where_filter)
|
||||
{
|
||||
std::vector<ZoneStateSpawns> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE {}",
|
||||
BaseSelect(),
|
||||
where_filter
|
||||
)
|
||||
);
|
||||
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
ZoneStateSpawns e{};
|
||||
|
||||
e.id = row[0] ? strtoll(row[0], nullptr, 10) : 0;
|
||||
e.zone_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.instance_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.is_corpse = row[3] ? static_cast<int8_t>(atoi(row[3])) : 0;
|
||||
e.is_zone = row[4] ? static_cast<int8_t>(atoi(row[4])) : 0;
|
||||
e.decay_in_seconds = row[5] ? static_cast<int32_t>(atoi(row[5])) : 0;
|
||||
e.npc_id = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.spawn2_id = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.spawngroup_id = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.x = row[9] ? strtof(row[9], nullptr) : 0;
|
||||
e.y = row[10] ? strtof(row[10], nullptr) : 0;
|
||||
e.z = row[11] ? strtof(row[11], nullptr) : 0;
|
||||
e.heading = row[12] ? strtof(row[12], nullptr) : 0;
|
||||
e.respawn_time = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
|
||||
e.variance = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
||||
e.grid = row[15] ? static_cast<uint32_t>(strtoul(row[15], nullptr, 10)) : 0;
|
||||
e.current_waypoint = row[16] ? static_cast<int32_t>(atoi(row[16])) : 0;
|
||||
e.path_when_zone_idle = row[17] ? static_cast<int16_t>(atoi(row[17])) : 0;
|
||||
e.condition_id = row[18] ? static_cast<uint16_t>(strtoul(row[18], nullptr, 10)) : 0;
|
||||
e.condition_min_value = row[19] ? static_cast<int16_t>(atoi(row[19])) : 0;
|
||||
e.enabled = row[20] ? static_cast<int16_t>(atoi(row[20])) : 1;
|
||||
e.anim = row[21] ? static_cast<uint16_t>(strtoul(row[21], nullptr, 10)) : 0;
|
||||
e.loot_data = row[22] ? row[22] : "";
|
||||
e.entity_variables = row[23] ? row[23] : "";
|
||||
e.buffs = row[24] ? row[24] : "";
|
||||
e.hp = row[25] ? strtoll(row[25], nullptr, 10) : 0;
|
||||
e.mana = row[26] ? strtoll(row[26], nullptr, 10) : 0;
|
||||
e.endurance = row[27] ? strtoll(row[27], nullptr, 10) : 0;
|
||||
e.created_at = strtoll(row[28] ? row[28] : "-1", nullptr, 10);
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static int DeleteWhere(Database& db, const std::string &where_filter)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"DELETE FROM {} WHERE {}",
|
||||
TableName(),
|
||||
where_filter
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int Truncate(Database& db)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"TRUNCATE TABLE {}",
|
||||
TableName()
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int64 GetMaxId(Database& db)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"SELECT COALESCE(MAX({}), 0) FROM {}",
|
||||
PrimaryKey(),
|
||||
TableName()
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||
}
|
||||
|
||||
static int64 Count(Database& db, const std::string &where_filter = "")
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"SELECT COUNT(*) FROM {} {}",
|
||||
TableName(),
|
||||
(where_filter.empty() ? "" : "WHERE " + where_filter)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||
}
|
||||
|
||||
static std::string BaseReplace()
|
||||
{
|
||||
return fmt::format(
|
||||
"REPLACE INTO {} ({}) ",
|
||||
TableName(),
|
||||
ColumnsRaw()
|
||||
);
|
||||
}
|
||||
|
||||
static int ReplaceOne(
|
||||
Database& db,
|
||||
const ZoneStateSpawns &e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.zone_id));
|
||||
v.push_back(std::to_string(e.instance_id));
|
||||
v.push_back(std::to_string(e.is_corpse));
|
||||
v.push_back(std::to_string(e.is_zone));
|
||||
v.push_back(std::to_string(e.decay_in_seconds));
|
||||
v.push_back(std::to_string(e.npc_id));
|
||||
v.push_back(std::to_string(e.spawn2_id));
|
||||
v.push_back(std::to_string(e.spawngroup_id));
|
||||
v.push_back(std::to_string(e.x));
|
||||
v.push_back(std::to_string(e.y));
|
||||
v.push_back(std::to_string(e.z));
|
||||
v.push_back(std::to_string(e.heading));
|
||||
v.push_back(std::to_string(e.respawn_time));
|
||||
v.push_back(std::to_string(e.variance));
|
||||
v.push_back(std::to_string(e.grid));
|
||||
v.push_back(std::to_string(e.current_waypoint));
|
||||
v.push_back(std::to_string(e.path_when_zone_idle));
|
||||
v.push_back(std::to_string(e.condition_id));
|
||||
v.push_back(std::to_string(e.condition_min_value));
|
||||
v.push_back(std::to_string(e.enabled));
|
||||
v.push_back(std::to_string(e.anim));
|
||||
v.push_back("'" + Strings::Escape(e.loot_data) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.entity_variables) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.buffs) + "'");
|
||||
v.push_back(std::to_string(e.hp));
|
||||
v.push_back(std::to_string(e.mana));
|
||||
v.push_back(std::to_string(e.endurance));
|
||||
v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES ({})",
|
||||
BaseReplace(),
|
||||
Strings::Implode(",", v)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int ReplaceMany(
|
||||
Database& db,
|
||||
const std::vector<ZoneStateSpawns> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &e: entries) {
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.zone_id));
|
||||
v.push_back(std::to_string(e.instance_id));
|
||||
v.push_back(std::to_string(e.is_corpse));
|
||||
v.push_back(std::to_string(e.is_zone));
|
||||
v.push_back(std::to_string(e.decay_in_seconds));
|
||||
v.push_back(std::to_string(e.npc_id));
|
||||
v.push_back(std::to_string(e.spawn2_id));
|
||||
v.push_back(std::to_string(e.spawngroup_id));
|
||||
v.push_back(std::to_string(e.x));
|
||||
v.push_back(std::to_string(e.y));
|
||||
v.push_back(std::to_string(e.z));
|
||||
v.push_back(std::to_string(e.heading));
|
||||
v.push_back(std::to_string(e.respawn_time));
|
||||
v.push_back(std::to_string(e.variance));
|
||||
v.push_back(std::to_string(e.grid));
|
||||
v.push_back(std::to_string(e.current_waypoint));
|
||||
v.push_back(std::to_string(e.path_when_zone_idle));
|
||||
v.push_back(std::to_string(e.condition_id));
|
||||
v.push_back(std::to_string(e.condition_min_value));
|
||||
v.push_back(std::to_string(e.enabled));
|
||||
v.push_back(std::to_string(e.anim));
|
||||
v.push_back("'" + Strings::Escape(e.loot_data) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.entity_variables) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.buffs) + "'");
|
||||
v.push_back(std::to_string(e.hp));
|
||||
v.push_back(std::to_string(e.mana));
|
||||
v.push_back(std::to_string(e.endurance));
|
||||
v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")");
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES {}",
|
||||
BaseReplace(),
|
||||
Strings::Implode(",", insert_chunks)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
};
|
||||
|
||||
#endif //EQEMU_BASE_ZONE_STATE_SPAWNS_REPOSITORY_H
|
||||
@@ -106,8 +106,13 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
auto buy_lines =
|
||||
BaseBuyerBuyLinesRepository::GetWhere(db, fmt::format("`buyer_id` = {}", buyer.front().id));
|
||||
auto buy_lines = BaseBuyerBuyLinesRepository::GetWhere(
|
||||
db,
|
||||
fmt::format("`buyer_id` = '{}'", buyer.front().id)
|
||||
);
|
||||
if (buy_lines.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> buy_line_ids{};
|
||||
for (auto const &bl: buy_lines) {
|
||||
@@ -116,65 +121,23 @@ public:
|
||||
|
||||
DeleteWhere(db, fmt::format("`char_id` = '{}';", char_id));
|
||||
if (buy_line_ids.empty()) {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
BaseBuyerBuyLinesRepository::DeleteWhere(
|
||||
db, fmt::format("`id` IN({})", Strings::Implode(", ", buy_line_ids))
|
||||
db,
|
||||
fmt::format("`id` IN({})", Strings::Implode(", ", buy_line_ids))
|
||||
);
|
||||
BaseBuyerTradeItemsRepository::DeleteWhere(
|
||||
db, fmt::format("`buyer_buy_lines_id` IN({})", Strings::Implode(", ", buy_line_ids))
|
||||
db,
|
||||
fmt::format(
|
||||
"`buyer_buy_lines_id` IN({})",
|
||||
Strings::Implode(", ", buy_line_ids))
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool DeleteBuyers(Database &db, uint32 char_zone_id, uint32 char_zone_instance_id)
|
||||
{
|
||||
auto buyers = GetWhere(
|
||||
db,
|
||||
fmt::format(
|
||||
"`char_zone_id` = {} AND `char_zone_instance_id` = {}", char_zone_id, char_zone_instance_id
|
||||
)
|
||||
);
|
||||
if (buyers.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> buyer_ids{};
|
||||
std::vector<std::string> buy_line_ids{};
|
||||
|
||||
for (auto const &b: buyers) {
|
||||
buyer_ids.push_back(std::to_string(b.id));
|
||||
}
|
||||
|
||||
auto buy_lines = BaseBuyerBuyLinesRepository::GetWhere(
|
||||
db, fmt::format("`buyer_id` IN({})", Strings::Implode(", ", buyer_ids))
|
||||
);
|
||||
|
||||
if (!buy_lines.empty()) {
|
||||
for (auto const &bl: buy_lines) {
|
||||
buy_line_ids.push_back(std::to_string(bl.id));
|
||||
}
|
||||
}
|
||||
|
||||
DeleteWhere(db, fmt::format("`id` IN({});", Strings::Implode(", ", buyer_ids)));
|
||||
if (buy_line_ids.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
BaseBuyerBuyLinesRepository::DeleteWhere(
|
||||
db,
|
||||
fmt::format("`id` IN({})", Strings::Implode(", ", buy_line_ids))
|
||||
);
|
||||
BaseBuyerTradeItemsRepository::DeleteWhere(
|
||||
db,
|
||||
fmt::format("`buyer_buy_lines_id` IN({})", Strings::Implode(", ", buy_line_ids))
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //EQEMU_BUYER_REPOSITORY_H
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user