Compare commits

...

76 Commits

Author SHA1 Message Date
Chris Miles 588de15382 ? 2025-06-29 23:39:33 -05:00
Chris Miles aeb13e8fd3 ? 2025-06-29 23:38:45 -05:00
Chris Miles 98f824b0f5 Build tweaks 2025-06-29 23:34:46 -05:00
Chris Miles 605e23e8d0 Build analyze work 2025-06-29 22:29:36 -05:00
nytmyr fc470d5f83 [Bots] Fix ^cast resurrects (#4958)
- Was failing stack checks and couldn't be casted. Added bypass.
2025-06-29 10:19:00 -04:00
Chris Miles 585ed3bd25 [Release] 23.8.1 2025-06-28 17:29:25 -05:00
Chris Miles 2eb291a461 [Databuckets] Revert Caching Changes of #4917 (#4957)
* [Databuckets] Revert Caching Changes of #4917

* Comment caching tests until addressed later
2025-06-28 17:28:19 -05:00
Alex King a1421af214 [Bug Fix] Fix Hero Forge on Character Select (#4954) 2025-06-26 19:35:28 -04:00
Alex King 13aad6229f [Crash Fix] Fix Possible Crashes with Raid Methods (#4955) 2025-06-26 19:35:20 -04:00
Alex King 76d46ceaf0 [Bug Fix] Fix FindCharacter Using content_db (#4956) 2025-06-26 19:35:11 -04:00
Chris Miles 389047c4e2 [Release] 23.8.0 (#4953)
* [Release] 23.8.0

* Changelog

* Update ruletypes.h
2025-06-25 21:12:05 -05:00
Chris Miles 2c6d405b2c [Hotfix] Fix ClientList Singleton Shortcomings of #4942 2025-06-25 15:50:34 -05:00
Fryguy 50ae0f8351 [Corpses] Add corpse entity variables to DB (#4911)
* [Corpses] Add corpse entity variables to DB

- When corpses have entity variables add/remove/modified it will update the database accordingly.
- Corpse loading will pull the database values if they exist.

* Updates per review

* Update version.h

---------

Co-authored-by: Chris Miles <akkadius1@gmail.com>
2025-06-25 15:21:52 -05:00
Alex King dc261bb203 [Code] ZSList Global to Singleton Cleanup (#4940)
* [Code] ZSList Global to Singleton Cleanup

* Final

* Post merge fixes

---------

Co-authored-by: Chris Miles <akkadius1@gmail.com>
2025-06-25 15:16:44 -05:00
Alex King 643ee56433 [Code] PlayerEventLogs Global to Singleton Cleanup (#4928)
* [Code] PlayerEventLogs Global to Singleton Cleanup

* Fix

---------

Co-authored-by: Chris Miles <akkadius1@gmail.com>
2025-06-25 15:05:33 -05:00
Alex King c0bb32ed12 [Code] WorldContentServer Global to Singleton Cleanup (#4939) 2025-06-25 14:55:39 -05:00
Alex King c99bda3f47 [Code] WebInterfaceList Global to Singleton Cleanup (#4935) 2025-06-25 14:49:32 -05:00
Alex King 967a13e692 [Code] WorldEventScheduler and ZoneEventScheduler Global to Singleton Cleanup (#4932) 2025-06-25 14:47:37 -05:00
Alex King f304f9cc61 [Code] QueryServConnection Global to Singleton Cleanup (#4938)
* [Code] QueryServConnection Global to Singleton Cleanup

* Fix missed file in PR

---------

Co-authored-by: Chris Miles <akkadius1@gmail.com>
2025-06-25 14:43:01 -05:00
Alex King 004e2ca63f [Code] AdventureManager Global to Singleton Cleanup (#4931)
* [Code] AdventureManager Global to Singleton Cleanup

* Post merge fix

---------

Co-authored-by: Chris Miles <akkadius1@gmail.com>
2025-06-25 14:38:24 -05:00
Alex King 128732e05d [Code] EvolvingItemsManager Global to Singleton Cleanup (#4929)
Co-authored-by: Chris Miles <akkadius1@gmail.com>
2025-06-25 14:26:29 -05:00
Alex King 1e6a4dac78 [Code] UCSConnection Global to Singleton Cleanup (#4937)
Co-authored-by: Chris Miles <akkadius1@gmail.com>
2025-06-25 14:25:37 -05:00
Alex King 654764685a [Code] LFGuildManager Global to Singleton Cleanup (#4927)
* [Code] LFGuildManager Global to Singleton Cleanup

* Update lfguild.h

* Update worldserver.cpp

---------

Co-authored-by: Chris Miles <akkadius1@gmail.com>
2025-06-25 14:19:52 -05:00
Alex King c5ab35e4af [Code] SharedTaskManager Global to Singleton Cleanup (#4930)
Co-authored-by: Chris Miles <akkadius1@gmail.com>
2025-06-25 14:11:40 -05:00
Chris Miles 947795f1d1 [Code] EQEmuLogSys Global to Singleton Cleanup (#4925)
* [Code] EQEmuLogSys Global to Singleton Cleanup

* Post merge fix
2025-06-25 14:05:49 -05:00
Alex King 1153c9ab96 [Code] LoginServerList Global to Singleton Cleanup (#4941) 2025-06-25 13:49:55 -05:00
Alex King 2128b45313 [Code] ClientList Global to Singleton Cleanup (#4942) 2025-06-25 13:49:42 -05:00
Alex King 4f7ff2d6f2 [Code] DatabaseUpdate Global to Singleton Cleanup (#4943)
Co-authored-by: Chris Miles <akkadius1@gmail.com>
2025-06-25 13:48:18 -05:00
Alex King b5f1e99d3b [Code] DiscordManager Global to Singleton Cleanup (#4926)
* [Code] DiscordManager Global to Singleton Cleanup

* Update discord_manager.h

---------

Co-authored-by: Chris Miles <akkadius1@gmail.com>
2025-06-25 13:47:47 -05:00
Chris Miles 83918ce020 [Performance] Wearchange Packet Send Deduplication (#4916)
* [Performance] Wearchange Packet Send Deduplication

* Update mob_appearance.cpp

* Reduce one allocation

* Update mob_appearance.cpp

* Change

* Update mob_appearance.cpp

* Update mob_appearance.cpp

* Update mob_appearance.cpp

* Update mob_appearance.cpp

* Update mob_appearance.cpp

* Wut

* ffs
2025-06-25 13:19:29 -05:00
Alex King f3aaeff0a9 [Code] PetitionList Global to Singleton Cleanup (#4944)
* [Code] PetitionList Global to Singleton Cleanup

* Update worldserver.cpp

* Update worldserver.cpp
2025-06-25 13:15:21 -05:00
Chris Miles 98eff43346 chore: Update language for clarity and attribution 2025-06-25 13:09:43 -05:00
Bemvaras 46b43a990f [Quest API] Add CompleteTask and UncompleteTask methods to Perl/Lua (#4921)
* Add quest::uncompletetask to quest API

* Remove CMakeSettings.json (local build config) from PR

* Push

* Final

* Update embparser_api.cpp

* Update questmgr.cpp

* Update lua_client.cpp

* Fix parcel slot duplication for evolving item augments

---------

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
Co-authored-by: Chris Miles <akkadius1@gmail.com>
2025-06-25 13:03:23 -05:00
Chris Miles ea96cbf885 [Databuckets] Nested Caching (#4917)
* [Databuckets] Nested Caching

* One more

* Update benchmark_databuckets.cpp

* Add caching tests

* Fix tests and scoping

* Update databuckets.cpp

* Fix tests

* Rebase fixes

* [Databuckets] Implement Cache in World (#4920)
2025-06-25 12:47:43 -05:00
regneq de07870c99 [Fix] Fix breaking changes to Titanium, SoF, SoD patches causes by big bags update (#4922)
* [Fix] Fix breaking change to Titanium patches caused by Big Bags update.

* Fixes for Titanium, SoD, SoF causes by big bag bug.
2025-06-25 12:41:13 -05:00
Chris Miles b3b228c26c [Code] PCH Cleanup (#4952)
* Update CMakeLists.txt

* Update CMakeLists.txt

* Update CMakeLists.txt

* Update CMakeLists.txt

* Update CMakeLists.txt

* Update CMakeLists.txt

* Update CMakeLists.txt

* Update CMakeLists.txt

* Update CMakeLists.txt

* Update CMakeLists.txt

* Update CMakeLists.txt

* Update app-pch.h

* Update CMakeLists.txt

* Split out pch to zone

* Update CMakeLists.txt

* Update CMakeLists.txt

* Update CMakeLists.txt

* Update CMakeLists.txt

* Update CMakeLists.txt

* Update windows-build.ps1

* Update windows-build.ps1

* Update CMakeLists.txt

* Update CMakeLists.txt

* Update CMakeLists.txt

* Update CMakeLists.txt

* Update CMakeLists.txt
2025-06-25 12:26:38 -05:00
Fryguy 27b5c80c3c [Quest API] Lua Client Scoped EnableTitleSets (#4914)
Example usage:
```lua
client:EnableTitleSet(reward.title_set)
```
2025-06-25 12:25:35 -05:00
Chris Miles fb4d003e19 [Player Events] Zone Fetch Settings from QS if Enabled (#4915)
* [Player Events] Zone Fetch Settings from QS if Enabled

* Update zonelist.cpp

* Update zoneserver.cpp
2025-06-25 12:21:35 -05:00
Chris Miles f025e5741b [Player Event Logs] Don't Clear Event Data on ETL Events (#4913)
* [Player Event Logs] Don't Clear Event Data on ETL Events

* Migration
2025-06-24 20:15:22 -04:00
Chris Miles c3f2708f1b [Player Events] Don't Write Empty Data (#4912)
* [Player Events] Don't Write Empty Data

* Revert "[Player Events] Don't Write Empty Data"

This reverts commit f64a824b33.

* Update player_events.h

* Augs
2025-06-24 20:14:51 -04:00
Alex King 2e760d6397 [Code] ZoneStore Global to Singleton Cleanup (#4934) 2025-06-23 06:45:06 -04:00
Chris Miles bac892b582 [API] Add wwmarquee <type> <message> (#4919)
* [API] Implement Console "wwmarquee"

* Fin
2025-06-23 05:25:50 -04:00
Chris Miles 4005b68383 [Code] Optimize PCH Config (Faster Builds) (#4951) 2025-06-22 13:52:23 -05:00
Chris Miles 5ac9dd04e4 [Code] Cleanup Strings Header (#4950)
* [Code] Cleanup Strings Header

* Include optimize
2025-06-22 13:52:13 -05:00
Alex King f0c041e8b3 [Code] EQ::Random Global to Singleton Cleanup (#4936) 2025-06-22 14:13:58 -04:00
Alex King 2f4a5b56dd [Code] SkillCaps Global to Singleton Cleanup (#4933) 2025-06-22 14:13:16 -04:00
Alex King 940f97c9ae [Code] TaskManager Global to Singleton Cleanup (#4945)
* [Code] TaskManager Global to Singleton Cleanup

* Remove checks for existence

* Final
2025-06-22 14:10:48 -04:00
Chris Miles f8ee664b27 [Code] Remove Lua Rule Constants (#4949) 2025-06-22 13:55:55 -04:00
Chris Miles df86ad371b [Code] PathManager Global to Singleton Cleanup (#4924) 2025-06-22 13:50:52 -04:00
Chris Miles e846bb86b6 [Code] Remove Regex Compile Bloat (#4947) 2025-06-22 02:08:15 -05:00
Chris Miles 3e6a3e2168 [Build] Significantly Improve Build Times Using Unity Builds (#4948) 2025-06-22 02:08:03 -05:00
Alex King 2aebf1a78a [Code] Remove Unused MZoneShutdown Mutex (#4946) 2025-06-22 01:49:39 -05:00
Chris Miles 1be7e56b86 [Databuckets] Move Databuckets to Common (#4918)
* [Databuckets] Move Databuckets to Common

* Fix linking issue
2025-06-16 16:48:29 -05:00
Chris Miles a0ff9d67a1 [Fix] Bulk Send Corpses after Idle State (#4910) 2025-06-09 14:31:28 -05:00
Chris Miles befee1c729 [Quests] Support Multiple Quest, Plugin, and Lua Module Paths (#4906)
* [Quests] Add Support for Multiple Load Paths

* Adjust load paths

* plugin != m_lua_module_directories
2025-06-09 12:49:46 -05:00
nytmyr 3d70063a68 [Doors] Fix door saving for versions (#4905)
* [Doors] Fix door saving for versions

- Door saving wasn't saving to the proper version on `#door save`

* Update doors.cpp

---------

Co-authored-by: Chris Miles <akkadius1@gmail.com>
2025-06-09 12:47:56 -05:00
JJ 4e28bcf85e Bump libuv to 1.50.0 (#4898) 2025-06-09 12:40:37 -05:00
JJ 687d10960a [Logs] Fix output for tasks in logs (#4907) 2025-06-09 12:32:45 -05:00
Chris Miles 567d46c3d6 [Performance] Auto Idle / AFK (#4903)
* [Performance] AFK Client Packet Filtering

* Player feedback

* Update client_packet.cpp

* Fixes

* Streamline updates to SetAFK

* Decouple idling and AFK and manual AFK

* Reset clock timer when we take AFK or idle off

* Exclude bard songs in non combat zones from resetting timer

* GM exclusion adjustments
2025-05-22 13:08:32 -05:00
Chris Miles 53cc2de459 [World API] Input Validation (#4904)
* [World API] Input Validation

* Update eqemu_api_world_data_service.cpp

* Add db ping to player events processor, move back into main thread
2025-05-22 13:08:17 -05:00
Chris Miles cb866cba31 [Release] 23.7.0 (#4902) 2025-05-19 12:31:37 -05:00
JJ e2162c08da [CLI] Add custom database version output (#4901)
* Add custom database version output to CLI from #4892

* Spacing alignment
2025-05-18 11:28:10 -05:00
Chris Miles e657953b8f [Netcode] Resend Logic Adjustments (#4900)
* Timeout adjustment

* Update daybreak_connection.cpp

* Update daybreak_connection.cpp

* Update daybreak_connection.cpp

* Update daybreak_connection.cpp

* Update daybreak_connection.cpp

* Update daybreak_connection.cpp

* Stuff

* Update daybreak_connection.h

* Update daybreak_connection.cpp

* Update daybreak_connection.cpp

* Update daybreak_connection.cpp

* Update daybreak_connection.cpp
2025-05-18 11:19:37 -05:00
JJ eb366e67b7 [CLI] Fix MySQL check in database dumper (#4897) 2025-05-16 18:56:38 -05:00
JJ 5b728a42f7 Update zonelist.h (#4896) 2025-05-16 18:17:38 -04:00
Chris Miles a1d414d64c [Netcode] Resend Logic Adjustments (#4895)
* [Netcode] Resend Logic Adjustments

* Update daybreak_connection.h
2025-05-16 16:46:07 -05:00
Chris Miles 907029ed76 [Database] Remove Transaction Wrapped Character Save (#4894) 2025-05-16 16:07:45 -05:00
Chris Miles 894f22fba0 [Fix] Deadlock on failed #copycharacter commands (#4887) 2025-05-16 13:39:34 -05:00
Chris Miles 7ec09d7e0f [Player Events] Add rule to ignore configured GM commands (#4888) 2025-05-16 13:39:24 -05:00
Chris Miles c82266790a [Zone State] Load New Spawn2 Data When Present (#4889) 2025-05-16 13:39:16 -05:00
Chris Miles ec31fddbae [Logging] Auto Update Log Category Names (#4890) 2025-05-16 13:39:08 -05:00
Chris Miles fb49ce2404 [Rules] Auto Update Rule Notes from Source (#4891)
* [Rules] Auto Update Rule Notes from Source

* Update rulesys.cpp
2025-05-16 13:38:59 -05:00
Chris Miles 276b7e238a [Database] Add Custom Database Migrations for Operators (#4892)
* [Database] Add Custom Database Migrations for Operators

* Changes

* Update database_update_manifest_custom.cpp
2025-05-16 13:38:51 -05:00
Chris Miles c7a463420b [World] Fix Rarer Reload Deadlock (#4893) 2025-05-16 13:38:42 -05:00
Chris Miles a56bb52808 Update README.md 2025-05-15 15:29:05 -05:00
Chris Miles 0bbdb58679 Update README.md 2025-05-15 15:26:07 -05:00
239 changed files with 5597 additions and 3675 deletions
+33 -1
View File
@@ -30,6 +30,11 @@ steps:
- name: cache
path: /home/eqemu/.ccache/
trigger:
branch:
exclude:
- build-analyze
---
kind: pipeline
@@ -57,6 +62,11 @@ steps:
commands:
- .\utils\scripts\build\windows-build.ps1
trigger:
branch:
exclude:
- build-analyze
---
kind: pipeline
@@ -87,7 +97,10 @@ steps:
trigger:
branch:
- master
include:
- master
exclude:
- build-analyze
event:
- push
@@ -95,4 +108,23 @@ depends_on:
- Build Windows
- Build Linux
---
kind: pipeline
type: docker
name: Build Analyze
steps:
- name: Build Linux X64
image: akkadius/eqemu-server:v16
environment:
GITHUB_TOKEN:
from_secret: GH_RELEASE_GITHUB_API_TOKEN
commands:
- ./utils/scripts/build/linux-build-analyze.sh
trigger:
branch:
- build-analyze
event:
- push
+150
View File
@@ -1,3 +1,153 @@
## [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
+3
View File
@@ -42,6 +42,7 @@ 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)
@@ -362,6 +363,8 @@ MESSAGE(STATUS "**************************************************")
#setup server libs and headers
SET(SERVER_LIBS common ${DATABASE_LIBRARY_LIBS} ${ZLIB_LIBRARY_LIBS} ${Boost_LIBRARIES} uv_a fmt RecastNavigation::Detour)
set(FMT_HEADER_ONLY OFF)
INCLUDE_DIRECTORIES(SYSTEM "${DATABASE_LIBRARY_INCLUDE}")
INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_LIBRARY_INCLUDE}")
INCLUDE_DIRECTORIES(SYSTEM "${Boost_INCLUDE_DIRS}")
+123 -56
View File
@@ -1,83 +1,150 @@
# EQEmulator Core Server
| Drone (Linux x64) | Drone (Windows x64) |
|:---:|:---:|
|[![Build Status](http://drone.akkadius.com/api/badges/EQEmu/Server/status.svg)](http://drone.akkadius.com/EQEmu/Server) |[![Build Status](http://drone.akkadius.com/api/badges/EQEmu/Server/status.svg)](http://drone.akkadius.com/EQEmu/Server) |
<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&amp;logo=discord&amp;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 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">
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>
## Server Installs
| |Windows|Linux|
|:---:|:---:|:---:|
|**Install Count**|![Windows Install Count](http://analytics.akkadius.com/?install_count&windows_count)|![Linux Install Count](http://analytics.akkadius.com/?install_count&linux_count)|
### > Windows
<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>
* [Install Guide](https://docs.eqemu.io/server/installation/server-installation-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>
### > Debian/Ubuntu/CentOS/Fedora
<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>
* [Install Guide](https://docs.eqemu.io/server/installation/server-installation-linux/)
***
* 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
<h3 align="center">
Technical Overview & Reverse Engineering Effort
</h1>
> 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
<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>
## Supported Clients
<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 ProjectEQs 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>
|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">|
## 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.
## 📚 Resources
## Contributions <img src="http://image.flaticon.com/icons/png/512/25/25231.png" width="20">
| Resource | Badges | Link |
|---------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------|
| **EQEmulator Docs** | [![Docs](https://img.shields.io/badge/docs-MkDocs%20Powered-blueviolet)](https://docs.eqemu.io) | [docs.eqemu.io](https://docs.eqemu.io/) |
| **Discord Community**| [![Discord](https://img.shields.io/discord/212663220849213441?label=Discord&logo=discord&color=7289DA)](https://discord.gg/QHsm7CD) | [Join Discord](https://discord.gg/QHsm7CD) |
| **Latest Release** | [![Latest Release](https://img.shields.io/github/v/release/eqemu/server)](https://github.com/eqemu/server/releases) <br> [![Release Date](https://img.shields.io/github/release-date/EQEmu/Server)](https://github.com/EQEmu/Server/releases) <br> [![All Releases](https://img.shields.io/github/downloads/eqemu/server/total.svg)](https://github.com/eqemu/server/releases) | [View Releases](https://github.com/eqemu/server/releases) |
| **License** | [![License](https://img.shields.io/github/license/EQEmu/Server)](./LICENSE) | [View License](./LICENSE) |
| **Build Status** | [![Build Status](http://drone.akkadius.com/api/badges/EQEmu/Server/status.svg)](http://drone.akkadius.com/EQEmu/Server) | [View Build Status](http://drone.akkadius.com/EQEmu/Server) |
| **Docker Pulls** | [![Docker Pulls](https://img.shields.io/docker/pulls/akkadius/eqemu-server)](https://hub.docker.com/r/akkadius/eqemu-server) | [Docker Hub](https://hub.docker.com/r/akkadius/eqemu-server) |
| **Contributions** | [![GitHub PRs](https://img.shields.io/github/issues-pr-closed/eqemu/server)](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) |
* 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.
## 🛠️ Getting Started
## Contact <img src="http://gamerescape.com/wp-content/uploads/2015/06/discord.png" height="20">
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!
- Discord Channel: https://discord.gg/QHsm7CD
- **User Discord Channel**: `#general`
- **Developer Discord Channel**: `#eqemucoders`
## 🗂️ Related Repositories
## Resources
- [EQEmulator Forums](http://www.eqemulator.org/forums)
- [EQEmulator Wiki](https://docs.eqemu.io/)
| 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 |
## 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>
+9 -16
View File
@@ -38,13 +38,6 @@
#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);
@@ -53,10 +46,10 @@ void ExportDBStrings(SharedDatabase *db);
int main(int argc, char **argv)
{
RegisterExecutablePlatform(ExePlatformClientExport);
LogSys.LoadLogSettingsDefaults();
EQEmuLogSys::Instance()->LoadLogSettingsDefaults();
set_exception_handler();
path.LoadPaths();
PathManager::Instance()->Init();
LogInfo("Client Files Export Utility");
if (!EQEmuConfig::LoadConfig()) {
@@ -99,8 +92,8 @@ int main(int argc, char **argv)
content_db.SetMySQL(database);
}
LogSys.SetDatabase(&database)
->SetLogPath(path.GetLogPath())
EQEmuLogSys::Instance()->SetDatabase(&database)
->SetLogPath(PathManager::Instance()->GetLogPath())
->LoadLogDatabaseSettings()
->StartFileLogs();
@@ -129,14 +122,14 @@ int main(int argc, char **argv)
ExportBaseData(&content_db);
ExportDBStrings(&database);
LogSys.CloseFileLogs();
EQEmuLogSys::Instance()->CloseFileLogs();
return 0;
}
void ExportSpells(SharedDatabase* db)
{
std::ofstream file(fmt::format("{}/export/spells_us.txt", path.GetServerPath()));
std::ofstream file(fmt::format("{}/export/spells_us.txt", PathManager::Instance()->GetServerPath()));
if (!file || !file.is_open()) {
LogError("Unable to open export/spells_us.txt to write, skipping.");
return;
@@ -155,7 +148,7 @@ void ExportSpells(SharedDatabase* db)
void ExportSkillCaps(SharedDatabase* db)
{
std::ofstream file(fmt::format("{}/export/SkillCaps.txt", path.GetServerPath()));
std::ofstream file(fmt::format("{}/export/SkillCaps.txt", PathManager::Instance()->GetServerPath()));
if (!file || !file.is_open()) {
LogError("Unable to open export/SkillCaps.txt to write, skipping.");
return;
@@ -174,7 +167,7 @@ void ExportSkillCaps(SharedDatabase* db)
void ExportBaseData(SharedDatabase *db)
{
std::ofstream file(fmt::format("{}/export/BaseData.txt", path.GetServerPath()));
std::ofstream file(fmt::format("{}/export/BaseData.txt", PathManager::Instance()->GetServerPath()));
if (!file || !file.is_open()) {
LogError("Unable to open export/BaseData.txt to write, skipping.");
return;
@@ -193,7 +186,7 @@ void ExportBaseData(SharedDatabase *db)
void ExportDBStrings(SharedDatabase *db)
{
std::ofstream file(fmt::format("{}/export/dbstr_us.txt", path.GetServerPath()));
std::ofstream file(fmt::format("{}/export/dbstr_us.txt", PathManager::Instance()->GetServerPath()));
if (!file || !file.is_open()) {
LogError("Unable to open export/dbstr_us.txt to write, skipping.");
return;
+9 -16
View File
@@ -32,13 +32,6 @@
#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);
@@ -46,10 +39,10 @@ void ImportDBStrings(SharedDatabase *db);
int main(int argc, char **argv) {
RegisterExecutablePlatform(ExePlatformClientImport);
LogSys.LoadLogSettingsDefaults();
EQEmuLogSys::Instance()->LoadLogSettingsDefaults();
set_exception_handler();
path.LoadPaths();
PathManager::Instance()->Init();
LogInfo("Client Files Import Utility");
if(!EQEmuConfig::LoadConfig()) {
@@ -92,8 +85,8 @@ int main(int argc, char **argv) {
content_db.SetMySQL(database);
}
LogSys.SetDatabase(&database)
->SetLogPath(path.GetLogPath())
EQEmuLogSys::Instance()->SetDatabase(&database)
->SetLogPath(PathManager::Instance()->GetLogPath())
->LoadLogDatabaseSettings()
->StartFileLogs();
@@ -102,7 +95,7 @@ int main(int argc, char **argv) {
ImportBaseData(&content_db);
ImportDBStrings(&database);
LogSys.CloseFileLogs();
EQEmuLogSys::Instance()->CloseFileLogs();
return 0;
}
@@ -138,7 +131,7 @@ bool IsStringField(int i) {
void ImportSpells(SharedDatabase *db) {
LogInfo("Importing Spells");
std::string file = fmt::format("{}/import/spells_us.txt", path.GetServerPath());
std::string file = fmt::format("{}/import/spells_us.txt", PathManager::Instance()->GetServerPath());
FILE *f = fopen(file.c_str(), "r");
if(!f) {
LogError("Unable to open {} to read, skipping.", file);
@@ -228,7 +221,7 @@ void ImportSpells(SharedDatabase *db) {
void ImportSkillCaps(SharedDatabase *db) {
LogInfo("Importing Skill Caps");
std::string file = fmt::format("{}/import/SkillCaps.txt", path.GetServerPath());
std::string file = fmt::format("{}/import/SkillCaps.txt", PathManager::Instance()->GetServerPath());
FILE *f = fopen(file.c_str(), "r");
if(!f) {
LogError("Unable to open {} to read, skipping.", file);
@@ -265,7 +258,7 @@ void ImportBaseData(SharedDatabase *db)
{
LogInfo("Importing Base Data");
const std::string& file_name = fmt::format("{}/import/BaseData.txt", path.GetServerPath());
const std::string& file_name = fmt::format("{}/import/BaseData.txt", PathManager::Instance()->GetServerPath());
const auto& file_contents = File::GetContents(file_name);
if (!file_contents.error.empty()) {
@@ -305,7 +298,7 @@ void ImportBaseData(SharedDatabase *db)
void ImportDBStrings(SharedDatabase *db) {
LogInfo("Importing DB Strings");
std::string file = fmt::format("{}/import/dbstr_us.txt", path.GetServerPath());
std::string file = fmt::format("{}/import/dbstr_us.txt", PathManager::Instance()->GetServerPath());
FILE *f = fopen(file.c_str(), "r");
if(!f) {
LogError("Unable to open {} to read, skipping.", file);
+3 -2
View File
@@ -17,6 +17,7 @@ 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
@@ -840,8 +841,8 @@ IF (UNIX)
SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/uf.cpp" PROPERTIES COMPILE_FLAGS -O0)
ENDIF (UNIX)
IF (WIN32 AND EQEMU_BUILD_PCH)
TARGET_PRECOMPILE_HEADERS(common PRIVATE pch/pch.h)
IF (EQEMU_BUILD_PCH)
TARGET_PRECOMPILE_HEADERS(common PRIVATE pch/std-pch.h)
ENDIF ()
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
+5 -5
View File
@@ -27,7 +27,7 @@ WorldContentService *WorldContentService::SetExpansionContext()
// pull expansion from rules
int expansion = RuleI(Expansion, CurrentExpansion);
if (expansion >= Expansion::Classic && expansion <= Expansion::MaxId) {
content_service.SetCurrentExpansion(expansion);
WorldContentService::Instance()->SetCurrentExpansion(expansion);
}
LogInfo(
@@ -41,12 +41,12 @@ WorldContentService *WorldContentService::SetExpansionContext()
std::string WorldContentService::GetCurrentExpansionName()
{
if (content_service.GetCurrentExpansion() == Expansion::EXPANSION_ALL) {
if (WorldContentService::Instance()->GetCurrentExpansion() == Expansion::EXPANSION_ALL) {
return "All Expansions";
}
if (current_expansion >= Expansion::Classic && current_expansion <= Expansion::MaxId) {
return Expansion::ExpansionName[content_service.GetCurrentExpansion()];
return Expansion::ExpansionName[WorldContentService::Instance()->GetCurrentExpansion()];
}
return "Unknown Expansion";
@@ -185,7 +185,7 @@ void WorldContentService::ReloadContentFlags()
SetContentFlags(set_content_flags);
LoadStaticGlobalZoneInstances();
zone_store.LoadZones(*m_content_database);
ZoneStore::Instance()->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: zone_store.GetZones()) {
for (const auto &z: ZoneStore::Instance()->GetZones()) {
for (auto &i: m_zone_static_instances) {
if (
z.zoneidnumber == zone_id &&
+6 -2
View File
@@ -181,6 +181,12 @@ 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;
@@ -194,6 +200,4 @@ private:
std::vector<InstanceListRepository::InstanceList> m_zone_static_instances;
};
extern WorldContentService content_service;
#endif //EQEMU_WORLD_CONTENT_SERVICE_H
+7 -5
View File
@@ -27,6 +27,8 @@ 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);
@@ -68,12 +70,12 @@ void SendCrashReport(const std::string &crash_report)
p["cpus"] = cpus.size();
p["origination_info"] = "";
if (!LogSys.origination_info.zone_short_name.empty()) {
if (!log->origination_info.zone_short_name.empty()) {
p["origination_info"] = fmt::format(
"{} ({}) instance_id [{}]",
LogSys.origination_info.zone_short_name,
LogSys.origination_info.zone_long_name,
LogSys.origination_info.instance_id
log->origination_info.zone_short_name,
log->origination_info.zone_long_name,
log->origination_info.instance_id
);
}
@@ -294,7 +296,7 @@ void print_trace()
SendCrashReport(crash_report);
}
LogSys.CloseFileLogs();
EQEmuLogSys::Instance()->CloseFileLogs();
exit(1);
}
+14 -30
View File
@@ -1,18 +1,23 @@
#include "data_bucket.h"
#include "zonedb.h"
#include "mob.h"
#include "client.h"
#include "worldserver.h"
#include "../common/data_bucket.h"
#include "database.h"
#include <ctime>
#include <cctype>
#include "../common/json/json.hpp"
using json = nlohmann::json;
extern WorldServer worldserver;
const std::string NESTED_KEY_DELIMITER = ".";
const std::string NESTED_KEY_DELIMITER = ".";
std::vector<DataBucketsRepository::DataBuckets> g_data_bucket_cache = {};
std::vector<DataBucketsRepository::DataBuckets> g_data_bucket_cache = {};
#if defined(ZONE)
#include "../zone/zonedb.h"
extern ZoneDatabase database;
#elif defined(WORLD)
#include "../world/worlddb.h"
extern WorldDatabase database;
#else
#error "You must define either ZONE or WORLD"
#endif
void DataBucket::SetData(const std::string &bucket_key, const std::string &bucket_value, std::string expires_time)
{
@@ -347,27 +352,6 @@ bool DataBucket::DeleteData(const std::string &bucket_key)
return DeleteData(DataBucketKey{.key = bucket_key});
}
// GetDataBuckets bulk loads all data buckets for a mob
bool DataBucket::GetDataBuckets(Mob *mob)
{
const uint32 id = mob->GetMobTypeIdentifier();
if (!id) {
return false;
}
if (mob->IsBot()) {
BulkLoadEntitiesToCache(DataBucketLoadType::Bot, {id});
}
else if (mob->IsClient()) {
uint32 account_id = mob->CastToClient()->AccountID();
BulkLoadEntitiesToCache(DataBucketLoadType::Account, {account_id});
BulkLoadEntitiesToCache(DataBucketLoadType::Client, {id});
}
return true;
}
bool DataBucket::DeleteData(const DataBucketKey &k)
{
bool is_nested_key = k.key.find(NESTED_KEY_DELIMITER) != std::string::npos;
@@ -859,4 +843,4 @@ bool DataBucket::CanCache(const DataBucketKey &key)
}
return false;
}
}
+3 -7
View File
@@ -2,11 +2,9 @@
#define EQEMU_DATABUCKET_H
#include <string>
#include "../common/types.h"
#include "../common/repositories/data_buckets_repository.h"
#include "mob.h"
#include "../common/json/json_archive_single_line.h"
#include "../common/servertalk.h"
#include "types.h"
#include "repositories/data_buckets_repository.h"
#include "json/json_archive_single_line.h"
struct DataBucketKey {
std::string key;
@@ -46,8 +44,6 @@ public:
static std::string GetDataExpires(const std::string &bucket_key);
static std::string GetDataRemaining(const std::string &bucket_key);
static bool GetDataBuckets(Mob *mob);
// scoped bucket methods
static void SetData(const DataBucketKey &k_);
static bool DeleteData(const DataBucketKey &k);
+34 -2
View File
@@ -708,6 +708,20 @@ 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);
@@ -1920,6 +1934,7 @@ 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",
@@ -1951,6 +1966,12 @@ 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;
@@ -1969,6 +1990,12 @@ 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) {
@@ -2036,13 +2063,18 @@ 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;
}
}
}
TransactionCommit();
auto r = TransactionCommit();
if (!r.Success()) {
LogError("Transaction failed [{}] rolling back", r.ErrorMessage());
return false;
}
LogInfo(
"Character [{}] copied to [{}] total rows [{}]",
@@ -2212,7 +2244,7 @@ void Database::PurgeCharacterParcels()
pel.event_data = ss.str();
pel.created_at = std::time(nullptr);
player_event_logs.AddToQueue(pel);
PlayerEventLogs::Instance()->AddToQueue(pel);
ss.str("");
ss.clear();
+3 -3
View File
@@ -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;
return version_output.find("mysql") != std::string::npos && (version_output.find("Ver") != std::string::npos || version_output.find("from") != std::string::npos);
}
/**
@@ -204,7 +204,7 @@ void DatabaseDumpService::DatabaseDump()
}
if (IsDumpOutputToConsole()) {
LogSys.SilenceConsoleLogging();
EQEmuLogSys::Instance()->SilenceConsoleLogging();
}
LogInfo("MySQL installed [{}]", GetMySQLVersion());
@@ -324,7 +324,7 @@ void DatabaseDumpService::DatabaseDump()
}
if (!IsDumpOutputToConsole()) {
LogSys.LoadLogSettingsDefaults();
EQEmuLogSys::Instance()->LoadLogSettingsDefaults();
}
if (!pipe_file.empty()) {
+39 -4
View File
@@ -7,6 +7,7 @@
#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"
@@ -14,7 +15,7 @@ constexpr int BREAK_LENGTH = 70;
DatabaseVersion DatabaseUpdate::GetDatabaseVersions()
{
auto results = m_database->QueryDatabase("SELECT `version`, `bots_version` FROM `db_version` LIMIT 1");
auto results = m_database->QueryDatabase("SELECT `version`, `bots_version`, `custom_version` FROM `db_version` LIMIT 1");
if (!results.Success() || !results.RowCount()) {
LogError("Failed to read from [db_version] table!");
return DatabaseVersion{};
@@ -25,6 +26,7 @@ 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]),
};
}
@@ -33,6 +35,7 @@ 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,
};
}
@@ -43,6 +46,7 @@ constexpr int LOOK_BACK_AMOUNT = 10;
// this check will take action
void DatabaseUpdate::CheckDbUpdates()
{
InjectCustomVersionColumn();
InjectBotsVersionColumn();
auto v = GetDatabaseVersions();
auto b = GetBinaryDatabaseVersions();
@@ -59,6 +63,15 @@ 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(
@@ -141,7 +154,7 @@ bool DatabaseUpdate::UpdateManifest(
std::vector<int> missing_migrations = {};
if (version_low != version_high) {
LogSys.DisableMySQLErrorLogs();
EQEmuLogSys::Instance()->DisableMySQLErrorLogs();
bool force_interactive = false;
for (int version = version_low + 1; version <= version_high; ++version) {
for (auto &e: entries) {
@@ -171,7 +184,7 @@ bool DatabaseUpdate::UpdateManifest(
}
}
}
LogSys.EnableMySQLErrorLogs();
EQEmuLogSys::Instance()->EnableMySQLErrorLogs();
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
if (!missing_migrations.empty() && m_skip_backup) {
@@ -344,6 +357,16 @@ 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));
@@ -353,7 +376,10 @@ 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;
return server_up_to_date && bots_up_to_date;
// 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;
}
// checks to see if there are pending updates
@@ -373,3 +399,12 @@ 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");
}
}
+9
View File
@@ -17,6 +17,7 @@ struct ManifestEntry {
struct DatabaseVersion {
int server_database_version;
int bots_database_version;
int custom_database_version;
};
class DatabaseUpdate {
@@ -32,12 +33,20 @@ 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();
};
@@ -7109,6 +7109,30 @@ ALTER TABLE `npc_types`
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
},
@@ -0,0 +1,55 @@
#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
// };
+3 -3
View File
@@ -160,7 +160,7 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
(uint32) mysql_insert_id(mysql)
);
if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1) {
if (EQEmuLogSys::Instance()->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");
}
void DBcore::TransactionCommit()
MySQLRequestResult DBcore::TransactionCommit()
{
QueryDatabase("COMMIT");
return QueryDatabase("COMMIT");
}
void DBcore::TransactionRollback()
+1 -1
View File
@@ -32,7 +32,7 @@ public:
MySQLRequestResult QueryDatabase(const std::string& query, bool retryOnFailureOnce = true);
MySQLRequestResult QueryDatabaseMulti(const std::string &query);
void TransactionBegin();
void TransactionCommit();
MySQLRequestResult TransactionCommit();
void TransactionRollback();
std::string Escape(const std::string& s);
uint32 DoEscapeString(char *tobuf, const char *frombuf, uint32 fromlen);
-1
View File
@@ -4,7 +4,6 @@
#include <string>
#include "../types.h"
#include "../http/httplib.h"
#include "../repositories/player_event_logs_repository.h"
#include "../events/player_events.h"
+2 -2
View File
@@ -26,7 +26,7 @@ void DiscordManager::ProcessMessageQueue()
continue;
}
auto webhook = LogSys.GetDiscordWebhooks()[q.first];
auto webhook = EQEmuLogSys::Instance()->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 = player_event_logs.GetDiscordWebhookUrlFromEventType(e.player_event_log.event_type_id);
auto w = PlayerEventLogs::Instance()->GetDiscordWebhookUrlFromEventType(e.player_event_log.event_type_id);
if (!w.empty()) {
Discord::SendPlayerEventMessage(e, w);
}
+6
View File
@@ -13,6 +13,12 @@ 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{};
+2 -2
View File
@@ -545,13 +545,13 @@ void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p)
uint32 chunksize, used;
uint32 length;
if (LogSys.log_settings[Logs::Server_Client_Packet].is_category_enabled == 1){
if (EQEmuLogSys::Instance()->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 (LogSys.log_settings[Logs::Server_Client_Packet_With_Dump].is_category_enabled == 1){
if (EQEmuLogSys::Instance()->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());
}
+17 -2
View File
@@ -177,6 +177,21 @@ 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
*/
@@ -421,11 +436,11 @@ void EQEmuConfig::CheckUcsConfigConversion()
LogInfo("Migrating old [eqemu_config] UCS configuration to new configuration");
std::string config_file_path = std::filesystem::path{
path.GetServerPath() + "/eqemu_config.json"
PathManager::Instance()->GetServerPath() + "/eqemu_config.json"
}.string();
std::string config_file_bak_path = std::filesystem::path{
path.GetServerPath() + "/eqemu_config.ucs-migrate-json.bak"
PathManager::Instance()->GetServerPath() + "/eqemu_config.ucs-migrate-json.bak"
}.string();
// copy eqemu_config.json to eqemu_config.json.bak
+22 -1
View File
@@ -120,6 +120,22 @@ 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;
@@ -133,6 +149,11 @@ 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()
@@ -170,7 +191,7 @@ class EQEmuConfig
std::string file = fmt::format(
"{}/{}",
(file_path.empty() ? path.GetServerPath() : file_path),
(file_path.empty() ? PathManager::Instance()->GetServerPath() : file_path),
EQEmuConfig::ConfigFile
);
+31 -12
View File
@@ -537,9 +537,9 @@ void EQEmuLogSys::StartFileLogs(const std::string &log_name)
{
EQEmuLogSys::CloseFileLogs();
if (!File::Exists(path.GetLogPath())) {
LogInfo("Logs directory not found, creating [{}]", path.GetLogPath());
File::Makedir(path.GetLogPath());
if (!File::Exists(PathManager::Instance()->GetLogPath())) {
LogInfo("Logs directory not found, creating [{}]", PathManager::Instance()->GetLogPath());
File::Makedir(PathManager::Instance()->GetLogPath());
}
/**
@@ -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) {
LogSys.m_file_logs_enabled = true;
m_file_logs_enabled = true;
}
db_categories.emplace_back(c.log_category_id);
@@ -682,14 +682,33 @@ 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 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);
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);
}
}
}
+15 -11
View File
@@ -194,8 +194,8 @@ namespace Logs {
"Web Interface (Deprecated)",
"World Server (Deprecated)",
"Zone Server (Deprecated)",
"QueryErr",
"Query",
"MySQL Error",
"MySQL Query",
"Mercenaries",
"Quest Debug",
"Legacy Packet Logging (Deprecated)",
@@ -211,15 +211,15 @@ namespace Logs {
"Traps",
"NPC Roam Box",
"NPC Scaling",
"MobAppearance",
"Mob Appearance",
"Info",
"Warning",
"Critical (Deprecated)",
"Emergency (Deprecated)",
"Alert (Deprecated)",
"Notice (Deprecated)",
"AI Scan",
"AI Yell",
"AI Scan Close",
"AI Yell For Help",
"AI CastBeneficial",
"AOE Cast",
"Entity Management",
@@ -237,7 +237,7 @@ namespace Logs {
"DialogueWindow",
"HTTP",
"Saylink",
"ChecksumVer",
"Checksum Verification",
"CombatRecord",
"Hate",
"Discord",
@@ -266,8 +266,6 @@ namespace Logs {
};
}
#include "eqemu_logsys_log_aliases.h"
class Database;
constexpr uint16 MAX_DISCORD_WEBHOOK_ID = 300;
@@ -285,6 +283,12 @@ public:
EQEmuLogSys *LoadLogSettingsDefaults();
EQEmuLogSys *LoadLogDatabaseSettings(bool silent_load = false);
static EQEmuLogSys *Instance()
{
static EQEmuLogSys instance;
return &instance;
}
/**
* @param directory_name
*/
@@ -350,7 +354,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 LogSys.SetDatabase(&database)->LoadLogDatabaseSettings();
* Database loaded via EQEmuLogSys::Instance()->SetDatabase(&database)->LoadLogDatabaseSettings();
*/
LogSettings log_settings[Logs::LogCategory::MaxCategoryID]{};
@@ -434,7 +438,7 @@ private:
void InjectTablesIfNotExist();
};
extern EQEmuLogSys LogSys;
#include "eqemu_logsys_log_aliases.h"
/**
template<typename... Args>
@@ -456,7 +460,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
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 (!Strings::EqualFold(h.augment_names[i], "None")) {
if (!h.augment_names[i].empty()) {
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 (!Strings::EqualFold(r.augment_names[i], "None")) {
if (!r.augment_names[i].empty()) {
const uint8 slot_id = (i + 1);
return_items_info += fmt::format(
"Augment {}: {} ({})\n",
+28 -9
View File
@@ -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();
@@ -195,10 +195,12 @@ void PlayerEventLogs::ProcessBatchQueue()
};
// 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++;
}
@@ -406,7 +408,6 @@ 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);
@@ -508,7 +509,7 @@ bool PlayerEventLogs::IsEventDiscordEnabled(int32_t event_type_id)
}
// ensure there is a matching webhook to begin with
if (!LogSys.GetDiscordWebhooks()[m_settings[event_type_id].discord_webhook_id].webhook_url.empty()) {
if (!EQEmuLogSys::Instance()->GetDiscordWebhooks()[m_settings[event_type_id].discord_webhook_id].webhook_url.empty()) {
return true;
}
@@ -528,13 +529,27 @@ std::string PlayerEventLogs::GetDiscordWebhookUrlFromEventType(int32_t event_typ
}
// ensure there is a matching webhook to begin with
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;
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;
}
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
@@ -916,6 +931,10 @@ 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();
+12 -5
View File
@@ -73,9 +73,11 @@ 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);
[[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);
static std::string GetDiscordPayloadFromEvent(const PlayerEvent::PlayerEventContainer &e);
@@ -94,6 +96,12 @@ public:
std::vector<PlayerEventAaPurchaseRepository::PlayerEventAaPurchase> aa_purchase;
};
static PlayerEventLogs* Instance()
{
static PlayerEventLogs instance;
return &instance;
}
private:
struct EtlSettings {
bool enabled;
@@ -113,6 +121,7 @@ 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
@@ -126,6 +135,4 @@ public:
std::map<PlayerEvent::EventType, EtlSettings> &GetEtlSettings() { return m_etl_settings;}
};
extern PlayerEventLogs player_event_logs;
#endif //EQEMU_PLAYER_EVENT_LOGS_H
File diff suppressed because it is too large Load Diff
+18 -18
View File
@@ -21,8 +21,8 @@ void EvolvingItemsManager::LoadEvolvingItems() const
results.begin(),
results.end(),
std::inserter(
evolving_items_manager.GetEvolvingItemsCache(),
evolving_items_manager.GetEvolvingItemsCache().end()
EvolvingItemsManager::Instance()->GetEvolvingItemsCache(),
EvolvingItemsManager::Instance()->GetEvolvingItemsCache().end()
),
[](const ItemsEvolvingDetailsRepository::ItemsEvolvingDetails &x) {
return std::make_pair(x.item_id, x);
@@ -42,13 +42,13 @@ void EvolvingItemsManager::SetContentDatabase(Database *db)
double EvolvingItemsManager::CalculateProgression(const uint64 current_amount, const uint32 item_id)
{
if (!evolving_items_manager.GetEvolvingItemsCache().contains(item_id)) {
if (!EvolvingItemsManager::Instance()->GetEvolvingItemsCache().contains(item_id)) {
return 0;
}
return evolving_items_manager.GetEvolvingItemsCache().at(item_id).required_amount > 0
return EvolvingItemsManager::Instance()->GetEvolvingItemsCache().at(item_id).required_amount > 0
? static_cast<double>(current_amount)
/ static_cast<double>(evolving_items_manager.GetEvolvingItemsCache().at(item_id).required_amount) * 100
/ static_cast<double>(EvolvingItemsManager::Instance()->GetEvolvingItemsCache().at(item_id).required_amount) * 100
: 0;
}
@@ -73,7 +73,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 = evolving_items_manager.GetFinalItemID(inst);
e.final_item_id = EvolvingItemsManager::Instance()->GetFinalItemID(inst);
auto r = CharacterEvolvingItemsRepository::InsertOne(*m_db, e);
e.id = r.id;
@@ -96,20 +96,20 @@ uint32 EvolvingItemsManager::GetFinalItemID(const EQ::ItemInstance &inst) const
}
const auto start_iterator = std::ranges::find_if(
evolving_items_manager.GetEvolvingItemsCache().cbegin(),
evolving_items_manager.GetEvolvingItemsCache().cend(),
EvolvingItemsManager::Instance()->GetEvolvingItemsCache().cbegin(),
EvolvingItemsManager::Instance()->GetEvolvingItemsCache().cend(),
[&](const std::pair<uint32, ItemsEvolvingDetailsRepository::ItemsEvolvingDetails> &a) {
return a.second.item_evo_id == inst.GetEvolveLoreID();
}
);
if (start_iterator == std::end(evolving_items_manager.GetEvolvingItemsCache())) {
if (start_iterator == std::end(EvolvingItemsManager::Instance()->GetEvolvingItemsCache())) {
return 0;
}
const auto final_id = std::ranges::max_element(
start_iterator,
evolving_items_manager.GetEvolvingItemsCache().cend(),
EvolvingItemsManager::Instance()->GetEvolvingItemsCache().cend(),
[&](
const std::pair<uint32, ItemsEvolvingDetailsRepository::ItemsEvolvingDetails> &a,
const std::pair<uint32, ItemsEvolvingDetailsRepository::ItemsEvolvingDetails> &b
@@ -131,15 +131,15 @@ uint32 EvolvingItemsManager::GetNextEvolveItemID(const EQ::ItemInstance &inst) c
int8 const current_level = inst.GetEvolveLvl();
const auto iterator = std::ranges::find_if(
evolving_items_manager.GetEvolvingItemsCache().cbegin(),
evolving_items_manager.GetEvolvingItemsCache().cend(),
EvolvingItemsManager::Instance()->GetEvolvingItemsCache().cbegin(),
EvolvingItemsManager::Instance()->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(evolving_items_manager.GetEvolvingItemsCache())) {
if (iterator == std::end(EvolvingItemsManager::Instance()->GetEvolvingItemsCache())) {
return 0;
}
@@ -255,8 +255,8 @@ EvolveTransfer EvolvingItemsManager::DetermineTransferResults(
return ets;
}
auto evolving_details_inst_from = evolving_items_manager.GetEvolveItemDetails(inst_from.GetID());
auto evolving_details_inst_to = evolving_items_manager.GetEvolveItemDetails(inst_to.GetID());
auto evolving_details_inst_from = EvolvingItemsManager::Instance()->GetEvolveItemDetails(inst_from.GetID());
auto evolving_details_inst_to = EvolvingItemsManager::Instance()->GetEvolveItemDetails(inst_to.GetID());
if (!evolving_details_inst_from.id || !evolving_details_inst_to.id) {
return ets;
@@ -272,10 +272,10 @@ EvolveTransfer EvolvingItemsManager::DetermineTransferResults(
compatibility = 30;
}
xp = evolving_items_manager.GetTotalEarnedXP(inst_from) * compatibility / 100;
auto results = evolving_items_manager.GetNextItemByXP(inst_to, xp);
xp = EvolvingItemsManager::Instance()->GetTotalEarnedXP(inst_from) * compatibility / 100;
auto results = EvolvingItemsManager::Instance()->GetNextItemByXP(inst_to, xp);
ets.item_from_id = evolving_items_manager.GetFirstItemInLoreGroup(inst_from.GetEvolveLoreID());
ets.item_from_id = EvolvingItemsManager::Instance()->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;
+5 -2
View File
@@ -56,12 +56,15 @@ public:
std::map<uint32, ItemsEvolvingDetailsRepository::ItemsEvolvingDetails>& GetEvolvingItemsCache() { return m_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;
Database * m_db;
Database * m_content_db;
};
extern EvolvingItemsManager evolving_items_manager;
#endif //EVOLVING_H
+1 -1
View File
@@ -55,7 +55,7 @@ namespace EQ {
EQ_EXCEPT("IPC Mutex", "Could not create mutex.");
}
#else
std::string final_name = fmt::format("{}/{}.lock", path.GetSharedMemoryPath(), name);
std::string final_name = fmt::format("{}/{}.lock", PathManager::Instance()->GetSharedMemoryPath(), name);
#ifdef __DARWIN
#if __DARWIN_C_LEVEL < 200809L
+2 -2
View File
@@ -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 || material_slot < 0) {
if (m_ornament_hero_model == 0) {
return 0;
}
@@ -1799,7 +1799,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 : "None");
augment_names.push_back(augment ? augment->GetItem()->Name : "");
}
return augment_names;
+1 -1
View File
@@ -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 = evolving_items_manager.CalculateProgression(GetEvolveCurrentAmount(), GetID()); }
void CalculateEvolveProgression() const { m_evolving_details.progression = EvolvingItemsManager::Instance()->CalculateProgression(GetEvolveCurrentAmount(), GetID()); }
protected:
//////////////////////////
+40 -10
View File
@@ -1127,16 +1127,37 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream)
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) {
LogNetClient(
"Not resending packets for stream [{}] packets [{}] time_first_sent [{}] resend_delay [{}] m_acked_since_last_resend [{}]",
stream,
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(),
time_since_first_sent,
first_packet.resend_delay,
@@ -1146,15 +1167,16 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream)
}
}
if (LogSys.IsLogEnabled(Logs::Detail, Logs::Netcode)) {
if (EQEmuLogSys::Instance()->IsLogEnabled(Logs::General, Logs::NetClient)) {
size_t total_size = 0;
for (auto &e: s->sent_packets) {
total_size += e.second.packet.Length();
}
LogNetClient(
"Resending packets for stream [{}] packet count [{}] total packet size [{}] m_acked_since_last_resend [{}]",
stream,
LogNetClientDetail(
"Resending packets for m_endpoint [{}] m_port [{}] packet count [{}] total packet size [{}] m_acked_since_last_resend [{}]",
m_endpoint,
m_port,
s->sent_packets.size(),
total_size,
m_acked_since_last_resend
@@ -1165,9 +1187,12 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream)
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 m_resend_packets_sent [{}] max [{}] m_resend_bytes_sent [{}] max [{}]",
"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,
m_resend_packets_sent,
MAX_CLIENT_RECV_PACKETS_PER_WINDOW,
s->sent_packets.size(),
m_resend_bytes_sent,
MAX_CLIENT_RECV_BYTES_PER_WINDOW
);
@@ -1204,11 +1229,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();
@@ -1224,12 +1249,14 @@ 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)
@@ -1247,6 +1274,9 @@ 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)
+1
View File
@@ -186,6 +186,7 @@ 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 -1
View File
@@ -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(),
(LogSys.IsLogEnabled(Logs::Detail, Logs::PacketServerClient) ? DumpPacketToString(p) : "")
(EQEmuLogSys::Instance()->IsLogEnabled(Logs::Detail, Logs::PacketServerClient) ? DumpPacketToString(p) : "")
);
if (m_opcode_manager && *m_opcode_manager) {
+1 -1
View File
@@ -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 = LogSys.IsLogEnabled(Logs::Detail, Logs::PacketServerToServer);
const auto is_detail_enabled = EQEmuLogSys::Instance()->IsLogEnabled(Logs::Detail, Logs::PacketServerToServer);
if (opcode != ServerOP_KeepAlive || is_detail_enabled) {
LogPacketServerToServer(
"[{:#06x}] Size [{}] {}",
+2 -2
View File
@@ -78,7 +78,7 @@ namespace RoF
{
//create our opcode manager if we havent already
if (opcodes == nullptr) {
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
std::string opfile = fmt::format("{}/patch_{}.conf", PathManager::Instance()->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", path.GetPatchPath(), name);
std::string opfile = fmt::format("{}/patch_{}.conf", PathManager::Instance()->GetPatchPath(), name);
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
return;
+2 -2
View File
@@ -81,7 +81,7 @@ namespace RoF2
//create our opcode manager if we havent already
if (opcodes == nullptr) {
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
std::string opfile = fmt::format("{}/patch_{}.conf", PathManager::Instance()->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", path.GetPatchPath(), name);
std::string opfile = fmt::format("{}/patch_{}.conf", PathManager::Instance()->GetPatchPath(), name);
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
return;
+13 -13
View File
@@ -72,7 +72,7 @@ namespace SoD
{
//create our opcode manager if we havent already
if (opcodes == nullptr) {
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
std::string opfile = fmt::format("{}/patch_{}.conf", PathManager::Instance()->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", path.GetPatchPath(), name);
std::string opfile = fmt::format("{}/patch_{}.conf", PathManager::Instance()->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_8_END && serverSlot >= EQ::invbag::GENERAL_BAGS_BEGIN) {
SoDSlot = serverSlot + 11;
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::CURSOR_BAG_END && serverSlot >= EQ::invbag::CURSOR_BAG_BEGIN) {
SoDSlot = serverSlot - 9;
SoDSlot = serverSlot - (EQ::invbag::CURSOR_BAG_BEGIN - invbag::CURSOR_BAG_BEGIN);
}
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 + 1;
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));;
}
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 + 1;
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));
}
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;
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));
}
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 - 11;
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));
}
else if (sod_slot <= invbag::CURSOR_BAG_END && sod_slot >= invbag::CURSOR_BAG_BEGIN) {
server_slot = sod_slot + 9;
server_slot = sod_slot + (EQ::invbag::CURSOR_BAG_BEGIN - invbag::CURSOR_BAG_BEGIN);
}
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 - 1;
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));
}
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 - 1;
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));
}
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;
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));
}
else if (sod_slot <= invslot::WORLD_END && sod_slot >= invslot::WORLD_BEGIN) {
+13 -13
View File
@@ -71,7 +71,7 @@ namespace SoF
{
//create our opcode manager if we havent already
if (opcodes == nullptr) {
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
std::string opfile = fmt::format("{}/patch_{}.conf", PathManager::Instance()->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", path.GetPatchPath(), name);
std::string opfile = fmt::format("{}/patch_{}.conf", PathManager::Instance()->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_8_END && server_slot >= EQ::invbag::GENERAL_BAGS_BEGIN) {
sof_slot = server_slot + 11;
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::CURSOR_BAG_END && server_slot >= EQ::invbag::CURSOR_BAG_BEGIN) {
sof_slot = server_slot - 9;
sof_slot = server_slot - (EQ::invbag::CURSOR_BAG_BEGIN - invbag::CURSOR_BAG_BEGIN);
}
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 + 1;
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));
}
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 + 1;
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));
}
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;
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));
}
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 - 11;
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));;
}
else if (sof_slot <= invbag::CURSOR_BAG_END && sof_slot >= invbag::CURSOR_BAG_BEGIN) {
server_slot = sof_slot + 9;
server_slot = sof_slot + (EQ::invbag::CURSOR_BAG_BEGIN - invbag::CURSOR_BAG_BEGIN);
}
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 - 1;
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));;
}
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 - 1;
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));;
}
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;
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));;
}
else if (sof_slot <= invslot::WORLD_END && sof_slot >= invslot::WORLD_BEGIN) {
+14 -14
View File
@@ -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", path.GetPatchPath(), name);
std::string opfile = fmt::format("{}/patch_{}.conf", PathManager::Instance()->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", path.GetPatchPath(), name);
std::string opfile = fmt::format("{}/patch_{}.conf", PathManager::Instance()->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_8_END &&
else if (server_slot <= EQ::invbag::GENERAL_BAGS_END &&
server_slot >= EQ::invbag::GENERAL_BAGS_BEGIN) {
titanium_slot = server_slot;
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));
}
else if (server_slot <= EQ::invbag::CURSOR_BAG_END && server_slot >= EQ::invbag::CURSOR_BAG_BEGIN) {
titanium_slot = server_slot - 20;
titanium_slot = server_slot - (EQ::invbag::CURSOR_BAG_BEGIN - invbag::CURSOR_BAG_BEGIN);
}
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_16_END && server_slot >= EQ::invbag::BANK_BAGS_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::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;
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));
}
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;
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));
}
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;
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));
}
else if (titanium_slot <= invbag::CURSOR_BAG_END && titanium_slot >= invbag::CURSOR_BAG_BEGIN) {
server_slot = titanium_slot + 20;
server_slot = titanium_slot + (EQ::invbag::CURSOR_BAG_BEGIN - invbag::CURSOR_BAG_BEGIN);
}
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;
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));
}
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;
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));
}
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;
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));
}
else if (titanium_slot <= invslot::WORLD_END && titanium_slot >= invslot::WORLD_BEGIN) {
server_slot = titanium_slot;
+2 -2
View File
@@ -76,7 +76,7 @@ namespace UF
{
//create our opcode manager if we havent already
if (opcodes == nullptr) {
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
std::string opfile = fmt::format("{}/patch_{}.conf", PathManager::Instance()->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", path.GetPatchPath(), name);
std::string opfile = fmt::format("{}/patch_{}.conf", PathManager::Instance()->GetPatchPath(), name);
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
return;
+44 -23
View File
@@ -8,7 +8,7 @@
namespace fs = std::filesystem;
void PathManager::LoadPaths()
void PathManager::Init()
{
m_server_path = File::FindEqemuConfigPath();
@@ -48,10 +48,23 @@ void PathManager::LoadPaths()
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);
@@ -62,13 +75,10 @@ void PathManager::LoadPaths()
std::vector<std::pair<std::string, std::string>> paths = {
{"server", m_server_path},
{"logs", m_log_path},
{"lua mods", m_lua_mods_path},
{"lua_modules", m_lua_modules_path},
{"maps", m_maps_path},
{"lua mods", m_lua_mods_path},
{"patches", m_patch_path},
{"opcode", m_opcode_path},
{"plugins", m_plugins_path},
{"quests", m_quests_path},
{"shared_memory", m_shared_memory_path}
};
@@ -83,6 +93,17 @@ void PathManager::LoadPaths()
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));
}
@@ -96,21 +117,26 @@ 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;
@@ -126,11 +152,6 @@ 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;
+25 -15
View File
@@ -3,10 +3,17 @@
#include <string>
#include <vector>
class PathManager {
public:
void LoadPaths();
void Init();
static PathManager *Instance()
{
static PathManager instance;
return &instance;
}
[[nodiscard]] const std::string &GetLogPath() const;
[[nodiscard]] const std::string &GetLuaModsPath() const;
@@ -14,24 +21,27 @@ 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_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;
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;
};
extern PathManager path;
#endif //EQEMU_PATH_MANAGER_H
+9
View File
@@ -0,0 +1,9 @@
#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"
-34
View File
@@ -1,34 +0,0 @@
// types
#include <limits>
#include <string>
#include <cctype>
#include <sstream>
// containers
#include <iterator>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <list>
#include <vector>
// utilities
#include <iostream>
#include <cassert>
#include <cmath>
#include <memory>
#include <functional>
#include <algorithm>
#include <utility>
#include <tuple>
#include <fstream>
#include <cstdio>
// fmt
#include <fmt/format.h>
// lua
#include "lua.hpp"
#include <luabind/luabind.hpp>
#include <luabind/object.hpp>
+14
View File
@@ -0,0 +1,14 @@
#pragma once
// Lightweight, widely used
#include <string>
#include <vector>
#include <map>
#include <unordered_map>
#include <memory>
#include <limits>
#include <cstdint>
#include <cassert>
// fmt
#include <fmt/format.h>
+1
View File
@@ -1,6 +1,7 @@
#include <string>
#include <memory>
#include "process.h"
#include <fmt/format.h>
std::string Process::execute(const std::string &cmd)
{
+6
View File
@@ -116,6 +116,12 @@ 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,6 +70,7 @@ public:
uint32_t gm_exp;
uint32_t killed_by;
uint8_t rezzable;
std::string entity_variables;
};
static std::string PrimaryKey()
@@ -131,6 +132,7 @@ public:
"gm_exp",
"killed_by",
"rezzable",
"entity_variables",
};
}
@@ -188,6 +190,7 @@ public:
"gm_exp",
"killed_by",
"rezzable",
"entity_variables",
};
}
@@ -279,6 +282,7 @@ public:
e.gm_exp = 0;
e.killed_by = 0;
e.rezzable = 0;
e.entity_variables = "";
return e;
}
@@ -366,6 +370,7 @@ 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;
}
@@ -449,6 +454,7 @@ 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(
@@ -521,6 +527,7 @@ 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(
@@ -601,6 +608,7 @@ 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) + ")");
}
@@ -685,6 +693,7 @@ 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);
}
@@ -760,6 +769,7 @@ 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);
}
@@ -885,6 +895,7 @@ 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(
@@ -958,6 +969,7 @@ 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) + ")");
}
@@ -15,7 +15,7 @@
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
#include <cereal/cereal.hpp>
class BasePlayerEventLogSettingsRepository {
public:
struct PlayerEventLogSettings {
@@ -25,6 +25,20 @@ 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()
@@ -231,6 +231,21 @@ public:
return UpdateOne(db, corpse);
}
static int UpdateEntityVariables(Database& db, uint32 corpse_id, const std::string& json_string)
{
auto results = db.QueryDatabase(
fmt::format(
"UPDATE `{}` SET `entity_variables` = '{}' WHERE `{}` = {}",
TableName(),
Strings::Escape(json_string),
PrimaryKey(),
corpse_id
)
);
return results.Success() ? results.RowsAffected() : 0;
}
};
#endif //EQEMU_CHARACTER_CORPSES_REPOSITORY_H
@@ -167,6 +167,30 @@ public:
return zone_player_counts;
}
static std::vector<uint32_t> GetCharacterIDsByAccountID(
Database& db,
uint32_t account_id
)
{
std::vector<uint32_t> character_ids;
auto query = fmt::format(
"SELECT id FROM character_data WHERE account_id = {} AND deleted_at IS NULL",
account_id
);
auto results = db.QueryDatabase(query);
if (results.Success()) {
for (auto row : results) {
if (row[0]) {
character_ids.push_back(static_cast<uint32_t>(std::stoul(row[0])));
}
}
}
return character_ids;
}
};
#endif //EQEMU_CHARACTER_DATA_REPOSITORY_H
@@ -14,7 +14,7 @@ namespace ContentFilterCriteria {
table_prefix = table_prefix + ".";
}
int current_expansion_filter_criteria = content_service.GetCurrentExpansion();
int current_expansion_filter_criteria = WorldContentService::Instance()->GetCurrentExpansion();
if (current_expansion_filter_criteria == Expansion::EXPANSION_ALL) {
current_expansion_filter_criteria = Expansion::EXPANSION_FILTER_MAX;
}
@@ -33,8 +33,8 @@ namespace ContentFilterCriteria {
table_prefix
);
std::vector<std::string> flags_disabled = content_service.GetContentFlagsDisabled();
std::vector<std::string> flags_enabled = content_service.GetContentFlagsEnabled();
std::vector<std::string> flags_disabled = WorldContentService::Instance()->GetContentFlagsDisabled();
std::vector<std::string> flags_enabled = WorldContentService::Instance()->GetContentFlagsEnabled();
std::string flags_in_filter_enabled;
std::string flags_in_filter_disabled;
if (!flags_enabled.empty()) {
+59 -2
View File
@@ -43,6 +43,47 @@ public:
* method and encapsulate filters there
*/
template<typename T1, typename T2, typename T3, typename T4>
static std::vector<std::string> join_tuple(
const std::string &glue,
const std::pair<char, char> &encapsulation,
const std::vector<std::tuple<T1, T2, T3, T4>> &src
)
{
if (src.empty()) {
return {};
}
std::vector<std::string> output;
for (const std::tuple<T1, T2, T3, T4> &src_iter: src) {
output.emplace_back(
fmt::format(
"{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
encapsulation.first,
std::get<0>(src_iter),
encapsulation.second,
glue,
encapsulation.first,
std::get<1>(src_iter),
encapsulation.second,
glue,
encapsulation.first,
std::get<2>(src_iter),
encapsulation.second,
glue,
encapsulation.first,
std::get<3>(src_iter),
encapsulation.second
)
);
}
return output;
}
// Custom extended repository methods here
static std::vector<std::string> GetRuleNames(Database &db, int rule_set_id)
{
@@ -87,12 +128,28 @@ public:
return v;
}
template<typename T>
static std::string
ImplodePair(const std::string &glue, const std::pair<char, char> &encapsulation, const std::vector<T> &src)
{
if (src.empty()) {
return {};
}
std::ostringstream oss;
for (const T &src_iter: src) {
oss << encapsulation.first << src_iter << encapsulation.second << glue;
}
std::string output(oss.str());
output.resize(output.size() - glue.size());
return output;
}
static bool DeleteOrphanedRules(Database& db, std::vector<std::string>& v)
{
const auto query = fmt::format(
"DELETE FROM {} WHERE rule_name IN ({})",
TableName(),
Strings::ImplodePair(",", std::pair<char, char>('\'', '\''), v)
ImplodePair(",", std::pair<char, char>('\'', '\''), v)
);
return db.QueryDatabase(query).Success();
@@ -103,7 +160,7 @@ public:
const auto query = fmt::format(
"REPLACE INTO {} (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES {}",
TableName(),
Strings::ImplodePair(
ImplodePair(
",",
std::pair<char, char>('(', ')'),
join_tuple(",", std::pair<char, char>('\'', '\''), v)
+13
View File
@@ -502,6 +502,19 @@ bool RuleManager::UpdateInjectedRules(Database *db, const std::string &rule_set_
}
}
// update rules in the database where the description is different
for (auto &e : RuleValuesRepository::All(*db)) {
auto i = rule_data.find(e.rule_name);
if (i != rule_data.end()) {
// if notes are different, update them
if (i->second.second != nullptr && *i->second.second != e.notes) {
LogInfo("Updating rule [{}] notes to [{}]", i->first, *i->second.second);
e.notes = *i->second.second;
RuleValuesRepository::ReplaceOne(*db, e);
}
}
}
if (injected_rule_entries.size()) {
if (!RuleValuesRepository::InjectRules(*db, injected_rule_entries)) {
return false;
+7
View File
@@ -233,6 +233,12 @@ RULE_BOOL(Character, SneakAlwaysSucceedOver100, false, "When sneak skill is over
RULE_INT(Character, BandolierSwapDelay, 0, "Bandolier swap delay in milliseconds, default is 0")
RULE_BOOL(Character, EnableHackedFastCampForGM, false, "Enables hacked fast camp for GM clients, if the GM doesn't have a hacked client they'll camp like normal")
RULE_BOOL(Character, AlwaysAllowNameChange, false, "Enable this option to allow /changename to work without enabling a name change via scripts.")
RULE_BOOL(Character, EnableAutoAFK, false, "Enable or disable the auto AFK feature, cuts down on packet spam")
RULE_BOOL(Character, AutoIdleFilterPackets, true, "Enable or disable filtering packets when auto AFK is enabled, heavily cuts down on packet spam in zones with lots of players")
RULE_INT(Character, SecondsBeforeIdleCombatZone, 600, "Seconds before a player is considered idle in combat zones (600 = 10 minutes)")
RULE_INT(Character, SecondsBeforeIdleNonCombatZone, 60, "Seconds before a player is considered idle in non-combat zones (60 = 1 minute)")
RULE_INT(Character, SecondsBeforeAFKCombatZone, 1800, "Seconds before a player is considered AFK in combat zones (1800 = 30 minutes)")
RULE_INT(Character, SecondsBeforeAFKNonCombatZone, 600, "Seconds before a player is considered AFK in non-combat zones (600 = 10 minutes)")
RULE_CATEGORY_END()
RULE_CATEGORY(Mercs)
@@ -1073,6 +1079,7 @@ RULE_CATEGORY(Logging)
RULE_BOOL(Logging, PrintFileFunctionAndLine, false, "Ex: [World Server] [net.cpp::main:309] Loading variables...")
RULE_BOOL(Logging, WorldGMSayLogging, true, "Relay worldserver logging to zone processes via GM say output")
RULE_BOOL(Logging, PlayerEventsQSProcess, false, "Have query server process player events instead of world. Useful when wanting to use a dedicated server and database for processing player events on separate disk")
RULE_STRING(Logging, PlayerEventsIgnoreGMCommands, "help,show", "This is a comma delimited list of commands to ignore when recording GM command player events.")
RULE_INT(Logging, BatchPlayerEventProcessIntervalSeconds, 5, "This is the interval in which player events are processed in world or qs")
RULE_INT(Logging, BatchPlayerEventProcessChunkSize, 10000, "This is the cap of events that can be inserted into the queue before a force flush. This is to keep from hitting MySQL max_allowed_packet and killing the connection")
RULE_CATEGORY_END()
+3 -1
View File
@@ -273,8 +273,9 @@
#define ServerOP_WWTaskUpdate 0x4758
// player events
#define ServerOP_QSSendQuery 0x5000
#define ServerOP_QSSendQuery 0x5000
#define ServerOP_PlayerEvent 0x5100
#define ServerOP_SendPlayerEventSettings 0x5101
enum {
CZUpdateType_Character,
@@ -1778,6 +1779,7 @@ struct BazaarPurchaseMessaging_Struct {
uint32 id;
};
#pragma pack()
#endif
+1 -1
View File
@@ -48,7 +48,7 @@ enum class SharedTaskRequestGroupType {
struct ServerSharedTaskRequest_Struct {
uint32 requested_character_id;
uint32 requested_task_id;
uint32 requested_npc_type_id; // original task logic passthrough
uint32 requested_npc_entity_id; // original task logic passthrough
uint32 accept_time;
};
+54 -6
View File
@@ -824,7 +824,7 @@ bool SharedDatabase::GetInventory(Client *c)
e.character_id = char_id;
e.item_id = item_id;
e.equipped = inst->GetEvolveEquipped();
e.final_item_id = evolving_items_manager.GetFinalItemID(*inst);
e.final_item_id = EvolvingItemsManager::Instance()->GetFinalItemID(*inst);
auto r = CharacterEvolvingItemsRepository::InsertOne(*this, e);
e.id = r.id;
@@ -974,7 +974,7 @@ bool SharedDatabase::LoadItems(const std::string &prefix) {
const auto Config = EQEmuConfig::get();
EQ::IPCMutex mutex("items");
mutex.Lock();
std::string file_name = fmt::format("{}/{}{}", path.GetSharedMemoryPath(), prefix, std::string("items"));
std::string file_name = fmt::format("{}/{}{}", PathManager::Instance()->GetSharedMemoryPath(), prefix, std::string("items"));
items_mmf = std::make_unique<EQ::MemoryMappedFile>(file_name);
items_hash = std::make_unique<EQ::FixedMemoryHashSet<EQ::ItemData>>(static_cast<uint8*>(items_mmf->Get()), items_mmf->Size());
mutex.Unlock();
@@ -1544,12 +1544,60 @@ bool SharedDatabase::GetCommandSettings(std::map<std::string, std::pair<uint8, s
return true;
}
template<typename T1, typename T2>
inline std::vector<std::string> join_pair(
const std::string &glue,
const std::pair<char, char> &encapsulation,
const std::vector<std::pair<T1, T2>> &src
)
{
if (src.empty()) {
return {};
}
std::vector<std::string> output;
for (const std::pair<T1, T2> &src_iter: src) {
output.emplace_back(
fmt::format(
"{}{}{}{}{}{}{}",
encapsulation.first,
src_iter.first,
encapsulation.second,
glue,
encapsulation.first,
src_iter.second,
encapsulation.second
)
);
}
return output;
}
template<typename T>
inline std::string
ImplodePair(const std::string &glue, const std::pair<char, char> &encapsulation, const std::vector<T> &src)
{
if (src.empty()) {
return {};
}
std::ostringstream oss;
for (const T &src_iter: src) {
oss << encapsulation.first << src_iter << encapsulation.second << glue;
}
std::string output(oss.str());
output.resize(output.size() - glue.size());
return output;
}
bool SharedDatabase::UpdateInjectedCommandSettings(const std::vector<std::pair<std::string, uint8>> &injected)
{
if (injected.size()) {
const std::string query = fmt::format(
"REPLACE INTO `command_settings`(`command`, `access`) VALUES {}",
Strings::ImplodePair(
ImplodePair(
",",
std::pair<char, char>('(', ')'),
join_pair(",", std::pair<char, char>('\'', '\''), injected)
@@ -1576,7 +1624,7 @@ bool SharedDatabase::UpdateOrphanedCommandSettings(const std::vector<std::string
if (orphaned.size()) {
std::string query = fmt::format(
"DELETE FROM `command_settings` WHERE `command` IN ({})",
Strings::ImplodePair(",", std::pair<char, char>('\'', '\''), orphaned)
ImplodePair(",", std::pair<char, char>('\'', '\''), orphaned)
);
auto results = QueryDatabase(query);
@@ -1586,7 +1634,7 @@ bool SharedDatabase::UpdateOrphanedCommandSettings(const std::vector<std::string
query = fmt::format(
"DELETE FROM `command_subsettings` WHERE `parent_command` IN ({})",
Strings::ImplodePair(",", std::pair<char, char>('\'', '\''), orphaned)
ImplodePair(",", std::pair<char, char>('\'', '\''), orphaned)
);
auto results_two = QueryDatabase(query);
@@ -1665,7 +1713,7 @@ bool SharedDatabase::LoadSpells(const std::string &prefix, int32 *records, const
EQ::IPCMutex mutex("spells");
mutex.Lock();
std::string file_name = fmt::format("{}/{}{}", path.GetSharedMemoryPath(), prefix, std::string("spells"));
std::string file_name = fmt::format("{}/{}{}", PathManager::Instance()->GetSharedMemoryPath(), prefix, std::string("spells"));
spells_mmf = std::make_unique<EQ::MemoryMappedFile>(file_name);
LogInfo("Loading [{}]", file_name);
*records = *static_cast<uint32*>(spells_mmf->Get());
+6 -2
View File
@@ -16,12 +16,16 @@ public:
static int32_t GetSkillCapMaxLevel(uint8 class_id, EQ::skills::SkillType skill_id);
SkillCaps *SetContentDatabase(Database *db);
static SkillCaps* Instance()
{
static SkillCaps instance;
return &instance;
}
private:
Database *m_content_database{};
std::map<uint64, SkillCapsRepository::SkillCaps> m_skill_caps = {};
};
extern SkillCaps skill_caps;
#endif //CODE_SKILL_CAPS_H
+1
View File
@@ -358,6 +358,7 @@ bool RequiresStackCheck(uint16 spell_type) {
case BotSpellTypes::CompleteHeal:
case BotSpellTypes::PetCompleteHeals:
case BotSpellTypes::GroupCompleteHeals:
case BotSpellTypes::Resurrect:
return false;
default:
return true;
+20
View File
@@ -34,6 +34,7 @@
*/
#include "strings.h"
#include <cereal/external/rapidjson/document.h>
#include <fmt/format.h>
#include <algorithm>
#include <cctype>
@@ -41,6 +42,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <sstream>
#include <random>
#include <string>
@@ -49,6 +51,12 @@
#include "strings_legacy.cpp" // legacy c functions
#include "strings_misc.cpp" // anything non "Strings" scoped
#ifdef _WINDOWS
#include <ctype.h>
#include <functional>
#include <algorithm>
#endif
std::string Strings::Random(size_t length)
{
static auto &chrs = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
@@ -701,6 +709,18 @@ std::string &Strings::Trim(std::string &str, const std::string &chars)
return LTrim(RTrim(str, chars), chars);
}
const std::string NUM_TO_ENGLISH_X[] = {
"", "One ", "Two ", "Three ", "Four ",
"Five ", "Six ", "Seven ", "Eight ", "Nine ", "Ten ", "Eleven ",
"Twelve ", "Thirteen ", "Fourteen ", "Fifteen ",
"Sixteen ", "Seventeen ", "Eighteen ", "Nineteen "
};
const std::string NUM_TO_ENGLISH_Y[] = {
"", "", "Twenty ", "Thirty ", "Forty ",
"Fifty ", "Sixty ", "Seventy ", "Eighty ", "Ninety "
};
// Function to convert single digit or two digit number into words
std::string Strings::ConvertToDigit(int n, const std::string& suffix)
{
+3 -193
View File
@@ -36,53 +36,19 @@
#define _STRINGUTIL_H_
#include <charconv>
#include <sstream>
#include <string.h>
#include <cstring>
#include <string_view>
#include <string>
#include <vector>
#include <cstdarg>
#include <tuple>
#include <type_traits>
#include <fmt/format.h>
#include <cereal/external/rapidjson/document.h>
#ifndef _WIN32
// this doesn't appear to affect linux-based systems..need feedback for _WIN64
#endif
#ifdef _WINDOWS
#ifdef _WIN32
#include <ctype.h>
#include <functional>
#include <algorithm>
#endif
#include "types.h"
namespace detail {
// template magic to check if std::from_chars floating point functions exist
template <typename T, typename = void>
struct has_from_chars_float : std::false_type { };
// basically it "uses" this template if they do exist because reasons
template <typename T>
struct has_from_chars_float < T,
std::void_t<decltype(std::from_chars(std::declval<const char *>(), std::declval<const char *>(),
std::declval<T &>()))>> : std::true_type { };
}; // namespace detail
namespace EQ {
// lame -- older GCC's didn't define this, clang's libc++ however does, even though they lack FP support
#if defined(__GNUC__) && (__GNUC__ < 11) && !defined(__clang__)
enum class chars_format {
scientific = 1, fixed = 2, hex = 4, general = fixed | scientific
};
#else
using chars_format = std::chars_format;
#endif
}; // namespace EQ
class Strings {
public:
static bool Contains(std::vector<std::string> container, const std::string& element);
@@ -133,61 +99,6 @@ public:
static bool BeginsWith(const std::string& subject, const std::string& search);
static bool EndsWith(const std::string& subject, const std::string& search);
static std::string ZoneTime(const uint8 hours, const uint8 minutes);
template<typename T>
static std::string
ImplodePair(const std::string &glue, const std::pair<char, char> &encapsulation, const std::vector<T> &src)
{
if (src.empty()) {
return {};
}
std::ostringstream oss;
for (const T &src_iter: src) {
oss << encapsulation.first << src_iter << encapsulation.second << glue;
}
std::string output(oss.str());
output.resize(output.size() - glue.size());
return output;
}
// basic string_view overloads that just use std stuff since they work!
template <typename T>
std::enable_if_t<std::is_floating_point_v<T> && detail::has_from_chars_float<T>::value, std::from_chars_result>
static from_chars(std::string_view str, T& value, EQ::chars_format fmt = EQ::chars_format::general)
{
return std::from_chars(str.data(), str.data() + str.size(), value, fmt);
}
template <typename T>
std::enable_if_t<std::is_integral_v<T>, std::from_chars_result>
static from_chars(std::string_view str, T& value, int base = 10)
{
return std::from_chars(str.data(), str.data() + str.size(), value, base);
}
// fallback versions of floating point in case they're not implemented
// TODO: add error handling ...
// This does have to allocate since from_chars doesn't need a null terminated string and neither does string_view
template <typename T>
std::enable_if_t<std::is_floating_point_v<T> && !detail::has_from_chars_float<T>::value && std::is_same_v<T, float>, std::from_chars_result>
static from_chars(std::string_view str, T& value, EQ::chars_format fmt = EQ::chars_format::general)
{
std::from_chars_result res{};
std::string tmp_str(str.data(), str.size());
value = strtof(tmp_str.data(), nullptr);
return res;
}
template <typename T>
std::enable_if_t<std::is_floating_point_v<T> && !detail::has_from_chars_float<T>::value && std::is_same_v<T, double>, std::from_chars_result>
static from_chars(std::string_view str, T& value, EQ::chars_format fmt = EQ::chars_format::general)
{
std::from_chars_result res{};
std::string tmp_str(str.data(), str.size());
value = strtod(tmp_str.data(), nullptr);
return res;
}
static std::string Slugify(const std::string &input, const std::string &separator = "-");
static bool IsValidJson(const std::string& json);
};
@@ -199,93 +110,6 @@ const std::string vStringFormat(const char *format, va_list args);
// Used for grid nodes, as NPC names remove numerals.
// But general purpose
const std::string NUM_TO_ENGLISH_X[] = {
"", "One ", "Two ", "Three ", "Four ",
"Five ", "Six ", "Seven ", "Eight ", "Nine ", "Ten ", "Eleven ",
"Twelve ", "Thirteen ", "Fourteen ", "Fifteen ",
"Sixteen ", "Seventeen ", "Eighteen ", "Nineteen "
};
const std::string NUM_TO_ENGLISH_Y[] = {
"", "", "Twenty ", "Thirty ", "Forty ",
"Fifty ", "Sixty ", "Seventy ", "Eighty ", "Ninety "
};
// _WIN32 builds require that #include<fmt/format.h> be included in whatever code file the invocation is made from (no header files)
template<typename T1, typename T2>
std::vector<std::string> join_pair(
const std::string &glue,
const std::pair<char, char> &encapsulation,
const std::vector<std::pair<T1, T2>> &src
)
{
if (src.empty()) {
return {};
}
std::vector<std::string> output;
for (const std::pair<T1, T2> &src_iter: src) {
output.emplace_back(
fmt::format(
"{}{}{}{}{}{}{}",
encapsulation.first,
src_iter.first,
encapsulation.second,
glue,
encapsulation.first,
src_iter.second,
encapsulation.second
)
);
}
return output;
}
// _WIN32 builds require that #include<fmt/format.h> be included in whatever code file the invocation is made from (no header files)
template<typename T1, typename T2, typename T3, typename T4>
std::vector<std::string> join_tuple(
const std::string &glue,
const std::pair<char, char> &encapsulation,
const std::vector<std::tuple<T1, T2, T3, T4>> &src
)
{
if (src.empty()) {
return {};
}
std::vector<std::string> output;
for (const std::tuple<T1, T2, T3, T4> &src_iter: src) {
output.emplace_back(
fmt::format(
"{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
encapsulation.first,
std::get<0>(src_iter),
encapsulation.second,
glue,
encapsulation.first,
std::get<1>(src_iter),
encapsulation.second,
glue,
encapsulation.first,
std::get<2>(src_iter),
encapsulation.second,
glue,
encapsulation.first,
std::get<3>(src_iter),
encapsulation.second
)
);
}
return output;
}
// misc functions
std::string SanitizeWorldServerName(std::string server_long_name);
std::vector<std::string> GetBadWords();
@@ -310,18 +134,4 @@ std::string FormatName(const std::string &char_name);
bool IsAllowedWorldServerCharacterList(char c);
void SanitizeWorldServerName(char *name);
template<typename InputIterator, typename OutputIterator>
auto CleanMobName(InputIterator first, InputIterator last, OutputIterator result)
{
for (; first != last; ++first) {
if (*first == '_') {
*result = ' ';
}
else if (isalpha(*first) || *first == '`') {
*result = *first;
}
}
return result;
}
#endif
+3 -2
View File
@@ -25,7 +25,7 @@
// Build variables
// these get injected during the build pipeline
#define CURRENT_VERSION "23.6.0-dev" // always append -dev to the current version for custom-builds
#define CURRENT_VERSION "23.8.1-dev" // always append -dev to the current version for custom-builds
#define LOGIN_VERSION "0.8.0"
#define COMPILE_DATE __DATE__
#define COMPILE_TIME __TIME__
@@ -42,8 +42,9 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9323
#define CURRENT_BINARY_DATABASE_VERSION 9325
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9054
#define CUSTOM_BINARY_DATABASE_VERSION 0
#endif
+13 -10
View File
@@ -104,36 +104,39 @@ public:
uint8 GetZoneIdleWhenEmpty(uint32 zone_id, int version = 0);
uint32 GetZoneSecondsBeforeIdle(uint32 zone_id, int version = 0);
static ZoneStore* Instance()
{
static ZoneStore instance;
return &instance;
}
private:
std::vector<ZoneRepository::Zone> m_zones;
};
extern ZoneStore zone_store;
/**
* Global helpers
*/
inline uint32 ZoneID(const char *in_zone_name) { return zone_store.GetZoneID(in_zone_name); }
inline uint32 ZoneID(const std::string& zone_name) { return zone_store.GetZoneID(zone_name); }
inline uint32 ZoneID(const char *in_zone_name) { return ZoneStore::Instance()->GetZoneID(in_zone_name); }
inline uint32 ZoneID(const std::string& zone_name) { return ZoneStore::Instance()->GetZoneID(zone_name); }
inline const char *ZoneName(uint32 zone_id, bool error_unknown = false)
{
return zone_store.GetZoneName(
return ZoneStore::Instance()->GetZoneName(
zone_id,
error_unknown
);
}
inline const char *ZoneLongName(uint32 zone_id, bool error_unknown = false)
{
return zone_store.GetZoneLongName(
return ZoneStore::Instance()->GetZoneLongName(
zone_id,
error_unknown
);
}
inline ZoneRepository::Zone *GetZone(uint32 zone_id, int version = 0) { return zone_store.GetZone(zone_id, version); };
inline ZoneRepository::Zone *GetZone(const char *in_zone_name) { return zone_store.GetZone(in_zone_name); };
inline ZoneRepository::Zone *GetZone(uint32 zone_id, int version = 0) { return ZoneStore::Instance()->GetZone(zone_id, version); };
inline ZoneRepository::Zone *GetZone(const char *in_zone_name) { return ZoneStore::Instance()->GetZone(in_zone_name); };
inline ZoneRepository::Zone *GetZone(const char *in_zone_name, int version = 0)
{
return zone_store.GetZone(
return ZoneStore::Instance()->GetZone(
ZoneID(
in_zone_name
), version
@@ -141,7 +144,7 @@ inline ZoneRepository::Zone *GetZone(const char *in_zone_name, int version = 0)
};
inline ZoneRepository::Zone *GetZoneVersionWithFallback(uint32 zone_id, int version = 0)
{
return zone_store.GetZoneWithFallback(
return ZoneStore::Instance()->GetZoneWithFallback(
zone_id,
version
);
+3 -6
View File
@@ -33,19 +33,16 @@
#include <signal.h>
#include <time.h>
EQEmuLogSys LogSys;
PathManager path;
bool RunLoops = false;
void CatchSignal(int sig_num);
int main(int argc, char *argv[]) {
RegisterExecutablePlatform(ExePlatformLaunch);
LogSys.LoadLogSettingsDefaults();
EQEmuLogSys::Instance()->LoadLogSettingsDefaults();
set_exception_handler();
path.LoadPaths();
PathManager::Instance()->Init();
std::string launcher_name;
if(argc == 2) {
@@ -169,7 +166,7 @@ int main(int argc, char *argv[]) {
delete zone->second;
}
LogSys.CloseFileLogs();
EQEmuLogSys::Instance()->CloseFileLogs();
return 0;
}
+1 -1
View File
@@ -25,7 +25,7 @@ bool Client::Process()
OpcodeManager::EmuToName(app->GetOpcode()),
o->EmuToEQ(app->GetOpcode()) == 0 ? app->GetProtocolOpcode() : o->EmuToEQ(app->GetOpcode()),
app->Size(),
(LogSys.IsLogEnabled(Logs::Detail, Logs::PacketClientServer) ? DumpPacketToString(app) : "")
(EQEmuLogSys::Instance()->IsLogEnabled(Logs::Detail, Logs::PacketClientServer) ? DumpPacketToString(app) : "")
);
if (m_client_status == cs_failed_to_login) {
+3 -3
View File
@@ -94,7 +94,7 @@ ClientManager::ClientManager()
std::string opcodes_path = fmt::format(
"{}/{}",
path.GetOpcodePath(),
PathManager::Instance()->GetOpcodePath(),
"login_opcodes.conf"
);
@@ -131,7 +131,7 @@ ClientManager::ClientManager()
opcodes_path = fmt::format(
"{}/{}",
path.GetOpcodePath(),
PathManager::Instance()->GetOpcodePath(),
"login_opcodes_sod.conf"
);
@@ -169,7 +169,7 @@ ClientManager::ClientManager()
opcodes_path = fmt::format(
"{}/{}",
path.GetOpcodePath(),
PathManager::Instance()->GetOpcodePath(),
"login_opcodes_larion.conf"
);
+8 -12
View File
@@ -22,12 +22,8 @@
#include <thread>
LoginServer server;
EQEmuLogSys LogSys;
bool run_server = true;
PathManager path;
Database database;
PlayerEventLogs player_event_logs;
ZoneStore zone_store;
void CatchSignal(int sig_num)
{
@@ -52,7 +48,7 @@ void LoadDatabaseConnection()
void LoadServerConfig()
{
server.config = EQ::JsonConfigFile::Load(
fmt::format("{}/login.json", path.GetServerPath())
fmt::format("{}/login.json", PathManager::Instance()->GetServerPath())
);
LogInfo("Config System Init");
@@ -159,21 +155,21 @@ int main(int argc, char **argv)
LogInfo("Logging System Init");
if (argc == 1) {
LogSys.LoadLogSettingsDefaults();
EQEmuLogSys::Instance()->LoadLogSettingsDefaults();
}
path.LoadPaths();
PathManager::Instance()->Init();
// command handler
if (argc > 1) {
LogSys.SilenceConsoleLogging();
EQEmuLogSys::Instance()->SilenceConsoleLogging();
LoadServerConfig();
LoadDatabaseConnection();
LogSys.LoadLogSettingsDefaults();
LogSys.log_settings[Logs::Debug].log_to_console = static_cast<uint8>(Logs::General);
LogSys.log_settings[Logs::Debug].is_category_enabled = 1;
EQEmuLogSys::Instance()->LoadLogSettingsDefaults();
EQEmuLogSys::Instance()->log_settings[Logs::Debug].log_to_console = static_cast<uint8>(Logs::General);
EQEmuLogSys::Instance()->log_settings[Logs::Debug].is_category_enabled = 1;
LoginserverCommandHandler::CommandHandler(argc, argv);
}
@@ -182,7 +178,7 @@ int main(int argc, char **argv)
LoadDatabaseConnection();
if (argc == 1) {
LogSys.SetDatabase(&database)
EQEmuLogSys::Instance()->SetDatabase(&database)
->SetLogPath("logs")
->LoadLogDatabaseSettings()
->StartFileLogs();
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "eqemu-server",
"version": "23.6.0",
"version": "23.8.1",
"repository": {
"type": "git",
"url": "https://github.com/EQEmu/Server.git"
+6
View File
@@ -44,6 +44,12 @@ public:
bool LoadDatabase();
void HandlePacket(ServerPacket *pack);
void ExpireEntries();
static LFGuildManager* Instance()
{
static LFGuildManager instance;
return &instance;
}
private:
void SendPlayerMatches(uint32 FromZoneID, uint32 FromInstanceID, char *From, uint32 FromLevel, uint32 ToLevel, uint32 MinAA, uint32 TimeZone, uint32 Classes);
void SendGuildMatches(uint32 FromZoneID, uint32 FromInstanceID, char *From, uint32 Level, uint32 AAPoints, uint32 TimeZone, uint32 Class);
+11 -19
View File
@@ -20,23 +20,15 @@
#include "../common/net/console_server.h"
#include "../queryserv/zonelist.h"
#include "../queryserv/zoneserver.h"
#include "../common/discord/discord_manager.h"
volatile bool RunLoops = true;
QSDatabase qs_database;
Database database;
LFGuildManager lfguildmanager;
std::string WorldShortName;
const queryservconfig *Config;
WorldServer *worldserver = 0;
EQEmuLogSys LogSys;
PathManager path;
ZoneStore zone_store;
PlayerEventLogs player_event_logs;
ZSList zs_list;
uint32 numzones = 0;
DiscordManager discord_manager;
void CatchSignal(int sig_num)
{
@@ -46,11 +38,11 @@ void CatchSignal(int sig_num)
int main()
{
RegisterExecutablePlatform(ExePlatformQueryServ);
LogSys.LoadLogSettingsDefaults();
EQEmuLogSys::Instance()->LoadLogSettingsDefaults();
set_exception_handler();
Timer LFGuildExpireTimer(60000);
path.LoadPaths();
PathManager::Instance()->Init();
LogInfo("Starting EQEmu QueryServ");
if (!queryservconfig::LoadConfig()) {
@@ -85,8 +77,8 @@ int main()
return 1;
}
LogSys.SetDatabase(&database)
->SetLogPath(path.GetLogPath())
EQEmuLogSys::Instance()->SetDatabase(&database)
->SetLogPath(PathManager::Instance()->GetLogPath())
->LoadLogDatabaseSettings()
->StartFileLogs();
@@ -129,7 +121,7 @@ int main()
server_connection->OnConnectionIdentified(
"Zone", [&console](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
numzones++;
zs_list.Add(new ZoneServer(connection, console.get()));
ZSList::Instance()->Add(new ZoneServer(connection, console.get()));
LogInfo(
"New Zone Server connection from [{}] at [{}:{}] zone_count [{}]",
@@ -144,7 +136,7 @@ int main()
server_connection->OnConnectionRemoved(
"Zone", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
numzones--;
zs_list.Remove(connection->GetUUID());
ZSList::Instance()->Remove(connection->GetUUID());
LogInfo(
"Removed Zone Server connection from [{}] total zone_count [{}]",
@@ -159,10 +151,10 @@ int main()
worldserver->Connect();
/* Load Looking For Guild Manager */
lfguildmanager.LoadDatabase();
LFGuildManager::Instance()->LoadDatabase();
Timer player_event_process_timer(1000);
player_event_logs.SetDatabase(&qs_database)->Init();
PlayerEventLogs::Instance()->SetDatabase(&qs_database)->Init();
auto loop_fn = [&](EQ::Timer *t) {
Timer::SetCurrentTime();
@@ -173,11 +165,11 @@ int main()
}
if (LFGuildExpireTimer.Check()) {
lfguildmanager.ExpireEntries();
LFGuildManager::Instance()->ExpireEntries();
}
if (player_event_process_timer.Check()) {
player_event_logs.Process();
PlayerEventLogs::Instance()->Process();
}
};
@@ -187,7 +179,7 @@ int main()
EQ::EventLoop::Get().Run();
safe_delete(worldserver);
LogSys.CloseFileLogs();
EQEmuLogSys::Instance()->CloseFileLogs();
}
void UpdateWindowTitle(char *iNewTitle)
+6 -4
View File
@@ -21,10 +21,11 @@
#include <string.h>
#include <time.h>
#include "zonelist.h"
extern WorldServer worldserver;
extern const queryservconfig *Config;
extern QSDatabase qs_database;
extern LFGuildManager lfguildmanager;
WorldServer::WorldServer()
{
@@ -76,8 +77,9 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
case ServerOP_ServerReloadRequest: {
auto o = (ServerReload::Request*) p.Data();
if (o->type == ServerReload::Type::Logs) {
LogSys.LoadLogDatabaseSettings();
player_event_logs.ReloadSettings();
EQEmuLogSys::Instance()->LoadLogDatabaseSettings();
PlayerEventLogs::Instance()->ReloadSettings();
ZSList::Instance()->SendPlayerEventLogSettings();
}
break;
@@ -112,7 +114,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
pack.pBuffer = (uchar *) p.Data();
pack.opcode = opcode;
pack.size = (uint32) p.Length();
lfguildmanager.HandlePacket(&pack);
LFGuildManager::Instance()->HandlePacket(&pack);
pack.pBuffer = nullptr;
break;
}
+9
View File
@@ -5,6 +5,8 @@
void ZSList::Add(ZoneServer* zoneserver) {
zone_server_list.emplace_back(std::unique_ptr<ZoneServer>(zoneserver));
zoneserver->SetIsZoneConnected(true);
zoneserver->SendPlayerEventLogSettings();
}
void ZSList::Remove(const std::string &uuid)
@@ -18,3 +20,10 @@ void ZSList::Remove(const std::string &uuid)
iter++;
}
}
void ZSList::SendPlayerEventLogSettings()
{
for (auto &zs : zone_server_list) {
zs->SendPlayerEventLogSettings();
}
}
+11 -4
View File
@@ -6,15 +6,22 @@
#include <vector>
#include <memory>
#include <list>
#include "zoneserver.h"
class WorldTCPConnection;
class ZoneServer;
class ZSList {
public:
std::list<std::unique_ptr<ZoneServer>> &GetZsList() { return zone_server_list; }
void Add(ZoneServer *zoneserver);
void Remove(const std::string &uuid);
std::list<std::unique_ptr<ZoneServer>>& GetZsList() { return zone_server_list; }
void Add(ZoneServer* zoneserver);
void Remove(const std::string& uuid);
void SendPlayerEventLogSettings();
static ZSList* Instance()
{
static ZSList instance;
return &instance;
}
private:
std::list<std::unique_ptr<ZoneServer>> zone_server_list;
+26 -4
View File
@@ -5,8 +5,6 @@
#include "../common/events/player_event_logs.h"
#include "../common/discord/discord_manager.h"
extern DiscordManager discord_manager;
ZoneServer::ZoneServer(
std::shared_ptr<EQ::Net::ServertalkServerConnection> in_connection,
EQ::Net::ConsoleServer *in_console
@@ -35,9 +33,9 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
cereal::BinaryInputArchive archive(ss);
archive(n);
player_event_logs.AddToQueue(n.player_event_log);
PlayerEventLogs::Instance()->AddToQueue(n.player_event_log);
discord_manager.QueuePlayerEventMessage(n);
DiscordManager::Instance()->QueuePlayerEventMessage(n);
break;
}
default: {
@@ -46,3 +44,27 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
}
}
}
void ZoneServer::SendPlayerEventLogSettings()
{
EQ::Net::DynamicPacket dyn_pack;
std::vector<PlayerEventLogSettingsRepository::PlayerEventLogSettings> settings(
PlayerEventLogs::Instance()->GetSettings(),
PlayerEventLogs::Instance()->GetSettings() + PlayerEvent::EventType::MAX
);
dyn_pack.PutSerialize(0, settings);
auto packet_size = sizeof(ServerSendPlayerEvent_Struct) + dyn_pack.Length();
auto pack = std::make_unique<ServerPacket>(
ServerOP_SendPlayerEventSettings,
static_cast<uint32_t>(packet_size)
);
auto* buf = reinterpret_cast<ServerSendPlayerEvent_Struct*>(pack->pBuffer);
buf->cereal_size = static_cast<uint32_t>(dyn_pack.Length());
memcpy(buf->cereal_data, dyn_pack.Data(), dyn_pack.Length());
SendPacket(pack.release());
}
+5 -4
View File
@@ -16,11 +16,12 @@ class ZoneServer : public WorldTCPConnection {
public:
ZoneServer(std::shared_ptr<EQ::Net::ServertalkServerConnection> in_connection, EQ::Net::ConsoleServer *in_console);
~ZoneServer();
void SendPacket(ServerPacket *pack) { m_connection->SendPacket(pack); }
void SetIsZoneConnected(bool in) { m_is_zone_connected = in; }
bool GetIsZoneConnected() { return m_is_zone_connected; }
void HandleMessage(uint16 opcode, const EQ::Net::Packet &p);
void SendPacket(ServerPacket *pack) { m_connection->SendPacket(pack); }
void SetIsZoneConnected(bool in) { m_is_zone_connected = in; }
bool GetIsZoneConnected() { return m_is_zone_connected; }
void HandleMessage(uint16 opcode, const EQ::Net::Packet &p);
std::string GetUUID() const { return m_connection->GetUUID(); }
void SendPlayerEventLogSettings();
private:
std::shared_ptr<EQ::Net::ServertalkServerConnection> m_connection{};
+9 -16
View File
@@ -35,13 +35,6 @@
#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;
#ifdef _WINDOWS
#include <direct.h>
#else
@@ -81,10 +74,10 @@ inline bool MakeDirectory(const std::string &directory_name)
int main(int argc, char **argv)
{
RegisterExecutablePlatform(ExePlatformSharedMemory);
LogSys.LoadLogSettingsDefaults();
EQEmuLogSys::Instance()->LoadLogSettingsDefaults();
set_exception_handler();
path.LoadPaths();
PathManager::Instance()->Init();
LogInfo("Shared Memory Loader Program");
if (!EQEmuConfig::LoadConfig()) {
@@ -126,8 +119,8 @@ int main(int argc, char **argv)
content_db.SetMySQL(database);
}
LogSys.SetDatabase(&database)
->SetLogPath(path.GetLogPath())
EQEmuLogSys::Instance()->SetDatabase(&database)
->SetLogPath(PathManager::Instance()->GetLogPath())
->LoadLogDatabaseSettings()
->StartFileLogs();
@@ -169,16 +162,16 @@ int main(int argc, char **argv)
}
content_service.SetCurrentExpansion(RuleI(Expansion, CurrentExpansion));
content_service.SetDatabase(&database)
WorldContentService::Instance()->SetCurrentExpansion(RuleI(Expansion, CurrentExpansion));
WorldContentService::Instance()->SetDatabase(&database)
->SetContentDatabase(&content_db)
->SetExpansionContext()
->ReloadContentFlags();
LogInfo(
"Current expansion is [{}] ({})",
content_service.GetCurrentExpansion(),
content_service.GetCurrentExpansionName()
WorldContentService::Instance()->GetCurrentExpansion(),
WorldContentService::Instance()->GetCurrentExpansionName()
);
std::string hotfix_name = "";
@@ -244,6 +237,6 @@ int main(int argc, char **argv)
}
}
LogSys.CloseFileLogs();
EQEmuLogSys::Instance()->CloseFileLogs();
return 0;
}
+2 -4
View File
@@ -34,14 +34,12 @@
#include "task_state_test.h"
const EQEmuConfig *Config;
EQEmuLogSys LogSys;
PathManager path;
int main()
{
RegisterExecutablePlatform(ExePlatformClientImport);
LogSys.LoadLogSettingsDefaults();
path.LoadPaths();
EQEmuLogSys::Instance()->LoadLogSettingsDefaults();
PathManager::Instance()->Init();
auto ConfigLoadResult = EQEmuConfig::LoadConfig();
Config = EQEmuConfig::get();
-16
View File
@@ -30,7 +30,6 @@ public:
TEST_ADD(StringUtilTest::EscapeStringTest);
TEST_ADD(StringUtilTest::SearchDeliminatedStringTest);
TEST_ADD(StringUtilTest::SplitStringTest);
TEST_ADD(StringUtilTest::FromCharsTest);
TEST_ADD(StringUtilTest::TestIsFloat);
TEST_ADD(StringUtilTest::TestIsNumber);
}
@@ -108,21 +107,6 @@ public:
TEST_ASSERT(v[2] == "789");
}
void FromCharsTest() {
char int_chars[] = "123";
int int_value = 0;
char float_chars[] = "3.14";
float float_value = 0.0f;
Strings::from_chars(int_chars, int_value);
TEST_ASSERT(int_value == 123);
Strings::from_chars(float_chars, float_value);
TEST_ASSERT(float_value == 3.14f);
}
void TestIsFloat() {
TEST_ASSERT_EQUALS(Strings::IsFloat("0.23424523"), true);
TEST_ASSERT_EQUALS(Strings::IsFloat("12312312313.23424523"), true);
+2 -2
View File
@@ -482,7 +482,7 @@ Clientlist::Clientlist(int ChatPort) {
const ucsconfig *Config = ucsconfig::get();
std::string opcodes_file = fmt::format("{}/{}", path.GetServerPath(), Config->MailOpCodesFile);
std::string opcodes_file = fmt::format("{}/{}", PathManager::Instance()->GetServerPath(), Config->MailOpCodesFile);
LogInfo("Loading [{}]", opcodes_file);
if (!ChatOpMgr->LoadOpcodes(opcodes_file.c_str()))
@@ -651,7 +651,7 @@ void Clientlist::Process()
OpcodeManager::EmuToName(app->GetOpcode()),
o->EmuToEQ(app->GetOpcode()) == 0 ? app->GetProtocolOpcode() : o->EmuToEQ(app->GetOpcode()),
app->Size(),
(LogSys.IsLogEnabled(Logs::Detail, Logs::PacketClientServer) ? DumpPacketToString(app) : "")
(EQEmuLogSys::Instance()->IsLogEnabled(Logs::Detail, Logs::PacketClientServer) ? DumpPacketToString(app) : "")
);
switch (opcode) {
+9 -13
View File
@@ -44,13 +44,8 @@
ChatChannelList *ChannelList;
Clientlist *g_Clientlist;
EQEmuLogSys LogSys;
UCSDatabase database;
WorldServer *worldserver = nullptr;
DiscordManager discord_manager;
PathManager path;
ZoneStore zone_store;
PlayerEventLogs player_event_logs;
const ucsconfig *Config;
@@ -75,7 +70,7 @@ void Shutdown() {
LogInfo("Shutting down...");
ChannelList->RemoveAllChannels();
g_Clientlist->CloseAllConnections();
LogSys.CloseFileLogs();
EQEmuLogSys::Instance()->CloseFileLogs();
}
int caught_loop = 0;
@@ -90,24 +85,24 @@ void CatchSignal(int sig_num) {
LogInfo("In a signal handler loop and process is incapable of exiting properly, forcefully cleaning up");
ChannelList->RemoveAllChannels();
g_Clientlist->CloseAllConnections();
LogSys.CloseFileLogs();
EQEmuLogSys::Instance()->CloseFileLogs();
std::exit(0);
}
}
void PlayerEventQueueListener() {
while (caught_loop == 0) {
discord_manager.ProcessMessageQueue();
DiscordManager::Instance()->ProcessMessageQueue();
Sleep(100);
}
}
int main() {
RegisterExecutablePlatform(ExePlatformUCS);
LogSys.LoadLogSettingsDefaults();
EQEmuLogSys::Instance()->LoadLogSettingsDefaults();
set_exception_handler();
path.LoadPaths();
PathManager::Instance()->Init();
// Check every minute for unused channels we can delete
//
@@ -139,12 +134,13 @@ int main() {
return 1;
}
LogSys.SetDatabase(&database)
->SetLogPath(path.GetLogPath())
EQEmuLogSys::Instance()
->SetDatabase(&database)
->SetLogPath(PathManager::Instance()->GetLogPath())
->LoadLogDatabaseSettings()
->StartFileLogs();
player_event_logs.SetDatabase(&database)->Init();
PlayerEventLogs::Instance()->SetDatabase(&database)->Init();
char tmp[64];
+4 -5
View File
@@ -42,7 +42,6 @@ extern WorldServer worldserver;
extern Clientlist *g_Clientlist;
extern const ucsconfig *Config;
extern UCSDatabase database;
extern DiscordManager discord_manager;
void ProcessMailTo(Client *c, const std::string& from, const std::string& subject, const std::string& message);
@@ -79,8 +78,8 @@ void WorldServer::ProcessMessage(uint16 opcode, EQ::Net::Packet &p)
case ServerOP_ServerReloadRequest: {
auto o = (ServerReload::Request*) pack->pBuffer;
if (o->type == ServerReload::Type::Logs) {
LogSys.LoadLogDatabaseSettings();
player_event_logs.ReloadSettings();
EQEmuLogSys::Instance()->LoadLogDatabaseSettings();
PlayerEventLogs::Instance()->ReloadSettings();
}
break;
@@ -92,14 +91,14 @@ void WorldServer::ProcessMessage(uint16 opcode, EQ::Net::Packet &p)
cereal::BinaryInputArchive archive(ss);
archive(n);
discord_manager.QueuePlayerEventMessage(n);
DiscordManager::Instance()->QueuePlayerEventMessage(n);
break;
}
case ServerOP_DiscordWebhookMessage: {
auto *q = (DiscordWebhookMessage_Struct *) p.Data();
discord_manager.QueueWebhookMessage(
DiscordManager::Instance()->QueueWebhookMessage(
q->webhook_id,
q->message
);
+44
View File
@@ -0,0 +1,44 @@
#!/bin/bash
set -ex
sudo chown eqemu:eqemu /drone/src/ * -R
# Install ClangBuildAnalyzer if missing
if ! command -v clang-build-analyzer &> /dev/null; then
echo "Installing latest Clang Build Analyzer..."
LATEST_VERSION=$(curl -s https://api.github.com/repos/aras-p/ClangBuildAnalyzer/releases/latest \
| grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
sudo curl -sSL "https://github.com/aras-p/ClangBuildAnalyzer/releases/download/v${LATEST_VERSION}/ClangBuildAnalyzer-linux" \
-o /usr/local/bin/clang-build-analyzer
sudo chmod +x /usr/local/bin/clang-build-analyzer
fi
git submodule init && git submodule update
perl utils/scripts/build/tag-version.pl
mkdir -p build
clang-build-analyzer --start build/
cd build && \
cmake -DEQEMU_BUILD_TESTS=ON \
-DCMAKE_BUILD_TYPE=Debug \
-DEQEMU_BUILD_LUA=ON \
-DEQEMU_BUILD_PERL=ON \
-DEQEMU_BUILD_LOGIN=ON \
-DEQEMU_BUILD_STATIC=ON \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DCMAKE_CXX_FLAGS:STRING="-O0 -g -Wno-everything -ftime-trace" \
-G 'Unix Makefiles' \
.. && \
make -j"$(nproc)"
# 🧠 Generate ClangBuildAnalyzer report
clang-build-analyzer --stop ./ /tmp/eqemu.capture
clang-build-analyzer --analyze /tmp/eqemu.capture > report.txt
cat report.txt
ldd ./bin/zone
cd /drone/src/
+3 -1
View File
@@ -1,6 +1,8 @@
module should-release
go 1.18
go 1.23.0
toolchain go1.23.5
require (
github.com/google/go-github/v41 v41.0.0
@@ -35,12 +35,12 @@ if (scalar(@enum) > 0) {
foreach my $cat (@cats) {
print "#define Log" . $cat . "(message, ...) do {\\
if (LogSys.IsLogEnabled(Logs::General, Logs::" . $cat . "))\\
if (EQEmuLogSys::Instance()->IsLogEnabled(Logs::General, Logs::" . $cat . "))\\
OutF(LogSys, Logs::General, Logs::" . $cat . ", __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\\
} while (0)
#define Log" . $cat . "Detail(message, ...) do {\\
if (LogSys.IsLogEnabled(Logs::Detail, Logs::" . $cat . "))\\
if (EQEmuLogSys::Instance()->IsLogEnabled(Logs::Detail, Logs::" . $cat . "))\\
OutF(LogSys, Logs::Detail, Logs::" . $cat . ", __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\\
} while (0)
@@ -114,7 +114,8 @@ if ($requested_table_to_generate ne "all") {
my @cereal_enabled_tables = (
"data_buckets",
"player_event_logs"
"player_event_logs",
"player_event_log_settings"
);
my $generated_base_repository_files = "";
+4 -2
View File
@@ -7,6 +7,7 @@ SET(world_sources
cliententry.cpp
clientlist.cpp
console.cpp
../common/data_bucket.cpp
dynamic_zone.cpp
dynamic_zone_manager.cpp
eql_config.cpp
@@ -42,6 +43,7 @@ SET(world_headers
cliententry.h
clientlist.h
console.h
../common/data_bucket.h
dynamic_zone.h
dynamic_zone_manager.h
eql_config.h
@@ -74,8 +76,8 @@ ADD_EXECUTABLE(world ${world_sources} ${world_headers})
INSTALL(TARGETS world RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
IF (WIN32 AND EQEMU_BUILD_PCH)
TARGET_PRECOMPILE_HEADERS(world PRIVATE ../common/pch/pch.h)
IF (EQEMU_BUILD_PCH)
TARGET_PRECOMPILE_HEADERS(world PRIVATE ../common/pch/std-pch.h)
ENDIF ()
ADD_DEFINITIONS(-DWORLD)
+15 -18
View File
@@ -15,9 +15,6 @@
#include "../common/zone_store.h"
#include "../common/repositories/character_corpses_repository.h"
extern ZSList zoneserver_list;
extern ClientList client_list;
extern AdventureManager adventure_manager;
extern EQ::Random emu_random;
Adventure::Adventure(AdventureTemplate *t)
@@ -177,7 +174,7 @@ void Adventure::SetStatus(AdventureStatus new_status)
ut->instance_id = instance_id;
ut->new_duration = adventure_template->duration + 60;
zoneserver_list.SendPacket(0, instance_id, pack);
ZSList::Instance()->SendPacket(0, instance_id, pack);
safe_delete(pack);
}
else if(new_status == AS_WaitingForSecondaryEndTime)
@@ -191,7 +188,7 @@ void Adventure::SetStatus(AdventureStatus new_status)
ut->instance_id = instance_id;
ut->new_duration = 1860;
zoneserver_list.SendPacket(0, instance_id, pack);
ZSList::Instance()->SendPacket(0, instance_id, pack);
safe_delete(pack);
}
else if(new_status == AS_Finished)
@@ -205,7 +202,7 @@ void Adventure::SetStatus(AdventureStatus new_status)
ut->instance_id = instance_id;
ut->new_duration = 1860;
zoneserver_list.SendPacket(0, instance_id, pack);
ZSList::Instance()->SendPacket(0, instance_id, pack);
safe_delete(pack);
}
else
@@ -216,7 +213,7 @@ void Adventure::SetStatus(AdventureStatus new_status)
auto iter = players.begin();
while(iter != players.end())
{
adventure_manager.GetAdventureData((*iter).c_str());
AdventureManager::Instance()->GetAdventureData((*iter).c_str());
++iter;
}
}
@@ -230,11 +227,11 @@ void Adventure::SendAdventureMessage(uint32 type, const char *msg)
auto iter = players.begin();
while(iter != players.end())
{
ClientListEntry *current = client_list.FindCharacter((*iter).c_str());
ClientListEntry *current = ClientList::Instance()->FindCharacter((*iter).c_str());
if(current)
{
strcpy(sms->to, (*iter).c_str());
zoneserver_list.SendPacket(current->zone(), current->instance(), pack);
ZSList::Instance()->SendPacket(current->zone(), current->instance(), pack);
}
++iter;
}
@@ -283,7 +280,7 @@ void Adventure::Finished(AdventureWinStatus ws)
{
auto iter = players.begin();
while (iter != players.end()) {
ClientListEntry *current = client_list.FindCharacter((*iter).c_str());
ClientListEntry *current = ClientList::Instance()->FindCharacter((*iter).c_str());
auto character_id = database.GetCharacterID(*iter);
if (character_id == 0) {
@@ -310,7 +307,7 @@ void Adventure::Finished(AdventureWinStatus ws)
af->win = false;
af->points = 0;
}
zoneserver_list.SendPacket(current->zone(), current->instance(), pack);
ZSList::Instance()->SendPacket(current->zone(), current->instance(), pack);
database.UpdateAdventureStatsEntry(character_id, GetTemplate()->theme, (ws != AWS_Lose) ? true : false);
delete pack;
}
@@ -331,7 +328,7 @@ void Adventure::Finished(AdventureWinStatus ws)
afe.win = false;
afe.points = 0;
}
adventure_manager.AddFinishedEvent(afe);
AdventureManager::Instance()->AddFinishedEvent(afe);
database.UpdateAdventureStatsEntry(character_id, GetTemplate()->theme, (ws != AWS_Lose) ? true : false);
}
}
@@ -352,12 +349,12 @@ void Adventure::Finished(AdventureWinStatus ws)
afe.win = false;
afe.points = 0;
}
adventure_manager.AddFinishedEvent(afe);
AdventureManager::Instance()->AddFinishedEvent(afe);
database.UpdateAdventureStatsEntry(character_id, GetTemplate()->theme, (ws != AWS_Lose) ? true : false);
}
++iter;
}
adventure_manager.GetAdventureData(this);
AdventureManager::Instance()->GetAdventureData(this);
}
void Adventure::MoveCorpsesToGraveyard()
@@ -368,8 +365,8 @@ void Adventure::MoveCorpsesToGraveyard()
glm::vec4 position;
float x = GetTemplate()->graveyard_x + emu_random.Real(-GetTemplate()->graveyard_radius, GetTemplate()->graveyard_radius);
float y = GetTemplate()->graveyard_y + emu_random.Real(-GetTemplate()->graveyard_radius, GetTemplate()->graveyard_radius);
float x = GetTemplate()->graveyard_x + EQ::Random::Instance()->Real(-GetTemplate()->graveyard_radius, GetTemplate()->graveyard_radius);
float y = GetTemplate()->graveyard_y + EQ::Random::Instance()->Real(-GetTemplate()->graveyard_radius, GetTemplate()->graveyard_radius);
float z = GetTemplate()->graveyard_z;
position.x = x;
@@ -396,7 +393,7 @@ void Adventure::MoveCorpsesToGraveyard()
d->InstanceID = 0;
d->ZoneID = GetTemplate()->graveyard_zone_id;
zoneserver_list.SendPacket(0, GetInstanceID(), pack);
ZSList::Instance()->SendPacket(0, GetInstanceID(), pack);
delete pack;
@@ -407,7 +404,7 @@ void Adventure::MoveCorpsesToGraveyard()
spc->player_corpse_id = e.id;
spc->zone_id = GetTemplate()->graveyard_zone_id;
zoneserver_list.SendPacket(spc->zone_id, 0, pack);
ZSList::Instance()->SendPacket(spc->zone_id, 0, pack);
delete pack;
}
+55 -59
View File
@@ -14,10 +14,6 @@
#include <sstream>
#include <stdio.h>
extern ZSList zoneserver_list;
extern ClientList client_list;
extern EQ::Random emu_random;
AdventureManager::AdventureManager()
{
process_timer = new Timer(500);
@@ -68,7 +64,7 @@ void AdventureManager::Process()
void AdventureManager::CalculateAdventureRequestReply(const char *data)
{
ServerAdventureRequest_Struct *sar = (ServerAdventureRequest_Struct*)data;
ClientListEntry *leader = client_list.FindCharacter(sar->leader);
ClientListEntry *leader = ClientList::Instance()->FindCharacter(sar->leader);
if(!leader)
{
return;
@@ -84,7 +80,7 @@ void AdventureManager::CalculateAdventureRequestReply(const char *data)
ServerAdventureRequestDeny_Struct *deny = (ServerAdventureRequestDeny_Struct*)pack->pBuffer;
strcpy(deny->leader, sar->leader);
strcpy(deny->reason, "There are currently no adventures set for this theme.");
zoneserver_list.SendPacket(leader->zone(), leader->instance(), pack);
ZSList::Instance()->SendPacket(leader->zone(), leader->instance(), pack);
delete pack;
return;
}
@@ -113,7 +109,7 @@ void AdventureManager::CalculateAdventureRequestReply(const char *data)
ss << (data + sizeof(ServerAdventureRequest_Struct) + (64 * i)) << " is already apart of an active adventure.";
strcpy(deny->reason, ss.str().c_str());
zoneserver_list.SendPacket(leader->zone(), leader->instance(), pack);
ZSList::Instance()->SendPacket(leader->zone(), leader->instance(), pack);
delete pack;
return;
}
@@ -185,7 +181,7 @@ void AdventureManager::CalculateAdventureRequestReply(const char *data)
for(int i = 0; i < sar->member_count; ++i)
{
ClientListEntry *current = client_list.FindCharacter((data + sizeof(ServerAdventureRequest_Struct) + (64 * i)));
ClientListEntry *current = ClientList::Instance()->FindCharacter((data + sizeof(ServerAdventureRequest_Struct) + (64 * i)));
if(current)
{
int lvl = current->level();
@@ -244,7 +240,7 @@ void AdventureManager::CalculateAdventureRequestReply(const char *data)
ServerAdventureRequestDeny_Struct *deny = (ServerAdventureRequestDeny_Struct*)pack->pBuffer;
strcpy(deny->leader, sar->leader);
strcpy(deny->reason, "The number of found players for this adventure was zero.");
zoneserver_list.SendPacket(leader->zone(), leader->instance(), pack);
ZSList::Instance()->SendPacket(leader->zone(), leader->instance(), pack);
delete pack;
return;
}
@@ -261,7 +257,7 @@ void AdventureManager::CalculateAdventureRequestReply(const char *data)
ss << "The maximum level range for this adventure is " << RuleI(Adventure, MaxLevelRange);
ss << " but the level range calculated was " << (max_level - min_level) << ".";
strcpy(deny->reason, ss.str().c_str());
zoneserver_list.SendPacket(leader->zone(), leader->instance(), pack);
ZSList::Instance()->SendPacket(leader->zone(), leader->instance(), pack);
delete pack;
return;
}
@@ -324,7 +320,7 @@ void AdventureManager::CalculateAdventureRequestReply(const char *data)
if(eligible_adventures.size() > 0)
{
ea_iter = eligible_adventures.begin();
int c_index = emu_random.Int(0, (eligible_adventures.size()-1));
int c_index = EQ::Random::Instance()->Int(0, (eligible_adventures.size()-1));
for(int i = 0; i < c_index; ++i)
{
++ea_iter;
@@ -338,7 +334,7 @@ void AdventureManager::CalculateAdventureRequestReply(const char *data)
sra->id = (*ea_iter)->id;
sra->member_count = sar->member_count;
memcpy((pack->pBuffer + sizeof(ServerAdventureRequestAccept_Struct)), (data + sizeof(ServerAdventureRequest_Struct)), (sar->member_count * 64));
zoneserver_list.SendPacket(leader->zone(), leader->instance(), pack);
ZSList::Instance()->SendPacket(leader->zone(), leader->instance(), pack);
delete pack;
return;
}
@@ -348,7 +344,7 @@ void AdventureManager::CalculateAdventureRequestReply(const char *data)
ServerAdventureRequestDeny_Struct *deny = (ServerAdventureRequestDeny_Struct*)pack->pBuffer;
strcpy(deny->leader, sar->leader);
strcpy(deny->reason, "The number of adventures returned was zero.");
zoneserver_list.SendPacket(leader->zone(), leader->instance(), pack);
ZSList::Instance()->SendPacket(leader->zone(), leader->instance(), pack);
delete pack;
return;
}
@@ -357,7 +353,7 @@ void AdventureManager::CalculateAdventureRequestReply(const char *data)
void AdventureManager::TryAdventureCreate(const char *data)
{
ServerAdventureRequestCreate_Struct *src = (ServerAdventureRequestCreate_Struct*)data;
ClientListEntry *leader = client_list.FindCharacter(src->leader);
ClientListEntry *leader = ClientList::Instance()->FindCharacter(src->leader);
if(!leader)
{
return;
@@ -368,7 +364,7 @@ void AdventureManager::TryAdventureCreate(const char *data)
{
auto pack = new ServerPacket(ServerOP_AdventureCreateDeny, 64);
strcpy((char*)pack->pBuffer, src->leader);
zoneserver_list.SendPacket(leader->zone(), leader->instance(), pack);
ZSList::Instance()->SendPacket(leader->zone(), leader->instance(), pack);
delete pack;
return;
}
@@ -378,7 +374,7 @@ void AdventureManager::TryAdventureCreate(const char *data)
{
auto pack = new ServerPacket(ServerOP_AdventureCreateDeny, 64);
strcpy((char*)pack->pBuffer, src->leader);
zoneserver_list.SendPacket(leader->zone(), leader->instance(), pack);
ZSList::Instance()->SendPacket(leader->zone(), leader->instance(), pack);
delete pack;
delete adv;
return;
@@ -391,7 +387,7 @@ void AdventureManager::TryAdventureCreate(const char *data)
{
auto pack = new ServerPacket(ServerOP_AdventureCreateDeny, 64);
strcpy((char*)pack->pBuffer, src->leader);
zoneserver_list.SendPacket(leader->zone(), leader->instance(), pack);
ZSList::Instance()->SendPacket(leader->zone(), leader->instance(), pack);
delete pack;
delete adv;
return;
@@ -404,7 +400,7 @@ void AdventureManager::TryAdventureCreate(const char *data)
for(int i = 0; i < src->member_count; ++i)
{
ClientListEntry *player = client_list.FindCharacter((data + sizeof(ServerAdventureRequestCreate_Struct) + (64 * i)));
ClientListEntry *player = ClientList::Instance()->FindCharacter((data + sizeof(ServerAdventureRequestCreate_Struct) + (64 * i)));
if(player)
{
int f_count = 0;
@@ -436,7 +432,7 @@ void AdventureManager::TryAdventureCreate(const char *data)
sfa->zone_in_object = finished_adventures[f]->GetTemplate()->zone_in_object_id;
}
zoneserver_list.SendPacket(player->zone(), player->instance(), pack);
ZSList::Instance()->SendPacket(player->zone(), player->instance(), pack);
safe_delete_array(finished_adventures);
delete pack;
}
@@ -458,7 +454,7 @@ void AdventureManager::GetAdventureData(Adventure *adv)
void AdventureManager::GetAdventureData(const char *name)
{
ClientListEntry *player = client_list.FindCharacter(name);
ClientListEntry *player = ClientList::Instance()->FindCharacter(name);
if(player)
{
int f_count = 0;
@@ -497,7 +493,7 @@ void AdventureManager::GetAdventureData(const char *name)
delete pack;
auto pack = new ServerPacket(ServerOP_AdventureDataClear, 64);
strcpy((char*)pack->pBuffer, name);
zoneserver_list.SendPacket(player->zone(), player->instance(), pack);
ZSList::Instance()->SendPacket(player->zone(), player->instance(), pack);
delete pack;
delete[] finished_adventures;
@@ -515,7 +511,7 @@ void AdventureManager::GetAdventureData(const char *name)
sfa->zone_in_object = finished_adventures[i]->GetTemplate()->zone_in_object_id;
}
zoneserver_list.SendPacket(player->zone(), player->instance(), pack);
ZSList::Instance()->SendPacket(player->zone(), player->instance(), pack);
safe_delete_array(finished_adventures);
delete pack;
delete[] finished_adventures;
@@ -764,7 +760,7 @@ void AdventureManager::PlayerClickedDoor(const char *player, int zone_id, int do
{
if((*iter)->PlayerExists(player))
{
ClientListEntry *pc = client_list.FindCharacter(player);
ClientListEntry *pc = ClientList::Instance()->FindCharacter(player);
if(pc)
{
auto pack =
@@ -783,7 +779,7 @@ void AdventureManager::PlayerClickedDoor(const char *player, int zone_id, int do
(*iter)->SetStatus(AS_WaitingForPrimaryEndTime);
}
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
ZSList::Instance()->SendPacket(pc->zone(), pc->instance(), pack);
safe_delete(pack);
}
return;
@@ -792,19 +788,19 @@ void AdventureManager::PlayerClickedDoor(const char *player, int zone_id, int do
++iter;
}
ClientListEntry *pc = client_list.FindCharacter(player);
ClientListEntry *pc = ClientList::Instance()->FindCharacter(player);
if(pc)
{
auto pack = new ServerPacket(ServerOP_AdventureClickDoorError, 64);
strcpy((char*)pack->pBuffer, player);
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
ZSList::Instance()->SendPacket(pc->zone(), pc->instance(), pack);
safe_delete(pack);
}
}
void AdventureManager::LeaveAdventure(const char *name)
{
ClientListEntry *pc = client_list.FindCharacter(name);
ClientListEntry *pc = ClientList::Instance()->FindCharacter(name);
if(pc)
{
Adventure *current = GetActiveAdventure(name);
@@ -814,7 +810,7 @@ void AdventureManager::LeaveAdventure(const char *name)
{
auto pack = new ServerPacket(ServerOP_AdventureLeaveDeny, 64);
strcpy((char*)pack->pBuffer, name);
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
ZSList::Instance()->SendPacket(pc->zone(), pc->instance(), pack);
safe_delete(pack);
}
else
@@ -827,7 +823,7 @@ void AdventureManager::LeaveAdventure(const char *name)
current->RemovePlayer(name);
auto pack = new ServerPacket(ServerOP_AdventureLeaveReply, 64);
strcpy((char*)pack->pBuffer, name);
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
ZSList::Instance()->SendPacket(pc->zone(), pc->instance(), pack);
safe_delete(pack);
}
}
@@ -835,7 +831,7 @@ void AdventureManager::LeaveAdventure(const char *name)
{
auto pack = new ServerPacket(ServerOP_AdventureLeaveReply, 64);
strcpy((char*)pack->pBuffer, name);
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
ZSList::Instance()->SendPacket(pc->zone(), pc->instance(), pack);
safe_delete(pack);
}
}
@@ -867,12 +863,12 @@ void AdventureManager::IncrementCount(uint16 instance_id)
while(siter != slist.end())
{
ClientListEntry *pc = client_list.FindCharacter((*siter).c_str());
ClientListEntry *pc = ClientList::Instance()->FindCharacter((*siter).c_str());
if(pc)
{
memset(ac->player, 0, 64);
strcpy(ac->player, (*siter).c_str());
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
ZSList::Instance()->SendPacket(pc->zone(), pc->instance(), pack);
}
++siter;
}
@@ -936,7 +932,7 @@ void AdventureManager::GetZoneData(uint16 instance_id)
zd->dest_y = temp->dest_y;
zd->dest_z = temp->dest_z;
zd->dest_h = temp->dest_h;
zoneserver_list.SendPacket(0, instance_id, pack);
ZSList::Instance()->SendPacket(0, instance_id, pack);
delete pack;
}
}
@@ -1262,7 +1258,7 @@ void AdventureManager::DoLeaderboardRequest(const char* player, uint8 type)
void AdventureManager::DoLeaderboardRequestWins(const char* player)
{
ClientListEntry *pc = client_list.FindCharacter(player);
ClientListEntry *pc = ClientList::Instance()->FindCharacter(player);
if(pc)
{
auto pack = new ServerPacket(ServerOP_AdventureLeaderboard, 64 + sizeof(AdventureLeaderboard_Struct));
@@ -1321,14 +1317,14 @@ void AdventureManager::DoLeaderboardRequestWins(const char* player)
al->failure = our_failures;
}
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
ZSList::Instance()->SendPacket(pc->zone(), pc->instance(), pack);
delete pack;
}
}
void AdventureManager::DoLeaderboardRequestPercentage(const char* player)
{
ClientListEntry *pc = client_list.FindCharacter(player);
ClientListEntry *pc = ClientList::Instance()->FindCharacter(player);
if(pc)
{
auto pack = new ServerPacket(ServerOP_AdventureLeaderboard, 64 + sizeof(AdventureLeaderboard_Struct));
@@ -1387,14 +1383,14 @@ void AdventureManager::DoLeaderboardRequestPercentage(const char* player)
al->failure = our_failures;
}
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
ZSList::Instance()->SendPacket(pc->zone(), pc->instance(), pack);
delete pack;
}
}
void AdventureManager::DoLeaderboardRequestWinsGuk(const char* player)
{
ClientListEntry *pc = client_list.FindCharacter(player);
ClientListEntry *pc = ClientList::Instance()->FindCharacter(player);
if(pc)
{
auto pack = new ServerPacket(ServerOP_AdventureLeaderboard, 64 + sizeof(AdventureLeaderboard_Struct));
@@ -1453,14 +1449,14 @@ void AdventureManager::DoLeaderboardRequestWinsGuk(const char* player)
al->failure = our_failures;
}
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
ZSList::Instance()->SendPacket(pc->zone(), pc->instance(), pack);
delete pack;
}
}
void AdventureManager::DoLeaderboardRequestPercentageGuk(const char* player)
{
ClientListEntry *pc = client_list.FindCharacter(player);
ClientListEntry *pc = ClientList::Instance()->FindCharacter(player);
if(pc)
{
auto pack = new ServerPacket(ServerOP_AdventureLeaderboard, 64 + sizeof(AdventureLeaderboard_Struct));
@@ -1519,14 +1515,14 @@ void AdventureManager::DoLeaderboardRequestPercentageGuk(const char* player)
al->failure = our_failures;
}
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
ZSList::Instance()->SendPacket(pc->zone(), pc->instance(), pack);
delete pack;
}
}
void AdventureManager::DoLeaderboardRequestWinsMir(const char* player)
{
ClientListEntry *pc = client_list.FindCharacter(player);
ClientListEntry *pc = ClientList::Instance()->FindCharacter(player);
if(pc)
{
auto pack = new ServerPacket(ServerOP_AdventureLeaderboard, 64 + sizeof(AdventureLeaderboard_Struct));
@@ -1585,14 +1581,14 @@ void AdventureManager::DoLeaderboardRequestWinsMir(const char* player)
al->failure = our_failures;
}
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
ZSList::Instance()->SendPacket(pc->zone(), pc->instance(), pack);
delete pack;
}
}
void AdventureManager::DoLeaderboardRequestPercentageMir(const char* player)
{
ClientListEntry *pc = client_list.FindCharacter(player);
ClientListEntry *pc = ClientList::Instance()->FindCharacter(player);
if(pc)
{
auto pack = new ServerPacket(ServerOP_AdventureLeaderboard, 64 + sizeof(AdventureLeaderboard_Struct));
@@ -1651,14 +1647,14 @@ void AdventureManager::DoLeaderboardRequestPercentageMir(const char* player)
al->failure = our_failures;
}
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
ZSList::Instance()->SendPacket(pc->zone(), pc->instance(), pack);
delete pack;
}
}
void AdventureManager::DoLeaderboardRequestWinsMmc(const char* player)
{
ClientListEntry *pc = client_list.FindCharacter(player);
ClientListEntry *pc = ClientList::Instance()->FindCharacter(player);
if(pc)
{
auto pack = new ServerPacket(ServerOP_AdventureLeaderboard, 64 + sizeof(AdventureLeaderboard_Struct));
@@ -1717,14 +1713,14 @@ void AdventureManager::DoLeaderboardRequestWinsMmc(const char* player)
al->failure = our_failures;
}
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
ZSList::Instance()->SendPacket(pc->zone(), pc->instance(), pack);
delete pack;
}
}
void AdventureManager::DoLeaderboardRequestPercentageMmc(const char* player)
{
ClientListEntry *pc = client_list.FindCharacter(player);
ClientListEntry *pc = ClientList::Instance()->FindCharacter(player);
if(pc)
{
auto pack = new ServerPacket(ServerOP_AdventureLeaderboard, 64 + sizeof(AdventureLeaderboard_Struct));
@@ -1783,14 +1779,14 @@ void AdventureManager::DoLeaderboardRequestPercentageMmc(const char* player)
al->failure = our_failures;
}
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
ZSList::Instance()->SendPacket(pc->zone(), pc->instance(), pack);
delete pack;
}
}
void AdventureManager::DoLeaderboardRequestWinsRuj(const char* player)
{
ClientListEntry *pc = client_list.FindCharacter(player);
ClientListEntry *pc = ClientList::Instance()->FindCharacter(player);
if(pc)
{
auto pack = new ServerPacket(ServerOP_AdventureLeaderboard, 64 + sizeof(AdventureLeaderboard_Struct));
@@ -1849,14 +1845,14 @@ void AdventureManager::DoLeaderboardRequestWinsRuj(const char* player)
al->failure = our_failures;
}
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
ZSList::Instance()->SendPacket(pc->zone(), pc->instance(), pack);
delete pack;
}
}
void AdventureManager::DoLeaderboardRequestPercentageRuj(const char* player)
{
ClientListEntry *pc = client_list.FindCharacter(player);
ClientListEntry *pc = ClientList::Instance()->FindCharacter(player);
if(pc)
{
auto pack = new ServerPacket(ServerOP_AdventureLeaderboard, 64 + sizeof(AdventureLeaderboard_Struct));
@@ -1915,14 +1911,14 @@ void AdventureManager::DoLeaderboardRequestPercentageRuj(const char* player)
al->failure = our_failures;
}
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
ZSList::Instance()->SendPacket(pc->zone(), pc->instance(), pack);
delete pack;
}
}
void AdventureManager::DoLeaderboardRequestWinsTak(const char* player)
{
ClientListEntry *pc = client_list.FindCharacter(player);
ClientListEntry *pc = ClientList::Instance()->FindCharacter(player);
if(pc)
{
auto pack = new ServerPacket(ServerOP_AdventureLeaderboard, 64 + sizeof(AdventureLeaderboard_Struct));
@@ -1981,14 +1977,14 @@ void AdventureManager::DoLeaderboardRequestWinsTak(const char* player)
al->failure = our_failures;
}
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
ZSList::Instance()->SendPacket(pc->zone(), pc->instance(), pack);
delete pack;
}
}
void AdventureManager::DoLeaderboardRequestPercentageTak(const char* player)
{
ClientListEntry *pc = client_list.FindCharacter(player);
ClientListEntry *pc = ClientList::Instance()->FindCharacter(player);
if(pc)
{
auto pack = new ServerPacket(ServerOP_AdventureLeaderboard, 64 + sizeof(AdventureLeaderboard_Struct));
@@ -2047,7 +2043,7 @@ void AdventureManager::DoLeaderboardRequestPercentageTak(const char* player)
al->failure = our_failures;
}
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
ZSList::Instance()->SendPacket(pc->zone(), pc->instance(), pack);
delete pack;
}
}
@@ -2074,7 +2070,7 @@ bool AdventureManager::PopFinishedEvent(const char *name, AdventureFinishEvent &
void AdventureManager::SendAdventureFinish(AdventureFinishEvent fe)
{
ClientListEntry *pc = client_list.FindCharacter(fe.name.c_str());
ClientListEntry *pc = ClientList::Instance()->FindCharacter(fe.name.c_str());
if(pc)
{
auto pack = new ServerPacket(ServerOP_AdventureFinish, sizeof(ServerAdventureFinish_Struct));
@@ -2084,7 +2080,7 @@ void AdventureManager::SendAdventureFinish(AdventureFinishEvent fe)
af->win = fe.win;
af->points = fe.points;
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
ZSList::Instance()->SendPacket(pc->zone(), pc->instance(), pack);
delete pack;
}
}
+6
View File
@@ -40,6 +40,12 @@ public:
AdventureTemplate *GetAdventureTemplate(int theme, int id);
AdventureTemplate *GetAdventureTemplate(int id);
void GetZoneData(uint16 instance_id);
static AdventureManager* Instance()
{
static AdventureManager instance;
return &instance;
}
protected:
bool IsInExcludedZoneList(std::list<AdventureZones> excluded_zones, std::string zone_name, int version);
bool IsInExcludedZoneInList(std::list<AdventureZoneIn> excluded_zone_ins, int zone_id, int door_object);
+3 -2
View File
@@ -12,8 +12,9 @@ void WorldserverCLI::DatabaseVersion(int argc, char **argv, argh::parser &cmd, s
Json::Value v;
v["database_version"] = CURRENT_BINARY_DATABASE_VERSION;
v["bots_database_version"] = RuleB(Bots, Enabled) ? CURRENT_BINARY_BOTS_DATABASE_VERSION : 0;
v["database_version"] = CURRENT_BINARY_DATABASE_VERSION;
v["bots_database_version"] = RuleB(Bots, Enabled) ? CURRENT_BINARY_BOTS_DATABASE_VERSION : 0;
v["custom_database_version"] = CUSTOM_BINARY_DATABASE_VERSION;
std::stringstream payload;
payload << v;

Some files were not shown because too many files have changed in this diff Show More