Compare commits

..

147 Commits

Author SHA1 Message Date
David Markowitz
bc0a7f4259 Script: Fix incorrect kill method 2023-11-01 19:58:48 -07:00
David Markowitz
65c743527e Add null check for loot drops (#1243)
fixes a crash
2023-10-28 05:32:19 -05:00
79752c9abc chore: remove rarity table debug log (#1245)
cause it's too noisy
2023-10-28 05:31:54 -05:00
David Markowitz
01efa72aad fix: Update navmeshes (#1229)
* re-add x and z checking for height

Now that we have better navmeshes, this will result in much better results and as such we can re-enable this check.

* Always run navmesh extraction

waste of time most of the time, but no other way to force update to the meshes easily.

* Navmeshes Version 2

- Add all missing zones
- Drastically improve several zones and their navmeshes, cleaning them up, making them more accurate and generally using more features of detour/recast.

* Update CMakeLists.txt

* update meshes

* Navmesh: Add pet cove navmesh

* Navmesh: Fix navmesh for fv
2023-10-27 23:19:43 -05:00
6f3950dae7 chore: remove uneeded old perm map check (#1240)
and remove unused softban perm
RIP DLU beta
2023-10-25 11:44:57 -05:00
David Markowitz
a5e46e2844 Chat: Fix possible nullptr access (#1238)
Fixes a possible nullptr access.  This is the only call to GetPlayerData where we do not check the result for some reason, so this PR adds in the check and a resulting log line.

Code compiles, unsure how to reproduce the issue, however here is the crash dump I used to deduce this being the possible issue

```

Error: signal 11:
[00] CatchUnhandled(int)(+0x316) [0x561469100336]
[01] /lib/x86_64-linux-gnu/libc.so.6(+0x42520) [0x7f65e8e45520]
[02] /DarkflameServer/build/ChatServer(+0x32719) [0x5614690fa719]
[03] HandlePacket(Packet*)(+0x2a0) [0x5614690fcfb0]
[04] /DarkflameServer/build/ChatServer(main+0x92e) [0x5614690fb75e]
[05] /lib/x86_64-linux-gnu/libc.so.6(+0x29d90) [0x7f65e8e2cd90]
[06] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x80) [0x7f65e8e2ce40]
[07] /DarkflameServer/build/ChatServer(_start+0x25) [0x5614690fc375]
```
2023-10-24 02:26:55 -07:00
David Markowitz
3a37f9581c Character Select: Fix deleted memory access (#1237) 2023-10-24 02:26:39 -07:00
David Markowitz
025ff593ce Script: Fix unupdated new component (#1236) 2023-10-23 13:25:07 -07:00
aab60567ba fix: adding a proximity monitor when one exists already (#1235) 2023-10-23 12:24:17 -05:00
David Markowitz
9aa81f95cc Script: Fix crashes (#1233) 2023-10-23 09:56:12 -05:00
David Markowitz
5ea06f9bda EntityManager: Fix iterator invalidation (#1234)
Tested that servers still start up, and that zones like bons no longer hard crash when all players have left the world.
2023-10-23 08:55:38 -05:00
David Markowitz
ae349d6b15 feat: Add isolated and simplified path to add components (#1204)
* Components: Make ComponentType inline

Prevents the next commits ODR violation

* Components: Add new components

* Entity: Add headers

inline script component ComponentType

* Components: Flip constructor argument order

Entity comes first always

* Entity: Add generic AddComponent

Allows for much easier adding of components and is error proof by not allowing the user to add more than 1 of a specific component type to an Entity.

* Entity: Migrate all component constructors

Move all to the new variadic templates AddComponent function to reduce clutter and ways the component map is modified.
The new function makes no assumptions.  Component is assumed to not exist and is checked for with operator[].  This will construct a null component which will then be newed if the component didnt exist, or it will just get the current component if it does already exist.  No new component will be allocated or constructed if the component already exists and the already existing pointer is returned instead.

* Entity: Add placement new

For the case where the component may already exist, use a placement new to construct the component again, it would be constructed again, but would not need to go through the allocator.

* Entity: Add comments on likely new code

* Tests: Fix tests

* Update Entity.cpp

* Update SGCannon.cpp

* Entity: call destructor when re-constructing

* Update Entity.cpp

Update Entity.cpp

---------

Co-authored-by: Aaron Kimbrell <aronwk.aaron@gmail.com>
2023-10-22 20:08:49 -05:00
David Markowitz
22207ea9c9 Diagnostics: Fix error file (#1231) 2023-10-22 19:58:19 -05:00
David Markowitz
23d71340c9 Scripts: Fix possible nullptr access (#1232)
unsure how to reproduce the actual bug, however we can see that with the following crash dump
```
Entity::GetComponent(eReplicaComponentType) const(+0x4) [0x56095665e634]
BossSpiderQueenEnemyServer::OnDie(Entity*, Entity*)(+0x28d) [0x560956795d0d]
Entity::Kill(Entity*)(+0xf8) [0x5609566637a8]
ZoneAgProperty::BaseTimerDone(Entity*, std::string const&)(+0x89b) [0x56095683736b]
Entity::Update(float)(+0x2b6) [0x560956662676]
EntityManager::UpdateEntities(float)(+0x2e) [0x56095667305e]
```
that the actual crash issue starts at
```
Entity::Kill(Entity*)(+0xf8) [0x5609566637a8]
ZoneAgProperty::BaseTimerDone(Entity*, std::string const&)
```
BaseTimerDone calls Kill, and there is only 1 call to Kill in the function which calls Kill no arguments, meaning the killer is a nullptr.  This propogates its way to the BossSpiderQueenEnemyServer::OnDie wherein we blindly check the killer pointer without verifying that the pointer is actually valid.

This patch simply checks that killer is valid before access to address the hole.
2023-10-22 14:53:54 -07:00
David Markowitz
5942182486 feat: Abstract Logger and simplify code (#1207)
* Logger: Rename logger to Logger from dLogger

* Logger: Add compile time filename

Fix include issues
Add writers
Add macros
Add macro to force compilation

* Logger: Replace calls with macros

Allows for filename and line number to be logged

* Logger: Add comments

and remove extra define

Logger: Replace with unique_ptr

also flush console at exit. regular file writer should be flushed on file close.

Logger: Remove constexpr on variable

* Logger: Simplify code

* Update Logger.cpp
2023-10-21 16:31:55 -07:00
David Markowitz
131239538b Entity: Add missing destroyable case (#1228)
Adds a missing edge case on the client where you may have the is_smashable flag set, but dont actually have a destroyable component.  In this case you should create only a destroyable component and add it to the component and serialize it last after all other data.  We also needed to add the set_faction var reading and setting as this is how Oliver Sudden actually gets their faction since they have no actual information in the database, it is all stored in ldf keys.

Tested that Oliver Sudden no longer logs Unable to unserialize logs when serialized or constructed.
2023-10-19 12:42:43 -05:00
Gie "Max" Vanommeslaeghe
4c507e34a5 Merge pull request #1219 from DarkflameUniverse/lol
fix: Address race condition
2023-10-19 12:25:27 +02:00
David Markowitz
50921cce2d Loot: Fix rarity sorting (#1226)
Missed this step from the previous speedup.  rollloot numbers match within margin of error to numbers pre-cache improvement.
2023-10-18 09:18:47 -05:00
David Markowitz
3806891db0 Teams: Default team loot to ffa (#1224) 2023-10-18 09:18:22 -05:00
David Markowitz
ba91058736 Destroyable: Fix animated deaths (#1227)
Fixes #1222

addresses an issue where the death behavior of a destructible component was not being respected and enemies with destroyable components that had special death animations were not able to play the animation on death.  This pr adds in the hardcoded constant the client uses for the same metric of 12 seconds.

Tested that claiming Nimbus Rock and completing the property guards mission allows him to vacuum away and then network the destruction packet 12 seconds later.
2023-10-18 09:17:57 -05:00
David Markowitz
73e70badb7 Entity: fix bad ldf key serialization (#1225) 2023-10-17 08:45:46 -05:00
David Markowitz
e4cae35edb PhantomPhysics: Fix gravity (#1221)
Fix gravity not being adjusted when colliding with a phantom physics object

Tested that while on moonbase, the players gravity is no longer reset to 1 when they change their cheat info.
2023-10-16 07:55:57 -05:00
David Markowitz
2746683235 Master: Address race condition
Fix a race condition that would overwrite the port of zone 0 with the auth server port or a chat server port which would cause a domino effect of desynced server ports

Tested that a sleep(5) in auth still allows a player to connect and login without issues
2023-10-14 00:01:41 -07:00
David Markowitz
c6087ce77a perf: Loot memory savings (#1165)
* Move away from constructor queries

Fix up other large tables to have proper backup lookups

Revert "idk im just dumb ig"

This reverts commit 5d5be5df53b8959b42b291613d7db749a65a3585.

idk im just dumb ig

* Fix slow components registry lookup

* add define for cdclient cache all

* Huge loot namespace rework

- Remove all excess memory usage
- do not cache components registry
- cache loot matrices on startup of the destroyable component
- convert loot singleton class to a namespace
- rework loot cdclient tables to operate closer to how someone would actually use them (basically doing the previous LootGenerator::LootGenerator caching but in those tables)
- Memory usage reduced by 10%+ across the board

* cache rebuild matrix

* Database: move reading to own function

Also change name of cache to PascalCase

* Database: Move common function rading
2023-10-09 15:33:22 -05:00
David Markowitz
e96fd56fbd Diagnostics: Fix demangling (#1215)
Rename to better names
More comments
Less branches
2023-10-09 15:31:43 -05:00
David Markowitz
500ae4d6e5 Scripts: Fix ambiguous base class (#1216) 2023-10-09 15:31:25 -05:00
David Markowitz
094797881b Cannon Cove: Fix incorrect sign (#1211)
Update CMakeVariables.txt

Cannon Cove: Fix incorrect sign
2023-10-09 15:29:11 -05:00
David Markowitz
3dd2791066 chore: Use TryParse for LDF parsing (#1206)
* LDF: Simplify parsing

* Update GeneralUtils.h
2023-10-09 15:22:40 -05:00
570c597148 WIP (#1203) 2023-10-09 15:20:56 -05:00
David Markowitz
ad003634f4 chore: Physics Component abstraction and addition of tests (#1159)
* Make serialize actually virtual

yep

* Abstract to PhysicsComponent

Move shared functionality of all physics related classes to a base class.

Tested that there were no failed to unserialize errors when in main gameplay in Gnarled Forest or in a race.

Tested that 2 players were able to see each other in the above scenarios just fine as well.

* Update PhantomPhysicsComponent.cpp

* Add SimplePhysicsTest

* Add construction test

* Update SimplePhysicsComponentTests.cpp

* remove flags and fix override

* Update VendorComponent.h
2023-10-09 15:19:38 -05:00
d8ac148cee refactor: re-write AOE, add FilterTargets, Update TacArc Reading (#1035)
* Re-write AOE behavior for new filter targets
Update Tacarc to use new filter targets
Added dev commands for skill and attack debugging

* Get all entities by detroyable
rather than controllable physics
Since destroyables are what can be hit

* Re-work filter targets to be 100% live accurate
reduce memory usage by only using one vector and removing invalid entries
get entities in the proximity rather than all entities with des comps in the instance, as was done in live

* remove debuging longs and remove oopsie

* address feedback

* make log more useful

* make filter more flat

* Add some more checks to filter targets
add pvp checks to isenemy

* fix typing

* Add filter target to TacArc and update filter target

* fix double declaration

* Some debugging logs

* Update TacArc reading

* make log clearer

* logs

* Update TacArcBehavior.cpp

* banana

* fix max targets

* remove extreanous parenthesesuuesdsds

* make behavior slot use a real type

---------

Co-authored-by: David Markowitz <EmosewaMC@gmail.com>
2023-10-09 15:18:51 -05:00
Gie "Max" Vanommeslaeghe
471d65707c Merge pull request #1217 from DarkflameUniverse/pre-req-fix
fix: Fix wisp lee mission
2023-10-09 15:11:23 +02:00
David Markowitz
94f8a99fba Revert: Fix wisp lee mission
This reverts commit d7e16ab589697fd1a0a270a02c622b8fa752638f.

Fixes an issue where the incorrect mission is marked as being offerable and this overwrote the original mission offered by wisp lee and forced him to offer a different, unacceptable mission.

Tested that completing the mission twice from a new daily state and a repeatable state both completed the chain correctly.  Unsure what the original bug was, but it does not appear to be present.
On top of that, there is no pre-requisite for mission 1883 anywhere in the cdclient, so at best, this check was always false, but the correct behavior is exact equivalence for the mission state.
2023-10-08 23:23:14 -07:00
TAHuntling
288991ef49 fix: Players are able to join a race without having a race car (#1149)
* Fixed Scrapped Racecar Stuck Issue

Changed RacingControlComponent to boot players back to the hub world when trying to race after dismantling a vehicle.

* Modified OnPlayerLoaded to fix Vehicle Inventory issue

* Change 3

---------

Co-authored-by: David Markowitz <EmosewaMC@gmail.com>
2023-10-08 19:38:48 -05:00
David Markowitz
74cc4176e1 Update RigidbodyPhantomPhysicsComponent.h (#1213) 2023-10-08 15:58:47 -05:00
b33e9935f5 fix: GM 1272 was labled as 1273 (#1210) 2023-10-05 23:20:20 -07:00
David Markowitz
258ee5c1ee CheatDetection: Move player access (#1209) 2023-10-05 15:31:05 -07:00
David Markowitz
a8820c14f2 AssetManager: Match allocators (#1205)
Currently on line 116 of AssetManager.cpp, we have the following
`*data = (char*)malloc(*len);`
however on line 45 of AssetManager.h we have `delete m_Base;` which is not the same allocator as we used to allocate the memory.
This PR matches the malloc and free to be the correct calls.
2023-09-30 18:48:12 -05:00
1ec8da8bf7 fix: remove foreign key on name in cheat_detection table (#1202) 2023-09-30 06:22:32 -05:00
David Markowitz
b24775f472 feat: Security improvements for spoofed packets (#1201)
* Add cheat detection for spoofed packets

* Add config option for ip loggin

* remove packet saving
2023-09-28 12:16:11 -05:00
David Markowitz
bd65fc6e33 Fix version number (#1199)
Accidentally reverted the changes in a previous PR.
2023-09-25 08:23:23 -05:00
David Markowitz
44f466ac72 fix: deleting last character still shows the character (#1123)
* Fix deleting last character

Fix an issue where deleting your last character caused the character to still show up on the character selection screen.

Tested that deleting my final character results in an empty character selection scene.

* Update UserManager.cpp
2023-09-24 02:55:54 -05:00
David Markowitz
51540568fb Strengthen checks for slash commands (#1198) 2023-09-22 17:48:35 -07:00
08020cd86d chore: cleanup LU(W)string writing (#1188)
* chore: cleanup LU(W)string writing
and add methods for reading
remove redunent "packet" from packet reading helpers
move write header to bitstreamutils since it's not packet related
add tests for reading/writing LU(W)Strings

* remove un-needed function defintions in header

* make reading and writing more efficient

* p

p

* quotes

* remove unneeded default

---------

Co-authored-by: David Markowitz <39972741+EmosewaMC@users.noreply.github.com>
2023-09-20 20:06:28 -05:00
ca78a166d9 fix #1194 (#1196) 2023-09-19 05:59:02 -05:00
2e386d29df fix: Limit the number of players that can join a team (#1187)
* Limit the number of players that can join a team
after being invited

* Notify player if they weren't added to the team

* check pointer
2023-08-18 18:58:27 -05:00
d893ecddeb Renamed RocketLaunchLUP to MultiZoneEntrance (#1185) 2023-08-18 14:14:40 -05:00
David Markowitz
f4f13e081a Update Commands.md (#1184)
If this fails to build im going to be nice to people
2023-08-13 17:05:04 -07:00
David Markowitz
c26086aff5 perf: Add path height correction on world load (#1178)
* Add path height correction on world load

* Increase height because Nexus Tower is tall

* Update height checker

- Only go up and down, do not deviate from the point you are on
- As a backup, use the nearestPoint on the nearestPoly, should detour be able to find one.
- Add a debug assert to fail the program should toReturn differ from nearestPoint[1].

Update dNavMesh.cpp

Update dNavMesh.cpp

* Fix if condition to actually return the value...

---------

Co-authored-by: Aaron Kimbrell <aronwk.aaron@gmail.com>
2023-08-12 09:20:00 -05:00
Gie "Max" Vanommeslaeghe
0337449aa7 Merge pull request #1183 from DarkflameUniverse/fastcrashfixes
fix: dangling pointer in mission when saving character data
2023-08-12 12:21:14 +02:00
David Markowitz
598f4e1663 Fix dangling pointer 2023-08-12 02:11:25 -07:00
David Markowitz
5eca25e42a refactor: Move CDClient Database away from constructor queries (#1164)
* Move away from constructor queries

Fix up other large tables to have proper backup lookups

Revert "idk im just dumb ig"

This reverts commit 5d5be5df53b8959b42b291613d7db749a65a3585.

idk im just dumb ig

* Fix slow components registry lookup

* add define for cdclient cache all

* Update CDBehaviorParameterTable.cpp
2023-08-10 23:27:40 -05:00
Gie "Max" Vanommeslaeghe
d233c7e2aa Merge pull request #1182 from DarkflameUniverse/fixRawReading
fix: RAW to OBJ parsing
2023-08-10 23:50:11 +02:00
beaceb947b fix: Properly read in scene metadata (#1170)
* fix: Properly read in scene metadata

* Fix reading in rental time and period from property path

* remove useless name in var
change hex to decimal so it's readable
fix scene transistion loop logic

* fix typoe and remove whitespace
2023-08-10 16:35:12 -05:00
David Markowitz
2cc13c6499 chore: Make serialize actually virtual (#1156)
* Make serialize actually virtual

* fix serialize and make update virutal

* Update VendorComponent.h

* Remove flag var

* Update SoundTriggerComponent.h

---------

Co-authored-by: Aaron Kimbrell <aronwk.aaron@gmail.com>
2023-08-10 14:33:15 -07:00
David Markowitz
ad81e341da add operator *= for vectors 2023-08-09 22:13:20 -07:00
David Markowitz
fe6be21008 fix raw reading 2023-08-09 22:08:32 -07:00
cefdfc696a fix: Implement proper Sound trigger component serialization (#1160)
* cleanup

* more cleanup and fully implement the sound trigger
and racing sound trigger

* more cleanup, and better defaults

* fixes and tested

* update initializor for guid and when to load sound guids

* make racing sound trigger it's own component

* fix type

* Remove global
move serializes

---------

Co-authored-by: David Markowitz <EmosewaMC@gmail.com>
2023-08-06 15:38:12 -05:00
7e2747a2d2 fix: load fdbchecksum to verify, even on character selection (world 0) (#1176) 2023-08-04 17:48:45 -05:00
a29253d2f0 feature: Donation Vendor Component (#1168)
* refactor: Vendor inventory loading
Implement proper delta compression
dynamically determine multicostitems and standard cost items
Quatantine max's custom code

* WIP

* progress missions

* address feedback

* fix newline

* Cleanup

* oops

* fix default for nexus tower jawbox
cleanup some logs

* remove log

* remove include that got added back
2023-08-03 21:44:03 -05:00
David Markowitz
e5b69745aa feat: Remove NET_VERSION define (#1153)
* Remove NET_VERSION define

I get to test this on 4 different platforms.  yay...

* move stuff around

finally fixed you docker

i love this

Update Dockerfile

Update Dockerfile

change type

Update AuthPackets.cpp

Update AuthServer.cpp

* Update CMakeVariables.txt

* Update sharedconfig.ini
2023-08-03 21:38:33 -05:00
David Markowitz
040a78c386 fix: Remove usage of rand() and seed randomness for chatserver (#1152)
* Remove usage of rand(), time(0) to time(NULL)

Replace it with the random engine mt19937.
convert time(0) to time(NULL)

* update

* revert a bunch of changes
2023-08-03 21:38:19 -05:00
David Markowitz
d8a5fd49a4 chore: Small movementAiComponent cleanup (#1145)
* rename and cleanup file

* more

* fix broken function

* Further naming fixes

t

Revert "Further naming fixes"

This reverts commit 057189982ba56788d48f9265d815e6c562ba6328.

* next step

* undo all testing changes

* minor tweaks
2023-08-03 21:38:04 -05:00
David Markowitz
208ed02158 Fix incorrect kick out of rebuilds (#1120) 2023-08-03 21:37:27 -05:00
952786c166 chore: cleanup some vanity npc logic (#1174)
* Dont setup talk for vanity npc's if they are no phrases
no ghosting ldfkey for canity npc's

* void, oops

* formatting
2023-08-03 21:37:09 -05:00
David Markowitz
9a07020a51 perf: Behavior Parameter memory savings (#1166)
* Memory Savings Behavior Parameter table

* Update CDBehaviorParameterTable.h
2023-08-03 19:31:02 -07:00
a22ecf385f feature: add full known GM list (#1171)
* feature: add full GM list

* Fix compiling

* add tests
Fix more issues
2023-08-03 21:27:40 -05:00
c2b4aa4026 refactor: Vendor inventory loading (#1163)
* refactor: Vendor inventory loading
Implement proper delta compression
dynamically determine multicostitems and standard cost items
Quatantine max's custom code

* address feedback

* fix newline

* oops

* remove header

* fix default and const for

* he said make it a reference too, not just const
2023-08-03 05:51:52 -05:00
David Markowitz
0d48cfe8c0 fix: Nipoint3 Operator+= (#1172)
* fix operator +=

* fix operator +=
2023-07-31 00:22:56 -07:00
e299bf9b62 fix: read and store the zone transition width properly (#1169) 2023-07-30 23:49:43 -07:00
Daniel Seiler
304af7922a Update MariaDB for windows (#792)
* Update CMakeMariaDBLists.txt

* Update CMakeMariaDBLists.txt

---------

Co-authored-by: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com>
Co-authored-by: David Markowitz <EmosewaMC@gmail.com>
2023-07-23 20:51:13 -05:00
TAHuntling
0610fe99f8 fix: Nexus Tower Combat Challenge can be started twice if two players start it at the same time (#1147)
* Nexus Tower Dummy Challenge Dual Instance Fix

Fix for dual instance starting when two players hit start on the challenge at the same time.

* Changed GetVar to GetNetworkVar

Changed the if statement to GetNetworkVar boolean of bInUse rather than GetVar boolean of bInUse
2023-07-23 16:04:45 -07:00
Gie "Max" Vanommeslaeghe
d1316cfc9f Merge pull request #1107 from EmosewaMC/first-draft-leaderboard-re-write
feat: Leaderboards
2023-07-24 00:29:17 +02:00
bd5ead40f6 feat: upgrade session keys to use mersenne twister (#1155)
* upgrade session keys to use mersenne twister

* arithmetic type static assert and windows min/max macro undef
2023-07-23 14:59:43 -07:00
David Markowitz
c791d1a237 feature: Auto update of ini files (#1154)
* Add auto update of ini files

Tested that config options that currently exist are not modified.

Tested that if the exact variable name is not located in the destination ini, the config option is added along with all of its corresponding comments.

Comments in the build files are ignored to prevent any possible name collision with comments.

* Fix typos and empty file issue
2023-07-23 12:09:07 -07:00
TAHuntling
54454973a1 Distance for pet digs increased slightly to help with navmesh issues (#1151) 2023-07-22 02:49:23 -07:00
David Markowitz
b87537c637 bump minor version 2023-07-22 02:16:53 -07:00
David Markowitz
a625d2eae5 Update SGCannon.cpp 2023-07-21 23:42:50 -07:00
David Markowitz
887e2a25f0 Fix race score bugs
num wins serialized properly
scores are saved and num wins and times played are incremented properly
2023-07-21 23:18:51 -07:00
David Markowitz
34392932b3 Merge branch 'main' into pr/1107 2023-07-21 19:40:30 -07:00
David Markowitz
cc251d0986 Update ActivityManager.cpp 2023-07-21 19:39:44 -07:00
David Markowitz
0c0f7216a1 Merge branch 'main' into pr/1107 2023-07-21 19:38:59 -07:00
TAHuntling
342da56678 Added Player Rewards for Solo Racing (#1150)
* Added Player Rewards for Solo Racing

* Fixed Dual PlayersRating multiplication

* Checking for solo player fixed

* Another change to fix issues
2023-07-21 19:37:31 -05:00
TAHuntling
11b0097488 freemoney type update (#1146)
Changed freemoney command to parse 64 bit integers as opposed to 32 bit
2023-07-19 09:07:41 -07:00
David Markowitz
3e3148e910 Move dZoneManager to game namespace (#1143)
* convert zone manager to game namespace

* Destroy logger last
2023-07-17 17:55:33 -05:00
David Markowitz
080a833144 Convert BrickDatabase to namespace (#1142)
* Convert BrickDatabase to namespace

This did not need to be a class.

* Fix linker errors

* convert to anonymous namespace

so the cache is unmodifiable outside the brickcache

* Move to lower scope level and remove log
2023-07-17 17:55:25 -05:00
David Markowitz
455f9470a5 Move EntityManager to Game namespace (#1140)
* Move EntityManager to Game namespace

* move initialization to later

Need to wait for dZoneManager to be initialized.

* Fix bugs

- Cannot delete from a RandomAccessIterator while in a range based for loop.

Touchup zone manager initialize

replace magic numbers with better named constants
replace magic zonecontrol id with a more readable hex alternative
condense stack variables
move initializers closer to their use
initialize entity manager with zone control

change initialize timings

If zone is not zero we expect to initialize the entity manager during zone manager initialization

Add constexpr for zone control LOT

* Add proper error handling

* revert vanity changes

* Update WorldServer.cpp

* Update dZoneManager.cpp
2023-07-15 13:56:33 -07:00
David Markowitz
e32cec6691 Merge branch 'first-draft-leaderboard-re-write' of https://github.com/EmosewaMC/DarkflameServer into first-draft-leaderboard-re-write 2023-06-21 21:53:23 -07:00
David Markowitz
85aa82b4b9 cleanup 2023-06-21 21:53:10 -07:00
David Markowitz
393733cc67 Update GameMessageHandler.cpp 2023-06-21 21:50:54 -07:00
David Markowitz
8156e5cc91 Update MigrationRunner.cpp 2023-06-21 21:50:16 -07:00
David Markowitz
d0e79d19fc Update Metrics.hpp 2023-06-21 21:48:58 -07:00
David Markowitz
45256a0338 Merge remote-tracking branch 'upstream/main' into first-draft-leaderboard-re-write 2023-06-21 21:48:22 -07:00
David Markowitz
238fc98ea5 Fix shooting gallery leaderboard bugs
- add weekly functionality for top scores
- Fix shooting gallery score saving
- remove extra leaderboard fetch
2023-06-21 21:46:11 -07:00
David Markowitz
d340874284 more bug fixing
- fix weekly leaderboards
- fix ag classic vs dlu scoring
- fix sorting for survival ns
- fix sorting for racing
2023-06-21 19:46:01 -07:00
EmosewaMC
c99e2a372b Add weekly filter 2023-06-05 16:04:56 -07:00
EmosewaMC
dab075fc39 forgor about this one 2023-06-05 15:19:52 -07:00
EmosewaMC
b4aa5db305 Comment out tests
rest in pepperoni tests
2023-06-05 15:10:08 -07:00
David Markowitz
259f0c8371 Working in game again
hooray
2023-06-05 04:10:59 -07:00
David Markowitz
a5e63529dc const and compile save 2023-06-05 02:50:40 -07:00
David Markowitz
c572f2a58d better tabs and organization 2023-06-05 02:43:02 -07:00
David Markowitz
5bff441c01 Fix query crashing
Just select all columns since we need most of them anyways
2023-06-05 02:31:49 -07:00
David Markowitz
96fc6e81d8 Update sql to work
The old way was supposed to work but doesn't.  Oh well!
2023-06-05 02:24:00 -07:00
David Markowitz
59d7121978 Merge remote-tracking branch 'upstream/main' into first-draft-leaderboard-re-write 2023-06-05 02:04:14 -07:00
EmosewaMC
8267823ca4 More simplification 2023-05-31 23:17:13 -07:00
EmosewaMC
b8878da61b Convert to using only floats
This will cover all of our bases for any type of score.  No need to do any conversions.
2023-05-31 23:05:19 -07:00
EmosewaMC
47deca6f4f Update migration
Better column names and maintainability
Better updating
Convert all data to floats
2023-05-31 23:04:33 -07:00
David Markowitz
8a1f275176 add a const 2023-05-31 03:10:28 -07:00
David Markowitz
e1a7b4993e look ma, more work 2023-05-30 18:21:10 -07:00
David Markowitz
0ecc5d83c3 Fix out of bounds access
Fixes an issue where we would try to access an array out of the physics bounds
2023-05-30 17:30:50 -07:00
EmosewaMC
a43e03255c It compiles at least now 2023-05-30 04:38:19 -07:00
EmosewaMC
83da45575e CONST 2023-05-30 04:28:50 -07:00
EmosewaMC
f5f599764d more const and views 2023-05-30 04:23:48 -07:00
EmosewaMC
7b1626901a Add some debug asserts 2023-05-30 04:18:32 -07:00
EmosewaMC
a595347211 Merge remote-tracking branch 'upstream/main' into first-draft-leaderboard-re-write 2023-05-30 04:11:53 -07:00
EmosewaMC
0107d05d55 draft 2023-05-30 04:11:37 -07:00
David Markowitz
f26e66da4d small updates to typs 2023-05-28 04:30:20 -07:00
David Markowitz
af1abe9e74 Use only ints 2023-05-10 01:32:55 -07:00
David Markowitz
4dba8d9225 Correct column order 2023-05-09 22:21:41 -07:00
David Markowitz
3448426caf commit 2023-05-09 22:00:13 -07:00
David Markowitz
7a067e7b48 Working in game!
- Add score saving for races
- Fix some bugs
- Still work to do.
2023-05-09 01:42:11 -07:00
David Markowitz
411c9eaf1f Remove dead code 2023-05-09 00:06:43 -07:00
David Markowitz
fcf5c5ea8a Resolve compiler errors 2023-05-09 00:06:26 -07:00
EmosewaMC
6c2312fe87 Implement page fetching 2023-05-08 19:59:10 -07:00
EmosewaMC
d98ad4b94f Implement leaderboard page offsets 2023-05-08 19:35:19 -07:00
EmosewaMC
5c086909ed Ready for implementation 2023-05-08 18:36:28 -07:00
David Markowitz
1c7ac93d4b Fix various bugs and make code cleaner.
Still have work to go.
2023-05-08 03:55:10 -07:00
David Markowitz
0f307ac4be Fix bugs
- Reinforce Query formatting
- Guarantee 11 rows are selected at a time by ranking by id, should there be more than an 11 way tie.
2023-05-08 02:46:55 -07:00
David Markowitz
bc518be654 Bug fixes and cleanup
Fix co-pilot induced column bugs
Fix insert/update statements
Added saving functionality
Added update clause for column
2023-05-07 04:09:10 -07:00
EmosewaMC
820b375c50 push 2023-05-07 00:31:38 -07:00
David Markowitz
3b8f18d2be Fix new lines 2023-05-05 21:33:30 -07:00
EmosewaMC
0faef7d791 Finished saving 2023-05-04 16:53:36 -07:00
EmosewaMC
28a0492201 Fix bugs 2023-05-04 14:48:26 -07:00
EmosewaMC
2ab995b9c3 Simplify snprintfs
so much better to read
2023-05-04 14:28:53 -07:00
EmosewaMC
8de528e77c Remove old code 2023-05-04 13:58:48 -07:00
David Markowitz
a3626a3b53 The query is supposed to get SMALLER
Still better than 9 different queries all with 1 minor change i guess.
2023-05-03 00:38:38 -07:00
David Markowitz
b5e3bd22e3 Merge remote-tracking branch 'upstream/main' into first-draft-leaderboard-re-write 2023-05-02 15:49:23 -07:00
EmosewaMC
48264e2cf4 push 2023-04-30 21:30:41 -07:00
David Markowitz
10a2c24d5e Add base MyStandings query 2023-04-26 02:10:57 -07:00
EmosewaMC
89f427ace0 Further work on leaderboards 2023-04-18 01:26:35 -07:00
EmosewaMC
08220d6852 Remove extra includes 2023-04-17 15:22:44 -07:00
EmosewaMC
42870028e4 Remove complex migration
Only shooting gallery had a value put in the wrong column.  All others were either already correct or unimplemented.
2023-04-17 15:19:13 -07:00
David Markowitz
fcb088d263 Further work on leaderboards
- Modularize tests
- Add migrations
- Fix switch case so it actually breaks
- Add in missing writes
- Beginning work on custom migration to move the leaderboard to the final state
2023-04-17 01:16:23 -07:00
EmosewaMC
ed2639ce4e Use inline functions 2023-04-14 01:32:52 -07:00
David Markowitz
41355cea58 Add remaining enum types 2023-04-13 21:55:09 -07:00
David Markowitz
c91f0d16b3 Get it compiling, add a test and optimize heavily 2023-04-13 00:45:03 -07:00
EmosewaMC
c02963013b first draft 2023-04-12 21:57:58 -07:00
519 changed files with 8534 additions and 6140 deletions

View File

@@ -97,26 +97,70 @@ make_directory(${CMAKE_BINARY_DIR}/logs)
# Copy resource files on first build # Copy resource files on first build
set(RESOURCE_FILES "sharedconfig.ini" "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini" "blacklist.dcf") set(RESOURCE_FILES "sharedconfig.ini" "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini" "blacklist.dcf")
foreach(resource_file ${RESOURCE_FILES}) message(STATUS "Checking resource file integrity")
if (NOT EXISTS ${PROJECT_BINARY_DIR}/${resource_file}) foreach (resource_file ${RESOURCE_FILES})
set(file_size 0)
if (EXISTS ${PROJECT_BINARY_DIR}/${resource_file})
file(SIZE ${PROJECT_BINARY_DIR}/${resource_file} file_size)
endif()
if (${file_size} EQUAL 0)
configure_file( configure_file(
${CMAKE_SOURCE_DIR}/resources/${resource_file} ${PROJECT_BINARY_DIR}/${resource_file} ${CMAKE_SOURCE_DIR}/resources/${resource_file} ${PROJECT_BINARY_DIR}/${resource_file}
COPYONLY COPYONLY
) )
message("Moved ${resource_file} to project binary directory") message(STATUS "Moved " ${resource_file} " to project binary directory")
elseif (resource_file MATCHES ".ini")
message(STATUS "Checking " ${resource_file} " for missing config options")
file(READ ${PROJECT_BINARY_DIR}/${resource_file} current_file_contents)
string(REPLACE "\\\n" "" current_file_contents ${current_file_contents})
string(REPLACE "\n" ";" current_file_contents ${current_file_contents})
set(parsed_current_file_contents "")
# Remove comment lines so they do not interfere with the variable parsing
foreach (line ${current_file_contents})
string(FIND ${line} "#" is_comment)
if (NOT ${is_comment} EQUAL 0)
string(APPEND parsed_current_file_contents ${line})
endif()
endforeach()
file(READ ${CMAKE_SOURCE_DIR}/resources/${resource_file} depot_file_contents)
string(REPLACE "\\\n" "" depot_file_contents ${depot_file_contents})
string(REPLACE "\n" ";" depot_file_contents ${depot_file_contents})
set(line_to_add "")
foreach (line ${depot_file_contents})
string(FIND ${line} "#" is_comment)
if (NOT ${is_comment} EQUAL 0)
string(REPLACE "=" ";" line_split ${line})
list(GET line_split 0 variable_name)
if (NOT ${parsed_current_file_contents} MATCHES ${variable_name})
message(STATUS "Adding missing config option " ${variable_name} " to " ${resource_file})
set(line_to_add ${line_to_add} ${line})
foreach (line_to_append ${line_to_add})
file(APPEND ${PROJECT_BINARY_DIR}/${resource_file} "\n" ${line_to_append})
endforeach()
file(APPEND ${PROJECT_BINARY_DIR}/${resource_file} "\n")
endif()
set(line_to_add "")
else()
set(line_to_add ${line_to_add} ${line})
endif()
endforeach()
endif() endif()
endforeach() endforeach()
message(STATUS "Resource file integrity check complete")
# if navmeshes directory does not exist, create it
if (NOT EXISTS ${PROJECT_BINARY_DIR}/navmeshes)
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/navmeshes)
endif()
# Copy navmesh data on first build and extract it # Copy navmesh data on first build and extract it
if (NOT EXISTS ${PROJECT_BINARY_DIR}/navmeshes/) configure_file(
configure_file(
${CMAKE_SOURCE_DIR}/resources/navmeshes.zip ${PROJECT_BINARY_DIR}/navmeshes.zip ${CMAKE_SOURCE_DIR}/resources/navmeshes.zip ${PROJECT_BINARY_DIR}/navmeshes.zip
COPYONLY COPYONLY
) )
file(ARCHIVE_EXTRACT INPUT ${PROJECT_BINARY_DIR}/navmeshes.zip) file(ARCHIVE_EXTRACT INPUT ${PROJECT_BINARY_DIR}/navmeshes.zip DESTINATION ${PROJECT_BINARY_DIR}/navmeshes)
file(REMOVE ${PROJECT_BINARY_DIR}/navmeshes.zip) file(REMOVE ${PROJECT_BINARY_DIR}/navmeshes.zip)
endif()
# Copy vanity files on first build # Copy vanity files on first build
set(VANITY_FILES "CREDITS.md" "INFO.md" "TESTAMENT.md" "NPC.xml") set(VANITY_FILES "CREDITS.md" "INFO.md" "TESTAMENT.md" "NPC.xml")

View File

@@ -1,12 +1,8 @@
PROJECT_VERSION_MAJOR=1 PROJECT_VERSION_MAJOR=1
PROJECT_VERSION_MINOR=0 PROJECT_VERSION_MINOR=1
PROJECT_VERSION_PATCH=4 PROJECT_VERSION_PATCH=1
# LICENSE # LICENSE
LICENSE=AGPL-3.0 LICENSE=AGPL-3.0
# The network version.
# 171023 - Darkflame Universe client
# 171022 - Unmodded client
NET_VERSION=171022
# Debugging # Debugging
# Set __dynamic to 1 to enable the -rdynamic flag for the linker, yielding some symbols in crashlogs. # Set __dynamic to 1 to enable the -rdynamic flag for the linker, yielding some symbols in crashlogs.
__dynamic=1 __dynamic=1
@@ -22,3 +18,5 @@ __maria_db_connector_compile_jobs__=1
__enable_testing__=1 __enable_testing__=1
# The path to OpenSSL. Change this if your OpenSSL install path is different than the default. # The path to OpenSSL. Change this if your OpenSSL install path is different than the default.
OPENSSL_ROOT_DIR=/usr/local/opt/openssl@3/ OPENSSL_ROOT_DIR=/usr/local/opt/openssl@3/
# Uncomment the below line to cache the entire CDClient into memory
# CDCLIENT_CACHE_ALL=1

View File

@@ -179,7 +179,7 @@ If you would like to build the server faster, append `-j<number>` where number i
### Notes ### Notes
Depending on your operating system, you may need to adjust some pre-processor defines in [CMakeVariables.txt](./CMakeVariables.txt) before building: Depending on your operating system, you may need to adjust some pre-processor defines in [CMakeVariables.txt](./CMakeVariables.txt) before building:
* If you are on MacOS, ensure OPENSSL_ROOT_DIR is pointing to the openssl root directory. * If you are on MacOS, ensure OPENSSL_ROOT_DIR is pointing to the openssl root directory.
* If you are using a Darkflame Universe client, ensure NET_VERSION is changed to 171023. * If you are using a Darkflame Universe client, ensure `client_net_version` in `build/sharedconfig.ini` is changed to 171023.
## Configuring your server ## Configuring your server
This server has a few steps that need to be taken to configure the server for your use case. This server has a few steps that need to be taken to configure the server for your use case.

View File

@@ -7,7 +7,7 @@
//DLU Includes: //DLU Includes:
#include "dCommonVars.h" #include "dCommonVars.h"
#include "dServer.h" #include "dServer.h"
#include "dLogger.h" #include "Logger.h"
#include "Database.h" #include "Database.h"
#include "dConfig.h" #include "dConfig.h"
#include "Diagnostics.h" #include "Diagnostics.h"
@@ -25,13 +25,14 @@
#include "Game.h" #include "Game.h"
namespace Game { namespace Game {
dLogger* logger = nullptr; Logger* logger = nullptr;
dServer* server = nullptr; dServer* server = nullptr;
dConfig* config = nullptr; dConfig* config = nullptr;
bool shouldShutdown = false; bool shouldShutdown = false;
std::mt19937 randomEngine;
} }
dLogger* SetupLogger(); Logger* SetupLogger();
void HandlePacket(Packet* packet); void HandlePacket(Packet* packet);
int main(int argc, char** argv) { int main(int argc, char** argv) {
@@ -50,9 +51,9 @@ int main(int argc, char** argv) {
Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0"); Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0");
Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1"); Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1");
Game::logger->Log("AuthServer", "Starting Auth server..."); LOG("Starting Auth server...");
Game::logger->Log("AuthServer", "Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR); LOG("Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
Game::logger->Log("AuthServer", "Compiled on: %s", __TIMESTAMP__); LOG("Compiled on: %s", __TIMESTAMP__);
//Connect to the MySQL Database //Connect to the MySQL Database
std::string mysql_host = Game::config->GetValue("mysql_host"); std::string mysql_host = Game::config->GetValue("mysql_host");
@@ -63,7 +64,7 @@ int main(int argc, char** argv) {
try { try {
Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password); Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password);
} catch (sql::SQLException& ex) { } catch (sql::SQLException& ex) {
Game::logger->Log("AuthServer", "Got an error while connecting to the database: %s", ex.what()); LOG("Got an error while connecting to the database: %s", ex.what());
Database::Destroy("AuthServer"); Database::Destroy("AuthServer");
delete Game::server; delete Game::server;
delete Game::logger; delete Game::logger;
@@ -83,6 +84,8 @@ int main(int argc, char** argv) {
delete res; delete res;
delete stmt; delete stmt;
Game::randomEngine = std::mt19937(time(0));
//It's safe to pass 'localhost' here, as the IP is only used as the external IP. //It's safe to pass 'localhost' here, as the IP is only used as the external IP.
uint32_t maxClients = 50; uint32_t maxClients = 50;
uint32_t ourPort = 1001; //LU client is hardcoded to use this for auth port, so I'm making it the default. uint32_t ourPort = 1001; //LU client is hardcoded to use this for auth port, so I'm making it the default.
@@ -158,7 +161,7 @@ int main(int argc, char** argv) {
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
dLogger* SetupLogger() { Logger* SetupLogger() {
std::string logPath = (BinaryPathFinder::GetBinaryDir() / ("logs/AuthServer_" + std::to_string(time(nullptr)) + ".log")).string(); std::string logPath = (BinaryPathFinder::GetBinaryDir() / ("logs/AuthServer_" + std::to_string(time(nullptr)) + ".log")).string();
bool logToConsole = false; bool logToConsole = false;
bool logDebugStatements = false; bool logDebugStatements = false;
@@ -167,7 +170,7 @@ dLogger* SetupLogger() {
logDebugStatements = true; logDebugStatements = true;
#endif #endif
return new dLogger(logPath, logToConsole, logDebugStatements); return new Logger(logPath, logToConsole, logDebugStatements);
} }
void HandlePacket(Packet* packet) { void HandlePacket(Packet* packet) {

View File

@@ -8,7 +8,7 @@
#include <regex> #include <regex>
#include "dCommonVars.h" #include "dCommonVars.h"
#include "dLogger.h" #include "Logger.h"
#include "dConfig.h" #include "dConfig.h"
#include "Database.h" #include "Database.h"
#include "Game.h" #include "Game.h"

View File

@@ -3,10 +3,11 @@
#include "Database.h" #include "Database.h"
#include <vector> #include <vector>
#include "PacketUtils.h" #include "PacketUtils.h"
#include "BitStreamUtils.h"
#include "Game.h" #include "Game.h"
#include "dServer.h" #include "dServer.h"
#include "GeneralUtils.h" #include "GeneralUtils.h"
#include "dLogger.h" #include "Logger.h"
#include "eAddFriendResponseCode.h" #include "eAddFriendResponseCode.h"
#include "eAddFriendResponseType.h" #include "eAddFriendResponseType.h"
#include "RakString.h" #include "RakString.h"
@@ -75,11 +76,11 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
//Now, we need to send the friendlist to the server they came from: //Now, we need to send the friendlist to the server they came from:
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(playerID); bitStream.Write(playerID);
//portion that will get routed: //portion that will get routed:
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GET_FRIENDS_LIST_RESPONSE); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GET_FRIENDS_LIST_RESPONSE);
bitStream.Write<uint8_t>(0); bitStream.Write<uint8_t>(0);
bitStream.Write<uint16_t>(1); //Length of packet -- just writing one as it doesn't matter, client skips it. bitStream.Write<uint16_t>(1); //Length of packet -- just writing one as it doesn't matter, client skips it.
bitStream.Write((uint16_t)friends.size()); bitStream.Write((uint16_t)friends.size());
@@ -117,6 +118,11 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
inStream.Read(isBestFriendRequest); inStream.Read(isBestFriendRequest);
auto requestor = playerContainer.GetPlayerData(requestorPlayerID); auto requestor = playerContainer.GetPlayerData(requestorPlayerID);
if (!requestor) {
LOG("No requestor player %llu sent to %s found.", requestorPlayerID, playerName.c_str());
return;
}
if (requestor->playerName == playerName) { if (requestor->playerName == playerName) {
SendFriendResponse(requestor, requestor, eAddFriendResponseType::MYTHRAN); SendFriendResponse(requestor, requestor, eAddFriendResponseType::MYTHRAN);
return; return;
@@ -396,7 +402,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
std::string message = PacketUtils::ReadString(0x66, packet, true, 512); std::string message = PacketUtils::ReadString(0x66, packet, true, 512);
Game::logger->Log("ChatPacketHandler", "Got a message from (%s) [%d]: %s", senderName.c_str(), channel, message.c_str()); LOG("Got a message from (%s) [%d]: %s", senderName.c_str(), channel, message.c_str());
if (channel != 8) return; if (channel != 8) return;
@@ -412,21 +418,21 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
const auto otherName = std::string(otherMember->playerName.c_str()); const auto otherName = std::string(otherMember->playerName.c_str());
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(otherMember->playerID); bitStream.Write(otherMember->playerID);
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
bitStream.Write(otherMember->playerID); bitStream.Write(otherMember->playerID);
bitStream.Write<uint8_t>(8); bitStream.Write<uint8_t>(8);
bitStream.Write<unsigned int>(69); bitStream.Write<unsigned int>(69);
PacketUtils::WritePacketWString(senderName, 33, &bitStream); bitStream.Write(LUWString(senderName));
bitStream.Write(sender->playerID); bitStream.Write(sender->playerID);
bitStream.Write<uint16_t>(0); bitStream.Write<uint16_t>(0);
bitStream.Write<uint8_t>(0); //not mythran nametag bitStream.Write<uint8_t>(0); //not mythran nametag
PacketUtils::WritePacketWString(otherName, 33, &bitStream); bitStream.Write(LUWString(otherName));
bitStream.Write<uint8_t>(0); //not mythran for receiver bitStream.Write<uint8_t>(0); //not mythran for receiver
bitStream.Write<uint8_t>(0); //teams? bitStream.Write<uint8_t>(0); //teams?
PacketUtils::WritePacketWString(message, 512, &bitStream); bitStream.Write(LUWString(message, 512));
SystemAddress sysAddr = otherMember->sysAddr; SystemAddress sysAddr = otherMember->sysAddr;
SEND_PACKET; SEND_PACKET;
@@ -434,7 +440,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
} }
void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) { void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
LWOOBJID senderID = PacketUtils::ReadPacketS64(0x08, packet); LWOOBJID senderID = PacketUtils::ReadS64(0x08, packet);
std::string receiverName = PacketUtils::ReadString(0x66, packet, true); std::string receiverName = PacketUtils::ReadString(0x66, packet, true);
std::string message = PacketUtils::ReadString(0xAA, packet, true, 512); std::string message = PacketUtils::ReadString(0xAA, packet, true, 512);
@@ -451,21 +457,21 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
//To the sender: //To the sender:
{ {
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(goonA->playerID); bitStream.Write(goonA->playerID);
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
bitStream.Write(goonA->playerID); bitStream.Write(goonA->playerID);
bitStream.Write<uint8_t>(7); bitStream.Write<uint8_t>(7);
bitStream.Write<unsigned int>(69); bitStream.Write<unsigned int>(69);
PacketUtils::WritePacketWString(goonAName, 33, &bitStream); bitStream.Write(LUWString(goonAName));
bitStream.Write(goonA->playerID); bitStream.Write(goonA->playerID);
bitStream.Write<uint16_t>(0); bitStream.Write<uint16_t>(0);
bitStream.Write<uint8_t>(0); //not mythran nametag bitStream.Write<uint8_t>(0); //not mythran nametag
PacketUtils::WritePacketWString(goonBName, 33, &bitStream); bitStream.Write(LUWString(goonBName));
bitStream.Write<uint8_t>(0); //not mythran for receiver bitStream.Write<uint8_t>(0); //not mythran for receiver
bitStream.Write<uint8_t>(0); //success bitStream.Write<uint8_t>(0); //success
PacketUtils::WritePacketWString(message, 512, &bitStream); bitStream.Write(LUWString(message, 512));
SystemAddress sysAddr = goonA->sysAddr; SystemAddress sysAddr = goonA->sysAddr;
SEND_PACKET; SEND_PACKET;
@@ -474,21 +480,21 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
//To the receiver: //To the receiver:
{ {
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(goonB->playerID); bitStream.Write(goonB->playerID);
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
bitStream.Write(goonA->playerID); bitStream.Write(goonA->playerID);
bitStream.Write<uint8_t>(7); bitStream.Write<uint8_t>(7);
bitStream.Write<unsigned int>(69); bitStream.Write<unsigned int>(69);
PacketUtils::WritePacketWString(goonAName, 33, &bitStream); bitStream.Write(LUWString(goonAName));
bitStream.Write(goonA->playerID); bitStream.Write(goonA->playerID);
bitStream.Write<uint16_t>(0); bitStream.Write<uint16_t>(0);
bitStream.Write<uint8_t>(0); //not mythran nametag bitStream.Write<uint8_t>(0); //not mythran nametag
PacketUtils::WritePacketWString(goonBName, 33, &bitStream); bitStream.Write(LUWString(goonBName));
bitStream.Write<uint8_t>(0); //not mythran for receiver bitStream.Write<uint8_t>(0); //not mythran for receiver
bitStream.Write<uint8_t>(3); //new whisper bitStream.Write<uint8_t>(3); //new whisper
PacketUtils::WritePacketWString(message, 512, &bitStream); bitStream.Write(LUWString(message, 512));
SystemAddress sysAddr = goonB->sysAddr; SystemAddress sysAddr = goonB->sysAddr;
SEND_PACKET; SEND_PACKET;
@@ -526,13 +532,13 @@ void ChatPacketHandler::HandleTeamInvite(Packet* packet) {
if (team->memberIDs.size() > 3) { if (team->memberIDs.size() > 3) {
// no more teams greater than 4 // no more teams greater than 4
Game::logger->Log("ChatPacketHandler", "Someone tried to invite a 5th player to a team"); LOG("Someone tried to invite a 5th player to a team");
return; return;
} }
SendTeamInvite(other, player); SendTeamInvite(other, player);
Game::logger->Log("ChatPacketHandler", "Got team invite: %llu -> %s", playerID, invitedPlayer.c_str()); LOG("Got team invite: %llu -> %s", playerID, invitedPlayer.c_str());
} }
void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet) { void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet) {
@@ -546,7 +552,7 @@ void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet) {
LWOOBJID leaderID = LWOOBJID_EMPTY; LWOOBJID leaderID = LWOOBJID_EMPTY;
inStream.Read(leaderID); inStream.Read(leaderID);
Game::logger->Log("ChatPacketHandler", "Accepted invite: %llu -> %llu (%d)", playerID, leaderID, declined); LOG("Accepted invite: %llu -> %llu (%d)", playerID, leaderID, declined);
if (declined) { if (declined) {
return; return;
@@ -555,13 +561,13 @@ void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet) {
auto* team = playerContainer.GetTeam(leaderID); auto* team = playerContainer.GetTeam(leaderID);
if (team == nullptr) { if (team == nullptr) {
Game::logger->Log("ChatPacketHandler", "Failed to find team for leader (%llu)", leaderID); LOG("Failed to find team for leader (%llu)", leaderID);
team = playerContainer.GetTeam(playerID); team = playerContainer.GetTeam(playerID);
} }
if (team == nullptr) { if (team == nullptr) {
Game::logger->Log("ChatPacketHandler", "Failed to find team for player (%llu)", playerID); LOG("Failed to find team for player (%llu)", playerID);
return; return;
} }
@@ -577,7 +583,7 @@ void ChatPacketHandler::HandleTeamLeave(Packet* packet) {
auto* team = playerContainer.GetTeam(playerID); auto* team = playerContainer.GetTeam(playerID);
Game::logger->Log("ChatPacketHandler", "(%llu) leaving team", playerID); LOG("(%llu) leaving team", playerID);
if (team != nullptr) { if (team != nullptr) {
playerContainer.RemoveMember(team, playerID, false, false, true); playerContainer.RemoveMember(team, playerID, false, false, true);
@@ -591,7 +597,7 @@ void ChatPacketHandler::HandleTeamKick(Packet* packet) {
std::string kickedPlayer = PacketUtils::ReadString(0x14, packet, true); std::string kickedPlayer = PacketUtils::ReadString(0x14, packet, true);
Game::logger->Log("ChatPacketHandler", "(%llu) kicking (%s) from team", playerID, kickedPlayer.c_str()); LOG("(%llu) kicking (%s) from team", playerID, kickedPlayer.c_str());
auto* kicked = playerContainer.GetPlayerData(kickedPlayer); auto* kicked = playerContainer.GetPlayerData(kickedPlayer);
@@ -621,7 +627,7 @@ void ChatPacketHandler::HandleTeamPromote(Packet* packet) {
std::string promotedPlayer = PacketUtils::ReadString(0x14, packet, true); std::string promotedPlayer = PacketUtils::ReadString(0x14, packet, true);
Game::logger->Log("ChatPacketHandler", "(%llu) promoting (%s) to team leader", playerID, promotedPlayer.c_str()); LOG("(%llu) promoting (%s) to team leader", playerID, promotedPlayer.c_str());
auto* promoted = playerContainer.GetPlayerData(promotedPlayer); auto* promoted = playerContainer.GetPlayerData(promotedPlayer);
@@ -709,13 +715,13 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender) { void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender) {
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver->playerID);
//portion that will get routed: //portion that will get routed:
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::TEAM_INVITE); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::TEAM_INVITE);
PacketUtils::WritePacketWString(sender->playerName.c_str(), 33, &bitStream); bitStream.Write(LUWString(sender->playerName.c_str()));
bitStream.Write(sender->playerID); bitStream.Write(sender->playerID);
SystemAddress sysAddr = receiver->sysAddr; SystemAddress sysAddr = receiver->sysAddr;
@@ -724,7 +730,7 @@ void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender)
void ChatPacketHandler::SendTeamInviteConfirm(PlayerData* receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName) { void ChatPacketHandler::SendTeamInviteConfirm(PlayerData* receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName) {
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver->playerID);
//portion that will get routed: //portion that will get routed:
@@ -751,7 +757,7 @@ void ChatPacketHandler::SendTeamInviteConfirm(PlayerData* receiver, bool bLeader
void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName) { void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName) {
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver->playerID);
//portion that will get routed: //portion that will get routed:
@@ -776,7 +782,7 @@ void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderI
void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64PlayerID) { void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64PlayerID) {
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver->playerID);
//portion that will get routed: //portion that will get routed:
@@ -793,7 +799,7 @@ void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64Play
void ChatPacketHandler::SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID) { void ChatPacketHandler::SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID) {
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver->playerID);
//portion that will get routed: //portion that will get routed:
@@ -822,7 +828,7 @@ void ChatPacketHandler::SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTria
void ChatPacketHandler::SendTeamRemovePlayer(PlayerData* receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName) { void ChatPacketHandler::SendTeamRemovePlayer(PlayerData* receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName) {
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver->playerID);
//portion that will get routed: //portion that will get routed:
@@ -848,7 +854,7 @@ void ChatPacketHandler::SendTeamRemovePlayer(PlayerData* receiver, bool bDisband
void ChatPacketHandler::SendTeamSetOffWorldFlag(PlayerData* receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID) { void ChatPacketHandler::SendTeamSetOffWorldFlag(PlayerData* receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID) {
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver->playerID);
//portion that will get routed: //portion that will get routed:
@@ -882,16 +888,16 @@ void ChatPacketHandler::SendFriendUpdate(PlayerData* friendData, PlayerData* pla
[bool] - is FTP*/ [bool] - is FTP*/
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(friendData->playerID); bitStream.Write(friendData->playerID);
//portion that will get routed: //portion that will get routed:
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::UPDATE_FRIEND_NOTIFY); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::UPDATE_FRIEND_NOTIFY);
bitStream.Write<uint8_t>(notifyType); bitStream.Write<uint8_t>(notifyType);
std::string playerName = playerData->playerName.c_str(); std::string playerName = playerData->playerName.c_str();
PacketUtils::WritePacketWString(playerName, 33, &bitStream); bitStream.Write(LUWString(playerName));
bitStream.Write(playerData->zoneID.GetMapID()); bitStream.Write(playerData->zoneID.GetMapID());
bitStream.Write(playerData->zoneID.GetInstanceID()); bitStream.Write(playerData->zoneID.GetInstanceID());
@@ -921,12 +927,12 @@ void ChatPacketHandler::SendFriendRequest(PlayerData* receiver, PlayerData* send
} }
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver->playerID);
//portion that will get routed: //portion that will get routed:
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_REQUEST); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_REQUEST);
PacketUtils::WritePacketWString(sender->playerName.c_str(), 33, &bitStream); bitStream.Write(LUWString(sender->playerName.c_str()));
bitStream.Write<uint8_t>(0); // This is a BFF flag however this is unused in live and does not have an implementation client side. bitStream.Write<uint8_t>(0); // This is a BFF flag however this is unused in live and does not have an implementation client side.
SystemAddress sysAddr = receiver->sysAddr; SystemAddress sysAddr = receiver->sysAddr;
@@ -937,16 +943,16 @@ void ChatPacketHandler::SendFriendResponse(PlayerData* receiver, PlayerData* sen
if (!receiver || !sender) return; if (!receiver || !sender) return;
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver->playerID);
// Portion that will get routed: // Portion that will get routed:
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_RESPONSE); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_RESPONSE);
bitStream.Write(responseCode); bitStream.Write(responseCode);
// For all requests besides accepted, write a flag that says whether or not we are already best friends with the receiver. // For all requests besides accepted, write a flag that says whether or not we are already best friends with the receiver.
bitStream.Write<uint8_t>(responseCode != eAddFriendResponseType::ACCEPTED ? isBestFriendsAlready : sender->sysAddr != UNASSIGNED_SYSTEM_ADDRESS); bitStream.Write<uint8_t>(responseCode != eAddFriendResponseType::ACCEPTED ? isBestFriendsAlready : sender->sysAddr != UNASSIGNED_SYSTEM_ADDRESS);
// Then write the player name // Then write the player name
PacketUtils::WritePacketWString(sender->playerName.c_str(), 33, &bitStream); bitStream.Write(LUWString(sender->playerName.c_str()));
// Then if this is an acceptance code, write the following extra info. // Then if this is an acceptance code, write the following extra info.
if (responseCode == eAddFriendResponseType::ACCEPTED) { if (responseCode == eAddFriendResponseType::ACCEPTED) {
bitStream.Write(sender->playerID); bitStream.Write(sender->playerID);
@@ -962,13 +968,13 @@ void ChatPacketHandler::SendRemoveFriend(PlayerData* receiver, std::string& pers
if (!receiver) return; if (!receiver) return;
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver->playerID);
//portion that will get routed: //portion that will get routed:
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::REMOVE_FRIEND_RESPONSE); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::REMOVE_FRIEND_RESPONSE);
bitStream.Write<uint8_t>(isSuccessful); //isOnline bitStream.Write<uint8_t>(isSuccessful); //isOnline
PacketUtils::WritePacketWString(personToRemove, 33, &bitStream); bitStream.Write(LUWString(personToRemove));
SystemAddress sysAddr = receiver->sysAddr; SystemAddress sysAddr = receiver->sysAddr;
SEND_PACKET; SEND_PACKET;

View File

@@ -6,7 +6,7 @@
//DLU Includes: //DLU Includes:
#include "dCommonVars.h" #include "dCommonVars.h"
#include "dServer.h" #include "dServer.h"
#include "dLogger.h" #include "Logger.h"
#include "Database.h" #include "Database.h"
#include "dConfig.h" #include "dConfig.h"
#include "dChatFilter.h" #include "dChatFilter.h"
@@ -27,16 +27,17 @@
#include <MessageIdentifiers.h> #include <MessageIdentifiers.h>
namespace Game { namespace Game {
dLogger* logger = nullptr; Logger* logger = nullptr;
dServer* server = nullptr; dServer* server = nullptr;
dConfig* config = nullptr; dConfig* config = nullptr;
dChatFilter* chatFilter = nullptr; dChatFilter* chatFilter = nullptr;
AssetManager* assetManager = nullptr; AssetManager* assetManager = nullptr;
bool shouldShutdown = false; bool shouldShutdown = false;
std::mt19937 randomEngine;
} }
dLogger* SetupLogger(); Logger* SetupLogger();
void HandlePacket(Packet* packet); void HandlePacket(Packet* packet);
PlayerContainer playerContainer; PlayerContainer playerContainer;
@@ -57,9 +58,9 @@ int main(int argc, char** argv) {
Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0"); Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0");
Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1"); Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1");
Game::logger->Log("ChatServer", "Starting Chat server..."); LOG("Starting Chat server...");
Game::logger->Log("ChatServer", "Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR); LOG("Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
Game::logger->Log("ChatServer", "Compiled on: %s", __TIMESTAMP__); LOG("Compiled on: %s", __TIMESTAMP__);
try { try {
std::string clientPathStr = Game::config->GetValue("client_location"); std::string clientPathStr = Game::config->GetValue("client_location");
@@ -71,7 +72,7 @@ int main(int argc, char** argv) {
Game::assetManager = new AssetManager(clientPath); Game::assetManager = new AssetManager(clientPath);
} catch (std::runtime_error& ex) { } catch (std::runtime_error& ex) {
Game::logger->Log("ChatServer", "Got an error while setting up assets: %s", ex.what()); LOG("Got an error while setting up assets: %s", ex.what());
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@@ -85,7 +86,7 @@ int main(int argc, char** argv) {
try { try {
Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password); Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password);
} catch (sql::SQLException& ex) { } catch (sql::SQLException& ex) {
Game::logger->Log("ChatServer", "Got an error while connecting to the database: %s", ex.what()); LOG("Got an error while connecting to the database: %s", ex.what());
Database::Destroy("ChatServer"); Database::Destroy("ChatServer");
delete Game::server; delete Game::server;
delete Game::logger; delete Game::logger;
@@ -115,6 +116,8 @@ int main(int argc, char** argv) {
Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", bool(std::stoi(Game::config->GetValue("dont_generate_dcf")))); Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", bool(std::stoi(Game::config->GetValue("dont_generate_dcf"))));
Game::randomEngine = std::mt19937(time(0));
//Run it until server gets a kill message from Master: //Run it until server gets a kill message from Master:
auto t = std::chrono::high_resolution_clock::now(); auto t = std::chrono::high_resolution_clock::now();
Packet* packet = nullptr; Packet* packet = nullptr;
@@ -182,7 +185,7 @@ int main(int argc, char** argv) {
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
dLogger* SetupLogger() { Logger* SetupLogger() {
std::string logPath = (BinaryPathFinder::GetBinaryDir() / ("logs/ChatServer_" + std::to_string(time(nullptr)) + ".log")).string(); std::string logPath = (BinaryPathFinder::GetBinaryDir() / ("logs/ChatServer_" + std::to_string(time(nullptr)) + ".log")).string();
bool logToConsole = false; bool logToConsole = false;
bool logDebugStatements = false; bool logDebugStatements = false;
@@ -191,16 +194,16 @@ dLogger* SetupLogger() {
logDebugStatements = true; logDebugStatements = true;
#endif #endif
return new dLogger(logPath, logToConsole, logDebugStatements); return new Logger(logPath, logToConsole, logDebugStatements);
} }
void HandlePacket(Packet* packet) { void HandlePacket(Packet* packet) {
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) { if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
Game::logger->Log("ChatServer", "A server has disconnected, erasing their connected players from the list."); LOG("A server has disconnected, erasing their connected players from the list.");
} }
if (packet->data[0] == ID_NEW_INCOMING_CONNECTION) { if (packet->data[0] == ID_NEW_INCOMING_CONNECTION) {
Game::logger->Log("ChatServer", "A server is connecting, awaiting user list."); LOG("A server is connecting, awaiting user list.");
} }
if (packet->length < 4) return; // Nothing left to process. Need 4 bytes to continue. if (packet->length < 4) return; // Nothing left to process. Need 4 bytes to continue.
@@ -231,7 +234,7 @@ void HandlePacket(Packet* packet) {
} }
default: default:
Game::logger->Log("ChatServer", "Unknown CHAT_INTERNAL id: %i", int(packet->data[3])); LOG("Unknown CHAT_INTERNAL id: %i", int(packet->data[3]));
} }
} }
@@ -242,7 +245,7 @@ void HandlePacket(Packet* packet) {
break; break;
case eChatMessageType::GET_IGNORE_LIST: case eChatMessageType::GET_IGNORE_LIST:
Game::logger->Log("ChatServer", "Asked for ignore list, but is unimplemented right now."); LOG("Asked for ignore list, but is unimplemented right now.");
break; break;
case eChatMessageType::TEAM_GET_STATUS: case eChatMessageType::TEAM_GET_STATUS:
@@ -300,19 +303,19 @@ void HandlePacket(Packet* packet) {
break; break;
default: default:
Game::logger->Log("ChatServer", "Unknown CHAT id: %i", int(packet->data[3])); LOG("Unknown CHAT id: %i", int(packet->data[3]));
} }
} }
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::WORLD) { if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::WORLD) {
switch (static_cast<eWorldMessageType>(packet->data[3])) { switch (static_cast<eWorldMessageType>(packet->data[3])) {
case eWorldMessageType::ROUTE_PACKET: { case eWorldMessageType::ROUTE_PACKET: {
Game::logger->Log("ChatServer", "Routing packet from world"); LOG("Routing packet from world");
break; break;
} }
default: default:
Game::logger->Log("ChatServer", "Unknown World id: %i", int(packet->data[3])); LOG("Unknown World id: %i", int(packet->data[3]));
} }
} }
} }

View File

@@ -3,13 +3,15 @@
#include <iostream> #include <iostream>
#include <algorithm> #include <algorithm>
#include "Game.h" #include "Game.h"
#include "dLogger.h" #include "Logger.h"
#include "ChatPacketHandler.h" #include "ChatPacketHandler.h"
#include "GeneralUtils.h" #include "GeneralUtils.h"
#include "PacketUtils.h" #include "BitStreamUtils.h"
#include "Database.h" #include "Database.h"
#include "eConnectionType.h" #include "eConnectionType.h"
#include "eChatInternalMessageType.h" #include "eChatInternalMessageType.h"
#include "ChatPackets.h"
#include "dConfig.h"
PlayerContainer::PlayerContainer() { PlayerContainer::PlayerContainer() {
} }
@@ -18,6 +20,10 @@ PlayerContainer::~PlayerContainer() {
mPlayers.clear(); mPlayers.clear();
} }
TeamData::TeamData() {
lootFlag = Game::config->GetValue("default_team_loot") == "0" ? 0 : 1;
}
void PlayerContainer::InsertPlayer(Packet* packet) { void PlayerContainer::InsertPlayer(Packet* packet) {
CINSTREAM_SKIP_HEADER; CINSTREAM_SKIP_HEADER;
PlayerData* data = new PlayerData(); PlayerData* data = new PlayerData();
@@ -38,7 +44,7 @@ void PlayerContainer::InsertPlayer(Packet* packet) {
mNames[data->playerID] = GeneralUtils::UTF8ToUTF16(data->playerName); mNames[data->playerID] = GeneralUtils::UTF8ToUTF16(data->playerName);
mPlayers.insert(std::make_pair(data->playerID, data)); mPlayers.insert(std::make_pair(data->playerID, data));
Game::logger->Log("PlayerContainer", "Added user: %s (%llu), zone: %i", data->playerName.c_str(), data->playerID, data->zoneID.GetMapID()); LOG("Added user: %s (%llu), zone: %i", data->playerName.c_str(), data->playerID, data->zoneID.GetMapID());
auto* insertLog = Database::CreatePreppedStmt("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);"); auto* insertLog = Database::CreatePreppedStmt("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);");
@@ -81,7 +87,7 @@ void PlayerContainer::RemovePlayer(Packet* packet) {
} }
} }
Game::logger->Log("PlayerContainer", "Removed user: %llu", playerID); LOG("Removed user: %llu", playerID);
mPlayers.erase(playerID); mPlayers.erase(playerID);
auto* insertLog = Database::CreatePreppedStmt("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);"); auto* insertLog = Database::CreatePreppedStmt("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);");
@@ -104,7 +110,7 @@ void PlayerContainer::MuteUpdate(Packet* packet) {
auto* player = this->GetPlayerData(playerID); auto* player = this->GetPlayerData(playerID);
if (player == nullptr) { if (player == nullptr) {
Game::logger->Log("PlayerContainer", "Failed to find user: %llu", playerID); LOG("Failed to find user: %llu", playerID);
return; return;
} }
@@ -146,7 +152,7 @@ void PlayerContainer::CreateTeamServer(Packet* packet) {
void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time) { void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time) {
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::MUTE_UPDATE); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::MUTE_UPDATE);
bitStream.Write(player); bitStream.Write(player);
bitStream.Write(time); bitStream.Write(time);
@@ -207,6 +213,14 @@ TeamData* PlayerContainer::GetTeam(LWOOBJID playerID) {
} }
void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID) { void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID) {
if (team->memberIDs.size() >= 4){
LOG("Tried to add player to team that already had 4 players");
auto* player = GetPlayerData(playerID);
if (!player) return;
ChatPackets::SendSystemMessage(player->sysAddr, u"The teams is full! You have not been added to a team!");
return;
}
const auto index = std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID); const auto index = std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID);
if (index != team->memberIDs.end()) return; if (index != team->memberIDs.end()) return;
@@ -345,7 +359,7 @@ void PlayerContainer::TeamStatusUpdate(TeamData* team) {
void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) { void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) {
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::TEAM_UPDATE); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::TEAM_UPDATE);
bitStream.Write(team->teamID); bitStream.Write(team->teamID);
bitStream.Write(deleteTeam); bitStream.Write(deleteTeam);

View File

@@ -18,6 +18,7 @@ struct PlayerData {
}; };
struct TeamData { struct TeamData {
TeamData();
LWOOBJID teamID = LWOOBJID_EMPTY; // Internal use LWOOBJID teamID = LWOOBJID_EMPTY; // Internal use
LWOOBJID leaderID = LWOOBJID_EMPTY; LWOOBJID leaderID = LWOOBJID_EMPTY;
std::vector<LWOOBJID> memberIDs{}; std::vector<LWOOBJID> memberIDs{};

View File

@@ -2,7 +2,7 @@
#define __AMF3__H__ #define __AMF3__H__
#include "dCommonVars.h" #include "dCommonVars.h"
#include "dLogger.h" #include "Logger.h"
#include "Game.h" #include "Game.h"
#include <unordered_map> #include <unordered_map>

View File

@@ -1,7 +1,7 @@
#include "AmfSerialize.h" #include "AmfSerialize.h"
#include "Game.h" #include "Game.h"
#include "dLogger.h" #include "Logger.h"
// Writes an AMFValue pointer to a RakNet::BitStream // Writes an AMFValue pointer to a RakNet::BitStream
template<> template<>
@@ -29,7 +29,7 @@ void RakNet::BitStream::Write<AMFBaseValue&>(AMFBaseValue& value) {
break; break;
} }
default: { default: {
Game::logger->Log("AmfSerialize", "Encountered unwritable AMFType %i!", type); LOG("Encountered unwritable AMFType %i!", type);
} }
case eAmf::Undefined: case eAmf::Undefined:
case eAmf::Null: case eAmf::Null:

View File

@@ -9,7 +9,7 @@
#include "Database.h" #include "Database.h"
#include "Game.h" #include "Game.h"
#include "ZCompression.h" #include "ZCompression.h"
#include "dLogger.h" #include "Logger.h"
//! Forward declarations //! Forward declarations
@@ -59,14 +59,14 @@ uint32_t BrickByBrickFix::TruncateBrokenBrickByBrickXml() {
completeUncompressedModel.append((char*)uncompressedChunk.get()); completeUncompressedModel.append((char*)uncompressedChunk.get());
completeUncompressedModel.resize(previousSize + actualUncompressedSize); completeUncompressedModel.resize(previousSize + actualUncompressedSize);
} else { } else {
Game::logger->Log("BrickByBrickFix", "Failed to inflate chunk %i for model %llu. Error: %i", chunkCount, modelId, err); LOG("Failed to inflate chunk %i for model %llu. Error: %i", chunkCount, modelId, err);
break; break;
} }
chunkCount++; chunkCount++;
} }
std::unique_ptr<tinyxml2::XMLDocument> document = std::make_unique<tinyxml2::XMLDocument>(); std::unique_ptr<tinyxml2::XMLDocument> document = std::make_unique<tinyxml2::XMLDocument>();
if (!document) { if (!document) {
Game::logger->Log("BrickByBrickFix", "Failed to initialize tinyxml document. Aborting."); LOG("Failed to initialize tinyxml document. Aborting.");
return 0; return 0;
} }
@@ -75,8 +75,7 @@ uint32_t BrickByBrickFix::TruncateBrokenBrickByBrickXml() {
"</LXFML>", "</LXFML>",
completeUncompressedModel.length() >= 15 ? completeUncompressedModel.length() - 15 : 0) == std::string::npos completeUncompressedModel.length() >= 15 ? completeUncompressedModel.length() - 15 : 0) == std::string::npos
) { ) {
Game::logger->Log("BrickByBrickFix", LOG("Brick-by-brick model %llu will be deleted!", modelId);
"Brick-by-brick model %llu will be deleted!", modelId);
ugcModelToDelete->setInt64(1, modelsToTruncate->getInt64(1)); ugcModelToDelete->setInt64(1, modelsToTruncate->getInt64(1));
pcModelToDelete->setInt64(1, modelsToTruncate->getInt64(1)); pcModelToDelete->setInt64(1, modelsToTruncate->getInt64(1));
ugcModelToDelete->execute(); ugcModelToDelete->execute();
@@ -85,8 +84,7 @@ uint32_t BrickByBrickFix::TruncateBrokenBrickByBrickXml() {
} }
} }
} else { } else {
Game::logger->Log("BrickByBrickFix", LOG("Brick-by-brick model %llu will be deleted!", modelId);
"Brick-by-brick model %llu will be deleted!", modelId);
ugcModelToDelete->setInt64(1, modelsToTruncate->getInt64(1)); ugcModelToDelete->setInt64(1, modelsToTruncate->getInt64(1));
pcModelToDelete->setInt64(1, modelsToTruncate->getInt64(1)); pcModelToDelete->setInt64(1, modelsToTruncate->getInt64(1));
ugcModelToDelete->execute(); ugcModelToDelete->execute();
@@ -140,12 +138,10 @@ uint32_t BrickByBrickFix::UpdateBrickByBrickModelsToSd0() {
insertionStatement->setInt64(2, modelId); insertionStatement->setInt64(2, modelId);
try { try {
insertionStatement->executeUpdate(); insertionStatement->executeUpdate();
Game::logger->Log("BrickByBrickFix", "Updated model %i to sd0", modelId); LOG("Updated model %i to sd0", modelId);
updatedModels++; updatedModels++;
} catch (sql::SQLException exception) { } catch (sql::SQLException exception) {
Game::logger->Log( LOG("Failed to update model %i. This model should be inspected manually to see why."
"BrickByBrickFix",
"Failed to update model %i. This model should be inspected manually to see why."
"The database error is %s", modelId, exception.what()); "The database error is %s", modelId, exception.what());
} }
} }

View File

@@ -4,7 +4,7 @@ set(DCOMMON_SOURCES
"BinaryIO.cpp" "BinaryIO.cpp"
"dConfig.cpp" "dConfig.cpp"
"Diagnostics.cpp" "Diagnostics.cpp"
"dLogger.cpp" "Logger.cpp"
"GeneralUtils.cpp" "GeneralUtils.cpp"
"LDFFormat.cpp" "LDFFormat.cpp"
"MD5.cpp" "MD5.cpp"
@@ -12,7 +12,7 @@ set(DCOMMON_SOURCES
"NiPoint3.cpp" "NiPoint3.cpp"
"NiQuaternion.cpp" "NiQuaternion.cpp"
"SHA512.cpp" "SHA512.cpp"
"Type.cpp" "Demangler.cpp"
"ZCompression.cpp" "ZCompression.cpp"
"BrickByBrickFix.cpp" "BrickByBrickFix.cpp"
"BinaryPathFinder.cpp" "BinaryPathFinder.cpp"

29
dCommon/Demangler.cpp Normal file
View File

@@ -0,0 +1,29 @@
#include "Demangler.h"
#ifdef __GNUG__
#include <cstdlib>
#include <cxxabi.h>
#include <memory>
#include <typeinfo>
std::string Demangler::Demangle(const char* name) {
// some arbitrary value to eliminate the compiler warning
// -4 is not a valid return value for __cxa_demangle so we'll use that.
int status = -4;
// __cxa_demangle requires that we free the returned char*
std::unique_ptr<char, void (*)(void*)> res{
abi::__cxa_demangle(name, NULL, NULL, &status),
std::free
};
return (status == 0) ? res.get() : "";
}
#else // __GNUG__
// does nothing if not g++
std::string Demangler::Demangle(const char* name) {
return name;
}
#endif // __GNUG__

9
dCommon/Demangler.h Normal file
View File

@@ -0,0 +1,9 @@
#pragma once
#include <string>
namespace Demangler {
// Given a char* containing a mangled name, return a std::string containing the demangled name.
// If the function fails for any reason, it returns an empty string.
std::string Demangle(const char* name);
}

View File

@@ -1,6 +1,6 @@
#include "Diagnostics.h" #include "Diagnostics.h"
#include "Game.h" #include "Game.h"
#include "dLogger.h" #include "Logger.h"
// If we're on Win32, we'll include our minidump writer // If we're on Win32, we'll include our minidump writer
#ifdef _WIN32 #ifdef _WIN32
@@ -9,7 +9,7 @@
#include <Dbghelp.h> #include <Dbghelp.h>
#include "Game.h" #include "Game.h"
#include "dLogger.h" #include "Logger.h"
void make_minidump(EXCEPTION_POINTERS* e) { void make_minidump(EXCEPTION_POINTERS* e) {
auto hDbgHelp = LoadLibraryA("dbghelp"); auto hDbgHelp = LoadLibraryA("dbghelp");
@@ -28,7 +28,7 @@ void make_minidump(EXCEPTION_POINTERS* e) {
"_%4d%02d%02d_%02d%02d%02d.dmp", "_%4d%02d%02d_%02d%02d%02d.dmp",
t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond); t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond);
} }
Game::logger->Log("Diagnostics", "Creating crash dump %s", name); LOG("Creating crash dump %s", name);
auto hFile = CreateFileA(name, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); auto hFile = CreateFileA(name, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile == INVALID_HANDLE_VALUE) if (hFile == INVALID_HANDLE_VALUE)
return; return;
@@ -83,7 +83,7 @@ struct bt_ctx {
static inline void Bt(struct backtrace_state* state) { static inline void Bt(struct backtrace_state* state) {
std::string fileName = Diagnostics::GetOutDirectory() + "crash_" + Diagnostics::GetProcessName() + "_" + std::to_string(getpid()) + ".log"; std::string fileName = Diagnostics::GetOutDirectory() + "crash_" + Diagnostics::GetProcessName() + "_" + std::to_string(getpid()) + ".log";
Game::logger->Log("Diagnostics", "backtrace is enabled, crash dump located at %s", fileName.c_str()); LOG("backtrace is enabled, crash dump located at %s", fileName.c_str());
FILE* file = fopen(fileName.c_str(), "w+"); FILE* file = fopen(fileName.c_str(), "w+");
if (file != nullptr) { if (file != nullptr) {
backtrace_print(state, 2, file); backtrace_print(state, 2, file);
@@ -107,7 +107,7 @@ static void ErrorCallback(void* data, const char* msg, int errnum) {
} }
#endif #endif
#include "Type.h" #include "Demangler.h"
void GenerateDump() { void GenerateDump() {
std::string cmd = "sudo gcore " + std::to_string(getpid()); std::string cmd = "sudo gcore " + std::to_string(getpid());
@@ -118,55 +118,56 @@ void CatchUnhandled(int sig) {
#ifndef __include_backtrace__ #ifndef __include_backtrace__
std::string fileName = Diagnostics::GetOutDirectory() + "crash_" + Diagnostics::GetProcessName() + "_" + std::to_string(getpid()) + ".log"; std::string fileName = Diagnostics::GetOutDirectory() + "crash_" + Diagnostics::GetProcessName() + "_" + std::to_string(getpid()) + ".log";
Game::logger->Log("Diagnostics", "Encountered signal %i, creating crash dump %s", sig, fileName.c_str()); LOG("Encountered signal %i, creating crash dump %s", sig, fileName.c_str());
if (Diagnostics::GetProduceMemoryDump()) { if (Diagnostics::GetProduceMemoryDump()) {
GenerateDump(); GenerateDump();
} }
constexpr uint8_t MaxStackTrace = 32;
void* array[10]; void* array[MaxStackTrace];
size_t size; size_t size;
// get void*'s for all entries on the stack // get void*'s for all entries on the stack
size = backtrace(array, 10); size = backtrace(array, MaxStackTrace);
#if defined(__GNUG__) and defined(__dynamic) # if defined(__GNUG__)
// Loop through the returned addresses, and get the symbols to be demangled // Loop through the returned addresses, and get the symbols to be demangled
char** strings = backtrace_symbols(array, size); char** strings = backtrace_symbols(array, size);
FILE* file = fopen(fileName.c_str(), "w+");
if (file != NULL) {
fprintf(file, "Error: signal %d:\n", sig);
}
// Print the stack trace // Print the stack trace
for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) {
// Take a string like './WorldServer(_ZN19SlashCommandHandler17HandleChatCommandERKSbIDsSt11char_traitsIDsESaIDsEEP6EntityRK13SystemAddress+0x6187) [0x55869c44ecf7]' and extract the function name // Take a string like './WorldServer(_ZN19SlashCommandHandler17HandleChatCommandERKSbIDsSt11char_traitsIDsESaIDsEEP6EntityRK13SystemAddress+0x6187) [0x55869c44ecf7]'
// and extract '_ZN19SlashCommandHandler17HandleChatCommandERKSbIDsSt11char_traitsIDsESaIDsEEP6EntityRK13SystemAddress' from it to be demangled into a proper name
std::string functionName = strings[i]; std::string functionName = strings[i];
std::string::size_type start = functionName.find('('); std::string::size_type start = functionName.find('(');
std::string::size_type end = functionName.find('+'); std::string::size_type end = functionName.find('+');
if (start != std::string::npos && end != std::string::npos) { if (start != std::string::npos && end != std::string::npos) {
std::string demangled = functionName.substr(start + 1, end - start - 1); std::string demangled = functionName.substr(start + 1, end - start - 1);
demangled = demangle(functionName.c_str()); demangled = Demangler::Demangle(demangled.c_str());
if (demangled.empty()) { // If the demangled string is not empty, then we can replace the mangled string with the demangled one
Game::logger->Log("Diagnostics", "[%02zu] %s", i, demangled.c_str()); if (!demangled.empty()) {
} else { demangled.push_back('(');
Game::logger->Log("Diagnostics", "[%02zu] %s", i, functionName.c_str()); demangled += functionName.substr(end);
} functionName = demangled;
} else {
Game::logger->Log("Diagnostics", "[%02zu] %s", i, functionName.c_str());
} }
} }
#else
backtrace_symbols_fd(array, size, STDOUT_FILENO);
#endif
FILE* file = fopen(fileName.c_str(), "w+"); LOG("[%02zu] %s", i, functionName.c_str());
if (file != NULL) { if (file != NULL) {
// print out all the frames to stderr fprintf(file, "[%02zu] %s\n", i, functionName.c_str());
fprintf(file, "Error: signal %d:\n", sig);
backtrace_symbols_fd(array, size, fileno(file));
fclose(file);
} }
}
# else // defined(__GNUG__)
backtrace_symbols_fd(array, size, STDOUT_FILENO);
# endif // defined(__GNUG__)
#else #else // __include_backtrace__
struct backtrace_state* state = backtrace_create_state( struct backtrace_state* state = backtrace_create_state(
Diagnostics::GetProcessFileName().c_str(), Diagnostics::GetProcessFileName().c_str(),
@@ -177,7 +178,7 @@ void CatchUnhandled(int sig) {
struct bt_ctx ctx = { state, 0 }; struct bt_ctx ctx = { state, 0 };
Bt(state); Bt(state);
#endif #endif // __include_backtrace__
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }

View File

@@ -9,7 +9,7 @@
#include "CDClientDatabase.h" #include "CDClientDatabase.h"
#include "GeneralUtils.h" #include "GeneralUtils.h"
#include "Game.h" #include "Game.h"
#include "dLogger.h" #include "Logger.h"
#include "AssetManager.h" #include "AssetManager.h"
#include "eSqliteDataType.h" #include "eSqliteDataType.h"
@@ -44,7 +44,7 @@ bool FdbToSqlite::Convert::ConvertDatabase(AssetMemoryBuffer& buffer) {
CDClientDatabase::ExecuteQuery("COMMIT;"); CDClientDatabase::ExecuteQuery("COMMIT;");
} catch (CppSQLite3Exception& e) { } catch (CppSQLite3Exception& e) {
Game::logger->Log("FdbToSqlite", "Encountered error %s converting FDB to SQLite", e.errorMessage()); LOG("Encountered error %s converting FDB to SQLite", e.errorMessage());
return false; return false;
} }

View File

@@ -3,16 +3,18 @@
#include <random> #include <random>
class dServer; class dServer;
class dLogger; class Logger;
class InstanceManager; class InstanceManager;
class dChatFilter; class dChatFilter;
class dConfig; class dConfig;
class RakPeerInterface; class RakPeerInterface;
class AssetManager; class AssetManager;
struct SystemAddress; struct SystemAddress;
class EntityManager;
class dZoneManager;
namespace Game { namespace Game {
extern dLogger* logger; extern Logger* logger;
extern dServer* server; extern dServer* server;
extern InstanceManager* im; extern InstanceManager* im;
extern dChatFilter* chatFilter; extern dChatFilter* chatFilter;
@@ -22,4 +24,6 @@ namespace Game {
extern AssetManager* assetManager; extern AssetManager* assetManager;
extern SystemAddress chatSysAddr; extern SystemAddress chatSysAddr;
extern bool shouldShutdown; extern bool shouldShutdown;
extern EntityManager* entityManager;
extern dZoneManager* zoneManager;
} }

View File

@@ -13,7 +13,7 @@
#include "NiPoint3.h" #include "NiPoint3.h"
#include "Game.h" #include "Game.h"
#include "dLogger.h" #include "Logger.h"
enum eInventoryType : uint32_t; enum eInventoryType : uint32_t;
enum class eObjectBits : size_t; enum class eObjectBits : size_t;
@@ -111,29 +111,6 @@ namespace GeneralUtils {
*/ */
bool CheckBit(int64_t value, uint32_t index); bool CheckBit(int64_t value, uint32_t index);
// MARK: Random Number Generation
//! Generates a random number
/*!
\param min The minimum the generate from
\param max The maximum to generate to
*/
template <typename T>
inline T GenerateRandomNumber(std::size_t min, std::size_t max) {
// Make sure it is a numeric type
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
if constexpr (std::is_integral_v<T>) { // constexpr only necessary on first statement
std::uniform_int_distribution<T> distribution(min, max);
return distribution(Game::randomEngine);
} else if (std::is_floating_point_v<T>) {
std::uniform_real_distribution<T> distribution(min, max);
return distribution(Game::randomEngine);
}
return T();
}
bool ReplaceInString(std::string& str, const std::string& from, const std::string& to); bool ReplaceInString(std::string& str, const std::string& from, const std::string& to);
std::u16string ReadWString(RakNet::BitStream* inStream); std::u16string ReadWString(RakNet::BitStream* inStream);
@@ -149,6 +126,11 @@ namespace GeneralUtils {
template <typename T> template <typename T>
T Parse(const char* value); T Parse(const char* value);
template <>
inline bool Parse(const char* value) {
return std::stoi(value);
}
template <> template <>
inline int32_t Parse(const char* value) { inline int32_t Parse(const char* value) {
return std::stoi(value); return std::stoi(value);
@@ -223,4 +205,42 @@ namespace GeneralUtils {
std::hash<T> h; std::hash<T> h;
s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2); s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2);
} }
// MARK: Random Number Generation
//! Generates a random number
/*!
\param min The minimum the generate from
\param max The maximum to generate to
*/
template <typename T>
inline T GenerateRandomNumber(std::size_t min, std::size_t max) {
// Make sure it is a numeric type
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
if constexpr (std::is_integral_v<T>) { // constexpr only necessary on first statement
std::uniform_int_distribution<T> distribution(min, max);
return distribution(Game::randomEngine);
} else if (std::is_floating_point_v<T>) {
std::uniform_real_distribution<T> distribution(min, max);
return distribution(Game::randomEngine);
}
return T();
}
// on Windows we need to undef these or else they conflict with our numeric limits calls
// DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS
#ifdef _WIN32
#undef min
#undef max
#endif
template <typename T>
inline T GenerateRandomNumber() {
// Make sure it is a numeric type
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
return GenerateRandomNumber<T>(std::numeric_limits<T>::min(), std::numeric_limits<T>::max());
}
} }

View File

@@ -4,7 +4,7 @@
#include "GeneralUtils.h" #include "GeneralUtils.h"
#include "Game.h" #include "Game.h"
#include "dLogger.h" #include "Logger.h"
// C++ // C++
#include <string_view> #include <string_view>
@@ -48,7 +48,7 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
try { try {
type = static_cast<eLDFType>(strtol(ldfTypeAndValue.first.data(), &storage, 10)); type = static_cast<eLDFType>(strtol(ldfTypeAndValue.first.data(), &storage, 10));
} catch (std::exception) { } catch (std::exception) {
Game::logger->Log("LDFFormat", "Attempted to process invalid ldf type (%s) from string (%s)", ldfTypeAndValue.first.data(), format.data()); LOG("Attempted to process invalid ldf type (%s) from string (%s)", ldfTypeAndValue.first.data(), format.data());
return nullptr; return nullptr;
} }
@@ -61,35 +61,33 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
} }
case LDF_TYPE_S32: { case LDF_TYPE_S32: {
try { int32_t data;
int32_t data = static_cast<int32_t>(strtoul(ldfTypeAndValue.second.data(), &storage, 10)); if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
returnValue = new LDFData<int32_t>(key, data); LOG("Warning: Attempted to process invalid int32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
} catch (std::exception) {
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid int32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
returnValue = new LDFData<int32_t>(key, data);
break; break;
} }
case LDF_TYPE_FLOAT: { case LDF_TYPE_FLOAT: {
try { float data;
float data = strtof(ldfTypeAndValue.second.data(), &storage); if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
returnValue = new LDFData<float>(key, data); LOG("Warning: Attempted to process invalid float value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
} catch (std::exception) {
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid float value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
returnValue = new LDFData<float>(key, data);
break; break;
} }
case LDF_TYPE_DOUBLE: { case LDF_TYPE_DOUBLE: {
try { double data;
double data = strtod(ldfTypeAndValue.second.data(), &storage); if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
returnValue = new LDFData<double>(key, data); LOG("Warning: Attempted to process invalid double value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
} catch (std::exception) {
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid double value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
returnValue = new LDFData<double>(key, data);
break; break;
} }
@@ -102,10 +100,8 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
} else if (ldfTypeAndValue.second == "false") { } else if (ldfTypeAndValue.second == "false") {
data = 0; data = 0;
} else { } else {
try { if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
data = static_cast<uint32_t>(strtoul(ldfTypeAndValue.second.data(), &storage, 10)); LOG("Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
} catch (std::exception) {
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
} }
@@ -122,10 +118,8 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
} else if (ldfTypeAndValue.second == "false") { } else if (ldfTypeAndValue.second == "false") {
data = false; data = false;
} else { } else {
try { if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
data = static_cast<bool>(strtol(ldfTypeAndValue.second.data(), &storage, 10)); LOG("Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
} catch (std::exception) {
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
} }
@@ -135,24 +129,22 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
} }
case LDF_TYPE_U64: { case LDF_TYPE_U64: {
try { uint64_t data;
uint64_t data = static_cast<uint64_t>(strtoull(ldfTypeAndValue.second.data(), &storage, 10)); if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
returnValue = new LDFData<uint64_t>(key, data); LOG("Warning: Attempted to process invalid uint64 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
} catch (std::exception) {
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid uint64 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
returnValue = new LDFData<uint64_t>(key, data);
break; break;
} }
case LDF_TYPE_OBJID: { case LDF_TYPE_OBJID: {
try { LWOOBJID data;
LWOOBJID data = static_cast<LWOOBJID>(strtoll(ldfTypeAndValue.second.data(), &storage, 10)); if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
returnValue = new LDFData<LWOOBJID>(key, data); LOG("Warning: Attempted to process invalid LWOOBJID value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
} catch (std::exception) {
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid LWOOBJID value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
returnValue = new LDFData<LWOOBJID>(key, data);
break; break;
} }
@@ -163,12 +155,12 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
} }
case LDF_TYPE_UNKNOWN: { case LDF_TYPE_UNKNOWN: {
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid unknown value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); LOG("Warning: Attempted to process invalid unknown value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
break; break;
} }
default: { default: {
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid LDF type (%d) from string (%s)", type, format.data()); LOG("Warning: Attempted to process invalid LDF type (%d) from string (%s)", type, format.data());
break; break;
} }
} }

96
dCommon/Logger.cpp Normal file
View File

@@ -0,0 +1,96 @@
#include "Logger.h"
#include <algorithm>
#include <ctime>
#include <filesystem>
#include <stdarg.h>
Writer::~Writer() {
// Dont try to close stdcout...
if (!m_Outfile || m_IsConsoleWriter) return;
fclose(m_Outfile);
m_Outfile = NULL;
}
void Writer::Log(const char* time, const char* message) {
if (!m_Outfile) return;
fputs(time, m_Outfile);
fputs(message, m_Outfile);
}
void Writer::Flush() {
if (!m_Outfile) return;
fflush(m_Outfile);
}
FileWriter::FileWriter(const char* outpath) {
m_Outfile = fopen(outpath, "wt");
if (!m_Outfile) printf("Couldn't open %s for writing!\n", outpath);
m_Outpath = outpath;
m_IsConsoleWriter = false;
}
ConsoleWriter::ConsoleWriter(bool enabled) {
m_Enabled = enabled;
m_Outfile = stdout;
m_IsConsoleWriter = true;
}
Logger::Logger(const std::string& outpath, bool logToConsole, bool logDebugStatements) {
m_logDebugStatements = logDebugStatements;
std::filesystem::path outpathPath(outpath);
if (!std::filesystem::exists(outpathPath.parent_path())) std::filesystem::create_directories(outpathPath.parent_path());
m_Writers.push_back(std::make_unique<FileWriter>(outpath));
m_Writers.push_back(std::make_unique<ConsoleWriter>(logToConsole));
}
void Logger::vLog(const char* format, va_list args) {
time_t t = time(NULL);
struct tm* time = localtime(&t);
char timeStr[70];
strftime(timeStr, sizeof(timeStr), "[%d-%m-%y %H:%M:%S ", time);
char message[2048];
vsnprintf(message, 2048, format, args);
for (const auto& writer : m_Writers) {
writer->Log(timeStr, message);
}
}
void Logger::Log(const char* className, const char* format, ...) {
va_list args;
std::string log = std::string(className) + "] " + std::string(format) + "\n";
va_start(args, format);
vLog(log.c_str(), args);
va_end(args);
}
void Logger::LogDebug(const char* className, const char* format, ...) {
if (!m_logDebugStatements) return;
va_list args;
std::string log = std::string(className) + "] " + std::string(format) + "\n";
va_start(args, format);
vLog(log.c_str(), args);
va_end(args);
}
void Logger::Flush() {
for (const auto& writer : m_Writers) {
writer->Flush();
}
}
void Logger::SetLogToConsole(bool logToConsole) {
for (const auto& writer : m_Writers) {
if (writer->IsConsoleWriter()) writer->SetEnabled(logToConsole);
}
}
bool Logger::GetLogToConsole() const {
bool toReturn = false;
for (const auto& writer : m_Writers) {
if (writer->IsConsoleWriter()) toReturn |= writer->GetEnabled();
}
return toReturn;
}

89
dCommon/Logger.h Normal file
View File

@@ -0,0 +1,89 @@
#pragma once
#include <memory>
#include <string>
#include <vector>
#define STRINGIFY_IMPL(x) #x
#define STRINGIFY(x) STRINGIFY_IMPL(x)
#define GET_FILE_NAME(x, y) GetFileNameFromAbsolutePath(__FILE__ x y)
#define FILENAME_AND_LINE GET_FILE_NAME(":", STRINGIFY(__LINE__))
// Calculate the filename at compile time from the path.
// We just do this by scanning the path for the last '/' or '\' character and returning the string after it.
constexpr const char* GetFileNameFromAbsolutePath(const char* path) {
const char* file = path;
while (*path) {
char nextChar = *path++;
if (nextChar == '/' || nextChar == '\\') {
file = path;
}
}
return file;
}
// These have to have a constexpr variable to store the filename_and_line result in a local variable otherwise
// they will not be valid constexpr and will be evaluated at runtime instead of compile time!
// The full string is still stored in the binary, however the offset of the filename in the absolute paths
// is used in the instruction instead of the start of the absolute path.
#define LOG(message, ...) do { auto str = FILENAME_AND_LINE; Game::logger->Log(str, message, ##__VA_ARGS__); } while(0)
#define LOG_DEBUG(message, ...) do { auto str = FILENAME_AND_LINE; Game::logger->LogDebug(str, message, ##__VA_ARGS__); } while(0)
// Writer class for writing data to files.
class Writer {
public:
Writer(bool enabled = true) : m_Enabled(enabled) {};
virtual ~Writer();
virtual void Log(const char* time, const char* message);
virtual void Flush();
void SetEnabled(bool disabled) { m_Enabled = disabled; }
bool GetEnabled() const { return m_Enabled; }
bool IsConsoleWriter() { return m_IsConsoleWriter; }
public:
bool m_Enabled = true;
bool m_IsConsoleWriter = false;
FILE* m_Outfile;
};
// FileWriter class for writing data to a file on a disk.
class FileWriter : public Writer {
public:
FileWriter(const char* outpath);
FileWriter(const std::string& outpath) : FileWriter(outpath.c_str()) {};
private:
std::string m_Outpath;
};
// ConsoleWriter class for writing data to the console.
class ConsoleWriter : public Writer {
public:
ConsoleWriter(bool enabled);
};
class Logger {
public:
Logger() = delete;
Logger(const std::string& outpath, bool logToConsole, bool logDebugStatements);
void Log(const char* filenameAndLine, const char* format, ...);
void LogDebug(const char* filenameAndLine, const char* format, ...);
void Flush();
bool GetLogToConsole() const;
void SetLogToConsole(bool logToConsole);
void SetLogDebugStatements(bool logDebugStatements) { m_logDebugStatements = logDebugStatements; }
private:
void vLog(const char* format, va_list args);
bool m_logDebugStatements;
std::vector<std::unique_ptr<Writer>> m_Writers;
};

View File

@@ -129,10 +129,19 @@ NiPoint3 NiPoint3::operator+(const NiPoint3& point) const {
} }
//! Operator for addition of vectors //! Operator for addition of vectors
NiPoint3 NiPoint3::operator+=(const NiPoint3& point) const { NiPoint3& NiPoint3::operator+=(const NiPoint3& point) {
return NiPoint3(this->x + point.x, this->y + point.y, this->z + point.z); this->x += point.x;
this->y += point.y;
this->z += point.z;
return *this;
} }
NiPoint3& NiPoint3::operator*=(const float scalar) {
this->x *= scalar;
this->y *= scalar;
this->z *= scalar;
return *this;
}
//! Operator for subtraction of vectors //! Operator for subtraction of vectors
NiPoint3 NiPoint3::operator-(const NiPoint3& point) const { NiPoint3 NiPoint3::operator-(const NiPoint3& point) const {

View File

@@ -136,7 +136,9 @@ public:
NiPoint3 operator+(const NiPoint3& point) const; NiPoint3 operator+(const NiPoint3& point) const;
//! Operator for addition of vectors //! Operator for addition of vectors
NiPoint3 operator+=(const NiPoint3& point) const; NiPoint3& operator+=(const NiPoint3& point);
NiPoint3& operator*=(const float scalar);
//! Operator for subtraction of vectors //! Operator for subtraction of vectors
NiPoint3 operator-(const NiPoint3& point) const; NiPoint3 operator-(const NiPoint3& point) const;

View File

@@ -1,27 +0,0 @@
#include "Type.h"
#ifdef __GNUG__
#include <cstdlib>
#include <memory>
#include <cxxabi.h>
std::string demangle(const char* name) {
int status = -4; // some arbitrary value to eliminate the compiler warning
// enable c++11 by passing the flag -std=c++11 to g++
std::unique_ptr<char, void(*)(void*)> res{
abi::__cxa_demangle(name, NULL, NULL, &status),
std::free
};
return (status == 0) ? res.get() : name;
}
#else
// does nothing if not g++
std::string demangle(const char* name) {
return name;
}
#endif

View File

@@ -1,12 +0,0 @@
#pragma once
#include <string>
#include <typeinfo>
std::string demangle(const char* name);
template <class T>
std::string type(const T& t) {
return demangle(typeid(t).name());
}

View File

@@ -2,7 +2,7 @@
#include "AssetManager.h" #include "AssetManager.h"
#include "Game.h" #include "Game.h"
#include "dLogger.h" #include "Logger.h"
#include <zlib.h> #include <zlib.h>

View File

@@ -42,7 +42,7 @@ struct AssetMemoryBuffer : std::streambuf {
} }
void close() { void close() {
delete m_Base; free(m_Base);
} }
}; };

View File

@@ -3,6 +3,7 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include <filesystem> #include <filesystem>
#include <fstream>
#pragma pack(push, 1) #pragma pack(push, 1)
struct PackRecord { struct PackRecord {

View File

@@ -1,7 +1,7 @@
#include "PackIndex.h" #include "PackIndex.h"
#include "BinaryIO.h" #include "BinaryIO.h"
#include "Game.h" #include "Game.h"
#include "dLogger.h" #include "Logger.h"
PackIndex::PackIndex(const std::filesystem::path& filePath) { PackIndex::PackIndex(const std::filesystem::path& filePath) {
m_FileStream = std::ifstream(filePath / "versions" / "primary.pki", std::ios::in | std::ios::binary); m_FileStream = std::ifstream(filePath / "versions" / "primary.pki", std::ios::in | std::ios::binary);
@@ -34,7 +34,7 @@ PackIndex::PackIndex(const std::filesystem::path& filePath) {
m_PackFileIndices.push_back(packFileIndex); m_PackFileIndices.push_back(packFileIndex);
} }
Game::logger->Log("PackIndex", "Loaded pack catalog with %i pack files and %i files", m_PackPaths.size(), m_PackFileIndices.size()); LOG("Loaded pack catalog with %i pack files and %i files", m_PackPaths.size(), m_PackFileIndices.size());
for (auto& item : m_PackPaths) { for (auto& item : m_PackPaths) {
std::replace(item.begin(), item.end(), '\\', '/'); std::replace(item.begin(), item.end(), '\\', '/');

View File

@@ -9,6 +9,7 @@
#include "BitStream.h" #include "BitStream.h"
#include "eConnectionType.h" #include "eConnectionType.h"
#include "eClientMessageType.h" #include "eClientMessageType.h"
#include "BitStreamUtils.h"
#pragma warning (disable:4251) //Disables SQL warnings #pragma warning (disable:4251) //Disables SQL warnings
@@ -32,7 +33,7 @@ constexpr uint32_t lowFrameDelta = FRAMES_TO_MS(lowFramerate);
#define CBITSTREAM RakNet::BitStream bitStream; #define CBITSTREAM RakNet::BitStream bitStream;
#define CINSTREAM RakNet::BitStream inStream(packet->data, packet->length, false); #define CINSTREAM RakNet::BitStream inStream(packet->data, packet->length, false);
#define CINSTREAM_SKIP_HEADER CINSTREAM if (inStream.GetNumberOfUnreadBits() >= BYTES_TO_BITS(HEADER_SIZE)) inStream.IgnoreBytes(HEADER_SIZE); else inStream.IgnoreBits(inStream.GetNumberOfUnreadBits()); #define CINSTREAM_SKIP_HEADER CINSTREAM if (inStream.GetNumberOfUnreadBits() >= BYTES_TO_BITS(HEADER_SIZE)) inStream.IgnoreBytes(HEADER_SIZE); else inStream.IgnoreBits(inStream.GetNumberOfUnreadBits());
#define CMSGHEADER PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GAME_MSG); #define CMSGHEADER BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GAME_MSG);
#define SEND_PACKET Game::server->Send(&bitStream, sysAddr, false); #define SEND_PACKET Game::server->Send(&bitStream, sysAddr, false);
#define SEND_PACKET_BROADCAST Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true); #define SEND_PACKET_BROADCAST Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);

File diff suppressed because it is too large Load Diff

View File

@@ -27,20 +27,6 @@ enum class ePermissionMap : uint64_t {
* The character has restricted chat access, bit 6. * The character has restricted chat access, bit 6.
*/ */
RestrictedChatAccess = 0x1 << 6, RestrictedChatAccess = 0x1 << 6,
//
// Combined permissions
//
/**
* The character is marked as 'old', restricted from trade and mail.
*/
Old = RestrictedTradeAccess | RestrictedMailAccess,
/**
* The character is soft banned, restricted from trade, mail, and chat.
*/
SoftBanned = RestrictedTradeAccess | RestrictedMailAccess | RestrictedChatAccess,
}; };
#endif //!__EPERMISSIONMAP__H__ #endif //!__EPERMISSIONMAP__H__

View File

@@ -101,7 +101,7 @@ enum class eReplicaComponentType : uint32_t {
TRADE, TRADE,
USER_CONTROL, USER_CONTROL,
IGNORE_LIST, IGNORE_LIST,
ROCKET_LAUNCH_LUP, MULTI_ZONE_ENTRANCE,
BUFF_REAL, // the real buff component, should just be name BUFF BUFF_REAL, // the real buff component, should just be name BUFF
INTERACTION_MANAGER, INTERACTION_MANAGER,
DONATION_VENDOR, DONATION_VENDOR,

View File

@@ -1,110 +0,0 @@
#include "dLogger.h"
dLogger::dLogger(const std::string& outpath, bool logToConsole, bool logDebugStatements) {
m_logToConsole = logToConsole;
m_logDebugStatements = logDebugStatements;
m_outpath = outpath;
#ifdef _WIN32
mFile = std::ofstream(m_outpath);
if (!mFile) { printf("Couldn't open %s for writing!\n", outpath.c_str()); }
#else
fp = fopen(outpath.c_str(), "wt");
if (fp == NULL) { printf("Couldn't open %s for writing!\n", outpath.c_str()); }
#endif
}
dLogger::~dLogger() {
#ifdef _WIN32
mFile.close();
#else
if (fp != nullptr) {
fclose(fp);
fp = nullptr;
}
#endif
}
void dLogger::vLog(const char* format, va_list args) {
#ifdef _WIN32
time_t t = time(NULL);
struct tm time;
localtime_s(&time, &t);
char timeStr[70];
strftime(timeStr, sizeof(timeStr), "%d-%m-%y %H:%M:%S", &time);
char message[2048];
vsnprintf(message, 2048, format, args);
if (m_logToConsole) std::cout << "[" << timeStr << "] " << message;
mFile << "[" << timeStr << "] " << message;
#else
time_t t = time(NULL);
struct tm* time = localtime(&t);
char timeStr[70];
strftime(timeStr, sizeof(timeStr), "%d-%m-%y %H:%M:%S", time);
char message[2048];
vsnprintf(message, 2048, format, args);
if (m_logToConsole) {
fputs("[", stdout);
fputs(timeStr, stdout);
fputs("] ", stdout);
fputs(message, stdout);
}
if (fp != nullptr) {
fputs("[", fp);
fputs(timeStr, fp);
fputs("] ", fp);
fputs(message, fp);
} else {
printf("Logger not initialized!\n");
}
#endif
}
void dLogger::LogBasic(const char* format, ...) {
va_list args;
va_start(args, format);
vLog(format, args);
va_end(args);
}
void dLogger::LogBasic(const std::string& message) {
LogBasic(message.c_str());
}
void dLogger::Log(const char* className, const char* format, ...) {
va_list args;
std::string log = "[" + std::string(className) + "] " + std::string(format) + "\n";
va_start(args, format);
vLog(log.c_str(), args);
va_end(args);
}
void dLogger::Log(const std::string& className, const std::string& message) {
Log(className.c_str(), message.c_str());
}
void dLogger::LogDebug(const char* className, const char* format, ...) {
if (!m_logDebugStatements) return;
va_list args;
std::string log = "[" + std::string(className) + "] " + std::string(format) + "\n";
va_start(args, format);
vLog(log.c_str(), args);
va_end(args);
}
void dLogger::LogDebug(const std::string& className, const std::string& message) {
LogDebug(className.c_str(), message.c_str());
}
void dLogger::Flush() {
#ifdef _WIN32
mFile.flush();
#else
if (fp != nullptr) {
std::fflush(fp);
}
#endif
}

View File

@@ -1,38 +0,0 @@
#pragma once
#include <ctime>
#include <cstdarg>
#include <string>
#include <fstream>
#include <iostream>
class dLogger {
public:
dLogger(const std::string& outpath, bool logToConsole, bool logDebugStatements);
~dLogger();
void SetLogToConsole(bool logToConsole) { m_logToConsole = logToConsole; }
void SetLogDebugStatements(bool logDebugStatements) { m_logDebugStatements = logDebugStatements; }
void vLog(const char* format, va_list args);
void LogBasic(const std::string& message);
void LogBasic(const char* format, ...);
void Log(const char* className, const char* format, ...);
void Log(const std::string& className, const std::string& message);
void LogDebug(const std::string& className, const std::string& message);
void LogDebug(const char* className, const char* format, ...);
void Flush();
const bool GetIsLoggingToConsole() const { return m_logToConsole; }
private:
bool m_logDebugStatements;
bool m_logToConsole;
std::string m_outpath;
std::ofstream mFile;
#ifndef _WIN32
//Glorious linux can run with SPEED:
FILE* fp = nullptr;
#endif
};

View File

@@ -13,15 +13,7 @@
#include <sstream> #include <sstream>
#include <iostream> #include <iostream>
// Enable this to cache all entries in each table for fast access, comes with more memory cost //! The CDClient Database namespace
//#define CDCLIENT_CACHE_ALL
/*!
\file CDClientDatabase.hpp
\brief An interface between the CDClient.sqlite file and the server
*/
//! The CDClient Database namespace
namespace CDClientDatabase { namespace CDClientDatabase {
//! Opens a connection with the CDClient //! Opens a connection with the CDClient

View File

@@ -38,43 +38,53 @@
#include "CDFeatureGatingTable.h" #include "CDFeatureGatingTable.h"
#include "CDRailActivatorComponent.h" #include "CDRailActivatorComponent.h"
// Uncomment this to cache the full cdclient database into memory. This will make the server load faster, but will use more memory.
// A vanilla CDClient takes about 46MB of memory + the regular world data.
// #define CDCLIENT_CACHE_ALL
#ifdef CDCLIENT_CACHE_ALL
#define CDCLIENT_DONT_CACHE_TABLE(x) x
#else
#define CDCLIENT_DONT_CACHE_TABLE(x)
#endif
CDClientManager::CDClientManager() { CDClientManager::CDClientManager() {
CDActivityRewardsTable::Instance(); CDActivityRewardsTable::Instance().LoadValuesFromDatabase();
CDAnimationsTable::Instance(); CDActivitiesTable::Instance().LoadValuesFromDatabase();
CDBehaviorParameterTable::Instance(); CDCLIENT_DONT_CACHE_TABLE(CDAnimationsTable::Instance().LoadValuesFromDatabase());
CDBehaviorTemplateTable::Instance(); CDBehaviorParameterTable::Instance().LoadValuesFromDatabase();
CDComponentsRegistryTable::Instance(); CDBehaviorTemplateTable::Instance().LoadValuesFromDatabase();
CDCurrencyTableTable::Instance(); CDBrickIDTableTable::Instance().LoadValuesFromDatabase();
CDDestructibleComponentTable::Instance(); CDCLIENT_DONT_CACHE_TABLE(CDComponentsRegistryTable::Instance().LoadValuesFromDatabase());
CDEmoteTableTable::Instance(); CDCurrencyTableTable::Instance().LoadValuesFromDatabase();
CDInventoryComponentTable::Instance(); CDDestructibleComponentTable::Instance().LoadValuesFromDatabase();
CDItemComponentTable::Instance(); CDEmoteTableTable::Instance().LoadValuesFromDatabase();
CDItemSetsTable::Instance(); CDFeatureGatingTable::Instance().LoadValuesFromDatabase();
CDItemSetSkillsTable::Instance(); CDInventoryComponentTable::Instance().LoadValuesFromDatabase();
CDLevelProgressionLookupTable::Instance(); CDCLIENT_DONT_CACHE_TABLE(CDItemComponentTable::Instance().LoadValuesFromDatabase());
CDLootMatrixTable::Instance(); CDItemSetSkillsTable::Instance().LoadValuesFromDatabase();
CDLootTableTable::Instance(); CDItemSetsTable::Instance().LoadValuesFromDatabase();
CDMissionNPCComponentTable::Instance(); CDLevelProgressionLookupTable::Instance().LoadValuesFromDatabase();
CDMissionTasksTable::Instance(); CDCLIENT_DONT_CACHE_TABLE(CDLootMatrixTable::Instance().LoadValuesFromDatabase());
CDMissionsTable::Instance(); CDCLIENT_DONT_CACHE_TABLE(CDLootTableTable::Instance().LoadValuesFromDatabase());
CDObjectSkillsTable::Instance(); CDMissionEmailTable::Instance().LoadValuesFromDatabase();
CDObjectsTable::Instance(); CDMissionNPCComponentTable::Instance().LoadValuesFromDatabase();
CDPhysicsComponentTable::Instance(); CDMissionTasksTable::Instance().LoadValuesFromDatabase();
CDRebuildComponentTable::Instance(); CDMissionsTable::Instance().LoadValuesFromDatabase();
CDScriptComponentTable::Instance(); CDMovementAIComponentTable::Instance().LoadValuesFromDatabase();
CDSkillBehaviorTable::Instance(); CDObjectSkillsTable::Instance().LoadValuesFromDatabase();
CDZoneTableTable::Instance(); CDCLIENT_DONT_CACHE_TABLE(CDObjectsTable::Instance().LoadValuesFromDatabase());
CDVendorComponentTable::Instance(); CDPhysicsComponentTable::Instance().LoadValuesFromDatabase();
CDActivitiesTable::Instance(); CDPackageComponentTable::Instance().LoadValuesFromDatabase();
CDPackageComponentTable::Instance(); CDProximityMonitorComponentTable::Instance().LoadValuesFromDatabase();
CDProximityMonitorComponentTable::Instance(); CDPropertyEntranceComponentTable::Instance().LoadValuesFromDatabase();
CDMovementAIComponentTable::Instance(); CDPropertyTemplateTable::Instance().LoadValuesFromDatabase();
CDBrickIDTableTable::Instance(); CDRailActivatorComponentTable::Instance().LoadValuesFromDatabase();
CDRarityTableTable::Instance(); CDRarityTableTable::Instance().LoadValuesFromDatabase();
CDMissionEmailTable::Instance(); CDRebuildComponentTable::Instance().LoadValuesFromDatabase();
CDRewardsTable::Instance(); CDRewardsTable::Instance().LoadValuesFromDatabase();
CDPropertyEntranceComponentTable::Instance(); CDScriptComponentTable::Instance().LoadValuesFromDatabase();
CDPropertyTemplateTable::Instance(); CDSkillBehaviorTable::Instance().LoadValuesFromDatabase();
CDFeatureGatingTable::Instance(); CDVendorComponentTable::Instance().LoadValuesFromDatabase();
CDRailActivatorComponentTable::Instance(); CDZoneTableTable::Instance().LoadValuesFromDatabase();
} }

View File

@@ -1,7 +1,7 @@
#include "Database.h" #include "Database.h"
#include "Game.h" #include "Game.h"
#include "dConfig.h" #include "dConfig.h"
#include "dLogger.h" #include "Logger.h"
using namespace std; using namespace std;
#pragma warning (disable:4251) //Disables SQL warnings #pragma warning (disable:4251) //Disables SQL warnings
@@ -64,8 +64,8 @@ void Database::Destroy(std::string source, bool log) {
if (!con) return; if (!con) return;
if (log) { if (log) {
if (source != "") Game::logger->Log("Database", "Destroying MySQL connection from %s!", source.c_str()); if (source != "") LOG("Destroying MySQL connection from %s!", source.c_str());
else Game::logger->Log("Database", "Destroying MySQL connection!"); else LOG("Destroying MySQL connection!");
} }
con->close(); con->close();
@@ -84,7 +84,7 @@ sql::PreparedStatement* Database::CreatePreppedStmt(const std::string& query) {
if (!con) { if (!con) {
Connect(); Connect();
Game::logger->Log("Database", "Trying to reconnect to MySQL"); LOG("Trying to reconnect to MySQL");
} }
if (!con->isValid() || con->isClosed()) { if (!con->isValid() || con->isClosed()) {
@@ -93,7 +93,7 @@ sql::PreparedStatement* Database::CreatePreppedStmt(const std::string& query) {
con = nullptr; con = nullptr;
Connect(); Connect();
Game::logger->Log("Database", "Trying to reconnect to MySQL from invalid or closed connection"); LOG("Trying to reconnect to MySQL from invalid or closed connection");
} }
auto* stmt = con->prepareStatement(str); auto* stmt = con->prepareStatement(str);

View File

@@ -5,10 +5,10 @@
#include "Database.h" #include "Database.h"
#include "Game.h" #include "Game.h"
#include "GeneralUtils.h" #include "GeneralUtils.h"
#include "dLogger.h" #include "Logger.h"
#include "BinaryPathFinder.h" #include "BinaryPathFinder.h"
#include <istream> #include <fstream>
Migration LoadMigration(std::string path) { Migration LoadMigration(std::string path) {
Migration migration{}; Migration migration{};
@@ -53,7 +53,7 @@ void MigrationRunner::RunMigrations() {
delete stmt; delete stmt;
if (doExit) continue; if (doExit) continue;
Game::logger->Log("MigrationRunner", "Running migration: %s", migration.name.c_str()); LOG("Running migration: %s", migration.name.c_str());
if (migration.name == "dlu/5_brick_model_sd0.sql") { if (migration.name == "dlu/5_brick_model_sd0.sql") {
runSd0Migrations = true; runSd0Migrations = true;
} else { } else {
@@ -67,7 +67,7 @@ void MigrationRunner::RunMigrations() {
} }
if (finalSQL.empty() && !runSd0Migrations) { if (finalSQL.empty() && !runSd0Migrations) {
Game::logger->Log("MigrationRunner", "Server database is up to date."); LOG("Server database is up to date.");
return; return;
} }
@@ -79,7 +79,7 @@ void MigrationRunner::RunMigrations() {
if (query.empty()) continue; if (query.empty()) continue;
simpleStatement->execute(query.c_str()); simpleStatement->execute(query.c_str());
} catch (sql::SQLException& e) { } catch (sql::SQLException& e) {
Game::logger->Log("MigrationRunner", "Encountered error running migration: %s", e.what()); LOG("Encountered error running migration: %s", e.what());
} }
} }
} }
@@ -87,9 +87,9 @@ void MigrationRunner::RunMigrations() {
// Do this last on the off chance none of the other migrations have been run yet. // Do this last on the off chance none of the other migrations have been run yet.
if (runSd0Migrations) { if (runSd0Migrations) {
uint32_t numberOfUpdatedModels = BrickByBrickFix::UpdateBrickByBrickModelsToSd0(); uint32_t numberOfUpdatedModels = BrickByBrickFix::UpdateBrickByBrickModelsToSd0();
Game::logger->Log("MasterServer", "%i models were updated from zlib to sd0.", numberOfUpdatedModels); LOG("%i models were updated from zlib to sd0.", numberOfUpdatedModels);
uint32_t numberOfTruncatedModels = BrickByBrickFix::TruncateBrokenBrickByBrickXml(); uint32_t numberOfTruncatedModels = BrickByBrickFix::TruncateBrokenBrickByBrickXml();
Game::logger->Log("MasterServer", "%i models were truncated from the database.", numberOfTruncatedModels); LOG("%i models were truncated from the database.", numberOfTruncatedModels);
} }
} }
@@ -135,14 +135,14 @@ void MigrationRunner::RunSQLiteMigrations() {
// Doing these 1 migration at a time since one takes a long time and some may think it is crashing. // Doing these 1 migration at a time since one takes a long time and some may think it is crashing.
// This will at the least guarentee that the full migration needs to be run in order to be counted as "migrated". // This will at the least guarentee that the full migration needs to be run in order to be counted as "migrated".
Game::logger->Log("MigrationRunner", "Executing migration: %s. This may take a while. Do not shut down server.", migration.name.c_str()); LOG("Executing migration: %s. This may take a while. Do not shut down server.", migration.name.c_str());
CDClientDatabase::ExecuteQuery("BEGIN TRANSACTION;"); CDClientDatabase::ExecuteQuery("BEGIN TRANSACTION;");
for (const auto& dml : GeneralUtils::SplitString(migration.data, ';')) { for (const auto& dml : GeneralUtils::SplitString(migration.data, ';')) {
if (dml.empty()) continue; if (dml.empty()) continue;
try { try {
CDClientDatabase::ExecuteDML(dml.c_str()); CDClientDatabase::ExecuteDML(dml.c_str());
} catch (CppSQLite3Exception& e) { } catch (CppSQLite3Exception& e) {
Game::logger->Log("MigrationRunner", "Encountered error running DML command: (%i) : %s", e.errorCode(), e.errorMessage()); LOG("Encountered error running DML command: (%i) : %s", e.errorCode(), e.errorMessage());
} }
} }
@@ -154,5 +154,5 @@ void MigrationRunner::RunSQLiteMigrations() {
CDClientDatabase::ExecuteQuery("COMMIT;"); CDClientDatabase::ExecuteQuery("COMMIT;");
} }
Game::logger->Log("MigrationRunner", "CDServer database is up to date."); LOG("CDServer database is up to date.");
} }

View File

@@ -1,7 +1,6 @@
#include "CDActivitiesTable.h" #include "CDActivitiesTable.h"
CDActivitiesTable::CDActivitiesTable(void) { void CDActivitiesTable::LoadValuesFromDatabase() {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM Activities"); auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM Activities");
@@ -55,8 +54,3 @@ std::vector<CDActivities> CDActivitiesTable::Query(std::function<bool(CDActiviti
return data; return data;
} }
std::vector<CDActivities> CDActivitiesTable::GetEntries(void) const {
return this->entries;
}

View File

@@ -30,9 +30,10 @@ private:
std::vector<CDActivities> entries; std::vector<CDActivities> entries;
public: public:
CDActivitiesTable(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDActivities> Query(std::function<bool(CDActivities)> predicate); std::vector<CDActivities> Query(std::function<bool(CDActivities)> predicate);
std::vector<CDActivities> GetEntries(void) const; const std::vector<CDActivities>& GetEntries() const { return this->entries; }
}; };

View File

@@ -1,6 +1,6 @@
#include "CDActivityRewardsTable.h" #include "CDActivityRewardsTable.h"
CDActivityRewardsTable::CDActivityRewardsTable(void) { void CDActivityRewardsTable::LoadValuesFromDatabase() {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
@@ -43,8 +43,3 @@ std::vector<CDActivityRewards> CDActivityRewardsTable::Query(std::function<bool(
return data; return data;
} }
std::vector<CDActivityRewards> CDActivityRewardsTable::GetEntries(void) const {
return this->entries;
}

View File

@@ -18,10 +18,10 @@ private:
std::vector<CDActivityRewards> entries; std::vector<CDActivityRewards> entries;
public: public:
CDActivityRewardsTable(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDActivityRewards> Query(std::function<bool(CDActivityRewards)> predicate); std::vector<CDActivityRewards> Query(std::function<bool(CDActivityRewards)> predicate);
std::vector<CDActivityRewards> GetEntries(void) const; std::vector<CDActivityRewards> GetEntries() const;
}; };

View File

@@ -2,6 +2,35 @@
#include "GeneralUtils.h" #include "GeneralUtils.h"
#include "Game.h" #include "Game.h"
void CDAnimationsTable::LoadValuesFromDatabase() {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Animations");
while (!tableData.eof()) {
std::string animation_type = tableData.getStringField("animation_type", "");
DluAssert(!animation_type.empty());
AnimationGroupID animationGroupID = tableData.getIntField("animationGroupID", -1);
DluAssert(animationGroupID != -1);
CDAnimation entry;
entry.animation_name = tableData.getStringField("animation_name", "");
entry.chance_to_play = tableData.getFloatField("chance_to_play", 1.0f);
UNUSED_COLUMN(entry.min_loops = tableData.getIntField("min_loops", 0);)
UNUSED_COLUMN(entry.max_loops = tableData.getIntField("max_loops", 0);)
entry.animation_length = tableData.getFloatField("animation_length", 0.0f);
UNUSED_COLUMN(entry.hideEquip = tableData.getIntField("hideEquip", 0) == 1;)
UNUSED_COLUMN(entry.ignoreUpperBody = tableData.getIntField("ignoreUpperBody", 0) == 1;)
UNUSED_COLUMN(entry.restartable = tableData.getIntField("restartable", 0) == 1;)
UNUSED_COLUMN(entry.face_animation_name = tableData.getStringField("face_animation_name", "");)
UNUSED_COLUMN(entry.priority = tableData.getFloatField("priority", 0.0f);)
UNUSED_COLUMN(entry.blendTime = tableData.getFloatField("blendTime", 0.0f);)
this->animations[CDAnimationKey(animation_type, animationGroupID)].push_back(entry);
tableData.nextRow();
}
tableData.finalize();
}
bool CDAnimationsTable::CacheData(CppSQLite3Statement& queryToCache) { bool CDAnimationsTable::CacheData(CppSQLite3Statement& queryToCache) {
auto tableData = queryToCache.execQuery(); auto tableData = queryToCache.execQuery();
// If we received a bad lookup, cache it anyways so we do not run the query again. // If we received a bad lookup, cache it anyways so we do not run the query again.

View File

@@ -27,6 +27,7 @@ class CDAnimationsTable : public CDTable<CDAnimationsTable> {
typedef std::string AnimationID; typedef std::string AnimationID;
typedef std::pair<std::string, AnimationGroupID> CDAnimationKey; typedef std::pair<std::string, AnimationGroupID> CDAnimationKey;
public: public:
void LoadValuesFromDatabase();
/** /**
* Given an animationType and the previousAnimationName played, return the next animationType to play. * Given an animationType and the previousAnimationName played, return the next animationType to play.
* If there are more than 1 animationTypes that can be played, one is selected at random but also does not allow * If there are more than 1 animationTypes that can be played, one is selected at random but also does not allow

View File

@@ -1,26 +1,30 @@
#include "CDBehaviorParameterTable.h" #include "CDBehaviorParameterTable.h"
#include "GeneralUtils.h" #include "GeneralUtils.h"
CDBehaviorParameterTable::CDBehaviorParameterTable(void) { uint64_t GetKey(const uint32_t behaviorID, const uint32_t parameterID) {
uint64_t key = behaviorID;
key <<= 31U;
key |= parameterID;
return key;
}
void CDBehaviorParameterTable::LoadValuesFromDatabase() {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorParameter"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorParameter");
uint32_t uniqueParameterId = 0;
uint64_t hash = 0;
while (!tableData.eof()) { while (!tableData.eof()) {
CDBehaviorParameter entry; uint32_t behaviorID = tableData.getIntField("behaviorID", -1);
entry.behaviorID = tableData.getIntField("behaviorID", -1);
auto candidateStringToAdd = std::string(tableData.getStringField("parameterID", "")); auto candidateStringToAdd = std::string(tableData.getStringField("parameterID", ""));
auto parameter = m_ParametersList.find(candidateStringToAdd); auto parameter = m_ParametersList.find(candidateStringToAdd);
uint32_t parameterId;
if (parameter != m_ParametersList.end()) { if (parameter != m_ParametersList.end()) {
entry.parameterID = parameter; parameterId = parameter->second;
} else { } else {
entry.parameterID = m_ParametersList.insert(std::make_pair(candidateStringToAdd, uniqueParameterId)).first; parameterId = m_ParametersList.insert(std::make_pair(candidateStringToAdd, m_ParametersList.size())).first->second;
uniqueParameterId++;
} }
hash = entry.behaviorID; uint64_t hash = GetKey(behaviorID, parameterId);
hash = (hash << 31U) | entry.parameterID->second; float value = tableData.getFloatField("value", -1.0f);
entry.value = tableData.getFloatField("value", -1.0f);
m_Entries.insert(std::make_pair(hash, entry)); m_Entries.insert(std::make_pair(hash, value));
tableData.nextRow(); tableData.nextRow();
} }
@@ -30,27 +34,22 @@ CDBehaviorParameterTable::CDBehaviorParameterTable(void) {
float CDBehaviorParameterTable::GetValue(const uint32_t behaviorID, const std::string& name, const float defaultValue) { float CDBehaviorParameterTable::GetValue(const uint32_t behaviorID, const std::string& name, const float defaultValue) {
auto parameterID = this->m_ParametersList.find(name); auto parameterID = this->m_ParametersList.find(name);
if (parameterID == this->m_ParametersList.end()) return defaultValue; if (parameterID == this->m_ParametersList.end()) return defaultValue;
auto hash = GetKey(behaviorID, parameterID->second);
uint64_t hash = behaviorID;
hash = (hash << 31U) | parameterID->second;
// Search for specific parameter // Search for specific parameter
const auto& it = m_Entries.find(hash); auto it = m_Entries.find(hash);
return it != m_Entries.end() ? it->second.value : defaultValue; return it != m_Entries.end() ? it->second : defaultValue;
} }
std::map<std::string, float> CDBehaviorParameterTable::GetParametersByBehaviorID(uint32_t behaviorID) { std::map<std::string, float> CDBehaviorParameterTable::GetParametersByBehaviorID(uint32_t behaviorID) {
uint64_t hashBase = behaviorID; uint64_t hashBase = behaviorID;
std::map<std::string, float> returnInfo; std::map<std::string, float> returnInfo;
uint64_t hash; for (auto& [parameterString, parameterId] : m_ParametersList) {
for (auto& parameterCandidate : m_ParametersList) { uint64_t hash = GetKey(hashBase, parameterId);
hash = (hashBase << 31U) | parameterCandidate.second;
auto infoCandidate = m_Entries.find(hash); auto infoCandidate = m_Entries.find(hash);
if (infoCandidate != m_Entries.end()) { if (infoCandidate != m_Entries.end()) {
returnInfo.insert(std::make_pair(infoCandidate->second.parameterID->first, infoCandidate->second.value)); returnInfo.insert(std::make_pair(parameterString, infoCandidate->second));
} }
} }
return returnInfo; return returnInfo;
} }

View File

@@ -5,18 +5,15 @@
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
struct CDBehaviorParameter {
unsigned int behaviorID; //!< The Behavior ID
std::unordered_map<std::string, uint32_t>::iterator parameterID; //!< The Parameter ID
float value; //!< The value of the behavior template
};
class CDBehaviorParameterTable : public CDTable<CDBehaviorParameterTable> { class CDBehaviorParameterTable : public CDTable<CDBehaviorParameterTable> {
private: private:
std::unordered_map<uint64_t, CDBehaviorParameter> m_Entries; typedef uint64_t BehaviorParameterHash;
typedef float BehaviorParameterValue;
std::unordered_map<BehaviorParameterHash, BehaviorParameterValue> m_Entries;
std::unordered_map<std::string, uint32_t> m_ParametersList; std::unordered_map<std::string, uint32_t> m_ParametersList;
public: public:
CDBehaviorParameterTable(); void LoadValuesFromDatabase();
float GetValue(const uint32_t behaviorID, const std::string& name, const float defaultValue = 0); float GetValue(const uint32_t behaviorID, const std::string& name, const float defaultValue = 0);
std::map<std::string, float> GetParametersByBehaviorID(uint32_t behaviorID); std::map<std::string, float> GetParametersByBehaviorID(uint32_t behaviorID);

View File

@@ -1,6 +1,6 @@
#include "CDBehaviorTemplateTable.h" #include "CDBehaviorTemplateTable.h"
CDBehaviorTemplateTable::CDBehaviorTemplateTable(void) { void CDBehaviorTemplateTable::LoadValuesFromDatabase() {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
@@ -48,7 +48,7 @@ std::vector<CDBehaviorTemplate> CDBehaviorTemplateTable::Query(std::function<boo
return data; return data;
} }
std::vector<CDBehaviorTemplate> CDBehaviorTemplateTable::GetEntries(void) const { const std::vector<CDBehaviorTemplate>& CDBehaviorTemplateTable::GetEntries() const {
return this->entries; return this->entries;
} }
@@ -64,4 +64,3 @@ const CDBehaviorTemplate CDBehaviorTemplateTable::GetByBehaviorID(uint32_t behav
return entry->second; return entry->second;
} }
} }

View File

@@ -19,11 +19,12 @@ private:
std::unordered_map<uint32_t, CDBehaviorTemplate> entriesMappedByBehaviorID; std::unordered_map<uint32_t, CDBehaviorTemplate> entriesMappedByBehaviorID;
std::unordered_set<std::string> m_EffectHandles; std::unordered_set<std::string> m_EffectHandles;
public: public:
CDBehaviorTemplateTable(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDBehaviorTemplate> Query(std::function<bool(CDBehaviorTemplate)> predicate); std::vector<CDBehaviorTemplate> Query(std::function<bool(CDBehaviorTemplate)> predicate);
std::vector<CDBehaviorTemplate> GetEntries(void) const; const std::vector<CDBehaviorTemplate>& GetEntries(void) const;
const CDBehaviorTemplate GetByBehaviorID(uint32_t behaviorID); const CDBehaviorTemplate GetByBehaviorID(uint32_t behaviorID);
}; };

View File

@@ -1,6 +1,6 @@
#include "CDBrickIDTableTable.h" #include "CDBrickIDTableTable.h"
CDBrickIDTableTable::CDBrickIDTableTable(void) { void CDBrickIDTableTable::LoadValuesFromDatabase() {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
@@ -39,7 +39,7 @@ std::vector<CDBrickIDTable> CDBrickIDTableTable::Query(std::function<bool(CDBric
return data; return data;
} }
std::vector<CDBrickIDTable> CDBrickIDTableTable::GetEntries(void) const { const std::vector<CDBrickIDTable>& CDBrickIDTableTable::GetEntries() const {
return this->entries; return this->entries;
} }

View File

@@ -21,9 +21,9 @@ private:
std::vector<CDBrickIDTable> entries; std::vector<CDBrickIDTable> entries;
public: public:
CDBrickIDTableTable(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDBrickIDTable> Query(std::function<bool(CDBrickIDTable)> predicate); std::vector<CDBrickIDTable> Query(std::function<bool(CDBrickIDTable)> predicate);
std::vector<CDBrickIDTable> GetEntries(void) const; const std::vector<CDBrickIDTable>& GetEntries() const;
}; };

View File

@@ -1,27 +1,37 @@
#include "CDComponentsRegistryTable.h" #include "CDComponentsRegistryTable.h"
#include "eReplicaComponentType.h" #include "eReplicaComponentType.h"
#define CDCLIENT_CACHE_ALL void CDComponentsRegistryTable::LoadValuesFromDatabase() {
CDComponentsRegistryTable::CDComponentsRegistryTable(void) {
#ifdef CDCLIENT_CACHE_ALL
// First, get the size of the table
unsigned int size = 0;
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM ComponentsRegistry");
while (!tableSize.eof()) {
size = tableSize.getIntField(0, 0);
tableSize.nextRow();
}
tableSize.finalize();
// Reserve the size
//this->entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ComponentsRegistry"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ComponentsRegistry");
while (!tableData.eof()) {
CDComponentsRegistry entry;
entry.id = tableData.getIntField("id", -1);
entry.component_type = static_cast<eReplicaComponentType>(tableData.getIntField("component_type", 0));
entry.component_id = tableData.getIntField("component_id", -1);
this->mappedEntries.insert_or_assign(((uint64_t)entry.component_type) << 32 | ((uint64_t)entry.id), entry.component_id);
this->mappedEntries.insert_or_assign(entry.id, 0);
tableData.nextRow();
}
tableData.finalize();
}
int32_t CDComponentsRegistryTable::GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue) {
auto exists = mappedEntries.find(id);
if (exists != mappedEntries.end()) {
auto iter = mappedEntries.find(((uint64_t)componentType) << 32 | ((uint64_t)id));
return iter == mappedEntries.end() ? defaultValue : iter->second;
}
// Now get the data. Get all components of this entity so we dont do a query for each component
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM ComponentsRegistry WHERE id = ?;");
query.bind(1, static_cast<int32_t>(id));
auto tableData = query.execQuery();
while (!tableData.eof()) { while (!tableData.eof()) {
CDComponentsRegistry entry; CDComponentsRegistry entry;
entry.id = tableData.getIntField("id", -1); entry.id = tableData.getIntField("id", -1);
@@ -33,61 +43,10 @@ CDComponentsRegistryTable::CDComponentsRegistryTable(void) {
tableData.nextRow(); tableData.nextRow();
} }
tableData.finalize(); mappedEntries.insert_or_assign(id, 0);
#endif
} auto iter = this->mappedEntries.find(((uint64_t)componentType) << 32 | ((uint64_t)id));
int32_t CDComponentsRegistryTable::GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue) { return iter == this->mappedEntries.end() ? defaultValue : iter->second;
const auto& iter = this->mappedEntries.find(((uint64_t)componentType) << 32 | ((uint64_t)id));
if (iter == this->mappedEntries.end()) {
return defaultValue;
}
return iter->second;
#ifndef CDCLIENT_CACHE_ALL
// Now get the data
std::stringstream query;
query << "SELECT * FROM ComponentsRegistry WHERE id = " << std::to_string(id);
auto tableData = CDClientDatabase::ExecuteQuery(query.str());
while (!tableData.eof()) {
CDComponentsRegistry entry;
entry.id = tableData.getIntField("id", -1);
entry.component_type = tableData.getIntField("component_type", -1);
entry.component_id = tableData.getIntField("component_id", -1);
//this->entries.push_back(entry);
//Darwin's stuff:
const auto& it = this->mappedEntries.find(entry.id);
if (it != mappedEntries.end()) {
const auto& iter = it->second.find(entry.component_type);
if (iter == it->second.end()) {
it->second.insert(std::make_pair(entry.component_type, entry.component_id));
}
} else {
std::map<unsigned int, unsigned int> map;
map.insert(std::make_pair(entry.component_type, entry.component_id));
this->mappedEntries.insert(std::make_pair(entry.id, map));
}
tableData.nextRow();
}
tableData.finalize();
const auto& it2 = this->mappedEntries.find(id);
if (it2 != mappedEntries.end()) {
const auto& iter = it2->second.find(componentType);
if (iter != it2->second.end()) {
return iter->second;
}
}
return defaultValue;
#endif
} }

View File

@@ -13,9 +13,9 @@ struct CDComponentsRegistry {
class CDComponentsRegistryTable : public CDTable<CDComponentsRegistryTable> { class CDComponentsRegistryTable : public CDTable<CDComponentsRegistryTable> {
private: private:
std::map<uint64_t, uint32_t> mappedEntries; //id, component_type, component_id std::unordered_map<uint64_t, uint32_t> mappedEntries; //id, component_type, component_id
public: public:
CDComponentsRegistryTable(); void LoadValuesFromDatabase();
int32_t GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue = 0); int32_t GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue = 0);
}; };

View File

@@ -1,7 +1,7 @@
#include "CDCurrencyTableTable.h" #include "CDCurrencyTableTable.h"
//! Constructor //! Constructor
CDCurrencyTableTable::CDCurrencyTableTable(void) { void CDCurrencyTableTable::LoadValuesFromDatabase() {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
@@ -43,7 +43,7 @@ std::vector<CDCurrencyTable> CDCurrencyTableTable::Query(std::function<bool(CDCu
return data; return data;
} }
std::vector<CDCurrencyTable> CDCurrencyTableTable::GetEntries(void) const { const std::vector<CDCurrencyTable>& CDCurrencyTableTable::GetEntries() const {
return this->entries; return this->entries;
} }

View File

@@ -23,9 +23,9 @@ private:
std::vector<CDCurrencyTable> entries; std::vector<CDCurrencyTable> entries;
public: public:
CDCurrencyTableTable(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDCurrencyTable> Query(std::function<bool(CDCurrencyTable)> predicate); std::vector<CDCurrencyTable> Query(std::function<bool(CDCurrencyTable)> predicate);
std::vector<CDCurrencyTable> GetEntries(void) const; const std::vector<CDCurrencyTable>& GetEntries() const;
}; };

View File

@@ -1,8 +1,6 @@
#include "CDDestructibleComponentTable.h" #include "CDDestructibleComponentTable.h"
//! Constructor void CDDestructibleComponentTable::LoadValuesFromDatabase() {
CDDestructibleComponentTable::CDDestructibleComponentTable(void) {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM DestructibleComponent"); auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM DestructibleComponent");
@@ -52,7 +50,7 @@ std::vector<CDDestructibleComponent> CDDestructibleComponentTable::Query(std::fu
return data; return data;
} }
std::vector<CDDestructibleComponent> CDDestructibleComponentTable::GetEntries(void) const { const std::vector<CDDestructibleComponent>& CDDestructibleComponentTable::GetEntries() const {
return this->entries; return this->entries;
} }

View File

@@ -25,9 +25,9 @@ private:
std::vector<CDDestructibleComponent> entries; std::vector<CDDestructibleComponent> entries;
public: public:
CDDestructibleComponentTable(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDDestructibleComponent> Query(std::function<bool(CDDestructibleComponent)> predicate); std::vector<CDDestructibleComponent> Query(std::function<bool(CDDestructibleComponent)> predicate);
std::vector<CDDestructibleComponent> GetEntries(void) const; const std::vector<CDDestructibleComponent>& GetEntries(void) const;
}; };

View File

@@ -1,40 +1,26 @@
#include "CDEmoteTable.h" #include "CDEmoteTable.h"
//! Constructor void CDEmoteTableTable::LoadValuesFromDatabase() {
CDEmoteTableTable::CDEmoteTableTable(void) {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Emotes"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Emotes");
while (!tableData.eof()) { while (!tableData.eof()) {
CDEmoteTable* entry = new CDEmoteTable(); CDEmoteTable entry;
entry->ID = tableData.getIntField("id", -1); entry.ID = tableData.getIntField("id", -1);
entry->animationName = tableData.getStringField("animationName", ""); entry.animationName = tableData.getStringField("animationName", "");
entry->iconFilename = tableData.getStringField("iconFilename", ""); entry.iconFilename = tableData.getStringField("iconFilename", "");
entry->channel = tableData.getIntField("channel", -1); entry.channel = tableData.getIntField("channel", -1);
entry->locked = tableData.getIntField("locked", -1) != 0; entry.locked = tableData.getIntField("locked", -1) != 0;
entry->localize = tableData.getIntField("localize", -1) != 0; entry.localize = tableData.getIntField("localize", -1) != 0;
entry->locState = tableData.getIntField("locStatus", -1); entry.locState = tableData.getIntField("locStatus", -1);
entry->gateVersion = tableData.getStringField("gate_version", ""); entry.gateVersion = tableData.getStringField("gate_version", "");
entries.insert(std::make_pair(entry->ID, entry)); entries.insert(std::make_pair(entry.ID, entry));
tableData.nextRow(); tableData.nextRow();
} }
tableData.finalize(); tableData.finalize();
} }
//! Destructor
CDEmoteTableTable::~CDEmoteTableTable(void) {
for (auto e : entries) {
if (e.second) delete e.second;
}
entries.clear();
}
CDEmoteTable* CDEmoteTableTable::GetEmote(int id) { CDEmoteTable* CDEmoteTableTable::GetEmote(int id) {
for (auto e : entries) { auto itr = entries.find(id);
if (e.first == id) return e.second; return itr != entries.end() ? &itr->second : nullptr;
}
return nullptr;
} }

View File

@@ -28,11 +28,10 @@ struct CDEmoteTable {
class CDEmoteTableTable : public CDTable<CDEmoteTableTable> { class CDEmoteTableTable : public CDTable<CDEmoteTableTable> {
private: private:
std::map<int, CDEmoteTable*> entries; std::map<int, CDEmoteTable> entries;
public: public:
CDEmoteTableTable(); void LoadValuesFromDatabase();
~CDEmoteTableTable();
// Returns an emote by ID // Returns an emote by ID
CDEmoteTable* GetEmote(int id); CDEmoteTable* GetEmote(int id);
}; };

View File

@@ -1,7 +1,6 @@
#include "CDFeatureGatingTable.h" #include "CDFeatureGatingTable.h"
//! Constructor void CDFeatureGatingTable::LoadValuesFromDatabase() {
CDFeatureGatingTable::CDFeatureGatingTable(void) {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
@@ -53,7 +52,7 @@ bool CDFeatureGatingTable::FeatureUnlocked(const std::string& feature) const {
return false; return false;
} }
std::vector<CDFeatureGating> CDFeatureGatingTable::GetEntries(void) const { const std::vector<CDFeatureGating>& CDFeatureGatingTable::GetEntries() const {
return this->entries; return this->entries;
} }

View File

@@ -16,11 +16,12 @@ private:
std::vector<CDFeatureGating> entries; std::vector<CDFeatureGating> entries;
public: public:
CDFeatureGatingTable(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDFeatureGating> Query(std::function<bool(CDFeatureGating)> predicate); std::vector<CDFeatureGating> Query(std::function<bool(CDFeatureGating)> predicate);
bool FeatureUnlocked(const std::string& feature) const; bool FeatureUnlocked(const std::string& feature) const;
std::vector<CDFeatureGating> GetEntries(void) const; const std::vector<CDFeatureGating>& GetEntries(void) const;
}; };

View File

@@ -1,7 +1,6 @@
#include "CDInventoryComponentTable.h" #include "CDInventoryComponentTable.h"
//! Constructor void CDInventoryComponentTable::LoadValuesFromDatabase() {
CDInventoryComponentTable::CDInventoryComponentTable(void) {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
@@ -42,7 +41,7 @@ std::vector<CDInventoryComponent> CDInventoryComponentTable::Query(std::function
return data; return data;
} }
std::vector<CDInventoryComponent> CDInventoryComponentTable::GetEntries(void) const { const std::vector<CDInventoryComponent>& CDInventoryComponentTable::GetEntries() const {
return this->entries; return this->entries;
} }

View File

@@ -15,9 +15,9 @@ private:
std::vector<CDInventoryComponent> entries; std::vector<CDInventoryComponent> entries;
public: public:
CDInventoryComponentTable(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDInventoryComponent> Query(std::function<bool(CDInventoryComponent)> predicate); std::vector<CDInventoryComponent> Query(std::function<bool(CDInventoryComponent)> predicate);
std::vector<CDInventoryComponent> GetEntries(void) const; const std::vector<CDInventoryComponent>& GetEntries() const;
}; };

View File

@@ -3,11 +3,7 @@
CDItemComponent CDItemComponentTable::Default = {}; CDItemComponent CDItemComponentTable::Default = {};
//! Constructor void CDItemComponentTable::LoadValuesFromDatabase() {
CDItemComponentTable::CDItemComponentTable(void) {
Default = CDItemComponent();
#ifdef CDCLIENT_CACHE_ALL
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM ItemComponent"); auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM ItemComponent");
@@ -55,13 +51,13 @@ CDItemComponentTable::CDItemComponentTable(void) {
entry.currencyLOT = tableData.getIntField("currencyLOT", -1); entry.currencyLOT = tableData.getIntField("currencyLOT", -1);
entry.altCurrencyCost = tableData.getIntField("altCurrencyCost", -1); entry.altCurrencyCost = tableData.getIntField("altCurrencyCost", -1);
entry.subItems = tableData.getStringField("subItems", ""); entry.subItems = tableData.getStringField("subItems", "");
entry.audioEventUse = tableData.getStringField("audioEventUse", ""); UNUSED_COLUMN(entry.audioEventUse = tableData.getStringField("audioEventUse", ""));
entry.noEquipAnimation = tableData.getIntField("noEquipAnimation", -1) == 1 ? true : false; entry.noEquipAnimation = tableData.getIntField("noEquipAnimation", -1) == 1 ? true : false;
entry.commendationLOT = tableData.getIntField("commendationLOT", -1); entry.commendationLOT = tableData.getIntField("commendationLOT", -1);
entry.commendationCost = tableData.getIntField("commendationCost", -1); entry.commendationCost = tableData.getIntField("commendationCost", -1);
entry.audioEquipMetaEventSet = tableData.getStringField("audioEquipMetaEventSet", ""); UNUSED_COLUMN(entry.audioEquipMetaEventSet = tableData.getStringField("audioEquipMetaEventSet", ""));
entry.currencyCosts = tableData.getStringField("currencyCosts", ""); entry.currencyCosts = tableData.getStringField("currencyCosts", "");
entry.ingredientInfo = tableData.getStringField("ingredientInfo", ""); UNUSED_COLUMN(entry.ingredientInfo = tableData.getStringField("ingredientInfo", ""));
entry.locStatus = tableData.getIntField("locStatus", -1); entry.locStatus = tableData.getIntField("locStatus", -1);
entry.forgeType = tableData.getIntField("forgeType", -1); entry.forgeType = tableData.getIntField("forgeType", -1);
entry.SellMultiplier = tableData.getFloatField("SellMultiplier", -1.0f); entry.SellMultiplier = tableData.getFloatField("SellMultiplier", -1.0f);
@@ -71,7 +67,6 @@ CDItemComponentTable::CDItemComponentTable(void) {
} }
tableData.finalize(); tableData.finalize();
#endif
} }
const CDItemComponent& CDItemComponentTable::GetItemComponentByID(unsigned int skillID) { const CDItemComponent& CDItemComponentTable::GetItemComponentByID(unsigned int skillID) {
@@ -80,12 +75,10 @@ const CDItemComponent& CDItemComponentTable::GetItemComponentByID(unsigned int s
return it->second; return it->second;
} }
#ifndef CDCLIENT_CACHE_ALL auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM ItemComponent WHERE id = ?;");
std::stringstream query; query.bind(1, static_cast<int32_t>(skillID));
query << "SELECT * FROM ItemComponent WHERE id = " << std::to_string(skillID); auto tableData = query.execQuery();
auto tableData = CDClientDatabase::ExecuteQuery(query.str());
if (tableData.eof()) { if (tableData.eof()) {
entries.insert(std::make_pair(skillID, Default)); entries.insert(std::make_pair(skillID, Default));
return Default; return Default;
@@ -144,7 +137,6 @@ const CDItemComponent& CDItemComponentTable::GetItemComponentByID(unsigned int s
if (it2 != this->entries.end()) { if (it2 != this->entries.end()) {
return it2->second; return it2->second;
} }
#endif
return Default; return Default;
} }

View File

@@ -54,7 +54,7 @@ private:
std::map<unsigned int, CDItemComponent> entries; std::map<unsigned int, CDItemComponent> entries;
public: public:
CDItemComponentTable(); void LoadValuesFromDatabase();
static std::map<LOT, uint32_t> ParseCraftingCurrencies(const CDItemComponent& itemComponent); static std::map<LOT, uint32_t> ParseCraftingCurrencies(const CDItemComponent& itemComponent);
// Gets an entry by ID // Gets an entry by ID

View File

@@ -1,7 +1,6 @@
#include "CDItemSetSkillsTable.h" #include "CDItemSetSkillsTable.h"
//! Constructor void CDItemSetSkillsTable::LoadValuesFromDatabase() {
CDItemSetSkillsTable::CDItemSetSkillsTable(void) {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
@@ -41,7 +40,7 @@ std::vector<CDItemSetSkills> CDItemSetSkillsTable::Query(std::function<bool(CDIt
return data; return data;
} }
std::vector<CDItemSetSkills> CDItemSetSkillsTable::GetEntries(void) const { const std::vector<CDItemSetSkills>& CDItemSetSkillsTable::GetEntries() const {
return this->entries; return this->entries;
} }

View File

@@ -14,11 +14,11 @@ private:
std::vector<CDItemSetSkills> entries; std::vector<CDItemSetSkills> entries;
public: public:
CDItemSetSkillsTable(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDItemSetSkills> Query(std::function<bool(CDItemSetSkills)> predicate); std::vector<CDItemSetSkills> Query(std::function<bool(CDItemSetSkills)> predicate);
std::vector<CDItemSetSkills> GetEntries(void) const; const std::vector<CDItemSetSkills>& GetEntries() const;
std::vector<CDItemSetSkills> GetBySkillID(unsigned int SkillSetID); std::vector<CDItemSetSkills> GetBySkillID(unsigned int SkillSetID);
}; };

View File

@@ -1,7 +1,6 @@
#include "CDItemSetsTable.h" #include "CDItemSetsTable.h"
//! Constructor void CDItemSetsTable::LoadValuesFromDatabase() {
CDItemSetsTable::CDItemSetsTable(void) {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
@@ -53,7 +52,7 @@ std::vector<CDItemSets> CDItemSetsTable::Query(std::function<bool(CDItemSets)> p
return data; return data;
} }
std::vector<CDItemSets> CDItemSetsTable::GetEntries(void) const { const std::vector<CDItemSets>& CDItemSetsTable::GetEntries() const {
return this->entries; return this->entries;
} }

View File

@@ -26,10 +26,10 @@ private:
std::vector<CDItemSets> entries; std::vector<CDItemSets> entries;
public: public:
CDItemSetsTable(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDItemSets> Query(std::function<bool(CDItemSets)> predicate); std::vector<CDItemSets> Query(std::function<bool(CDItemSets)> predicate);
std::vector<CDItemSets> GetEntries(void) const; const std::vector<CDItemSets>& GetEntries(void) const;
}; };

View File

@@ -1,7 +1,6 @@
#include "CDLevelProgressionLookupTable.h" #include "CDLevelProgressionLookupTable.h"
//! Constructor void CDLevelProgressionLookupTable::LoadValuesFromDatabase() {
CDLevelProgressionLookupTable::CDLevelProgressionLookupTable(void) {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
@@ -32,7 +31,6 @@ CDLevelProgressionLookupTable::CDLevelProgressionLookupTable(void) {
tableData.finalize(); tableData.finalize();
} }
//! Queries the table with a custom "where" clause
std::vector<CDLevelProgressionLookup> CDLevelProgressionLookupTable::Query(std::function<bool(CDLevelProgressionLookup)> predicate) { std::vector<CDLevelProgressionLookup> CDLevelProgressionLookupTable::Query(std::function<bool(CDLevelProgressionLookup)> predicate) {
std::vector<CDLevelProgressionLookup> data = cpplinq::from(this->entries) std::vector<CDLevelProgressionLookup> data = cpplinq::from(this->entries)
@@ -42,8 +40,7 @@ std::vector<CDLevelProgressionLookup> CDLevelProgressionLookupTable::Query(std::
return data; return data;
} }
//! Gets all the entries in the table const std::vector<CDLevelProgressionLookup>& CDLevelProgressionLookupTable::GetEntries() const {
std::vector<CDLevelProgressionLookup> CDLevelProgressionLookupTable::GetEntries(void) const {
return this->entries; return this->entries;
} }

View File

@@ -14,10 +14,10 @@ private:
std::vector<CDLevelProgressionLookup> entries; std::vector<CDLevelProgressionLookup> entries;
public: public:
CDLevelProgressionLookupTable(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDLevelProgressionLookup> Query(std::function<bool(CDLevelProgressionLookup)> predicate); std::vector<CDLevelProgressionLookup> Query(std::function<bool(CDLevelProgressionLookup)> predicate);
// Gets all the entries in the table const std::vector<CDLevelProgressionLookup>& GetEntries() const;
std::vector<CDLevelProgressionLookup> GetEntries(void) const;
}; };

View File

@@ -1,7 +1,19 @@
#include "CDLootMatrixTable.h" #include "CDLootMatrixTable.h"
//! Constructor CDLootMatrix CDLootMatrixTable::ReadRow(CppSQLite3Query& tableData) const {
CDLootMatrixTable::CDLootMatrixTable(void) { CDLootMatrix entry{};
if (tableData.eof()) return entry;
entry.LootTableIndex = tableData.getIntField("LootTableIndex", -1);
entry.RarityTableIndex = tableData.getIntField("RarityTableIndex", -1);
entry.percent = tableData.getFloatField("percent", -1.0f);
entry.minToDrop = tableData.getIntField("minToDrop", -1);
entry.maxToDrop = tableData.getIntField("maxToDrop", -1);
entry.flagID = tableData.getIntField("flagID", -1);
UNUSED(entry.gate_version = tableData.getStringField("gate_version", ""));
return entry;
}
void CDLootMatrixTable::LoadValuesFromDatabase() {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
@@ -12,8 +24,6 @@ CDLootMatrixTable::CDLootMatrixTable(void) {
tableSize.nextRow(); tableSize.nextRow();
} }
tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); this->entries.reserve(size);
@@ -21,33 +31,28 @@ CDLootMatrixTable::CDLootMatrixTable(void) {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootMatrix"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootMatrix");
while (!tableData.eof()) { while (!tableData.eof()) {
CDLootMatrix entry; CDLootMatrix entry;
entry.LootMatrixIndex = tableData.getIntField("LootMatrixIndex", -1); uint32_t lootMatrixIndex = tableData.getIntField("LootMatrixIndex", -1);
entry.LootTableIndex = tableData.getIntField("LootTableIndex", -1);
entry.RarityTableIndex = tableData.getIntField("RarityTableIndex", -1);
entry.percent = tableData.getFloatField("percent", -1.0f);
entry.minToDrop = tableData.getIntField("minToDrop", -1);
entry.maxToDrop = tableData.getIntField("maxToDrop", -1);
entry.id = tableData.getIntField("id", -1);
entry.flagID = tableData.getIntField("flagID", -1);
UNUSED(entry.gate_version = tableData.getStringField("gate_version", ""));
this->entries.push_back(entry); this->entries[lootMatrixIndex].push_back(ReadRow(tableData));
tableData.nextRow();
}
}
const LootMatrixEntries& CDLootMatrixTable::GetMatrix(uint32_t matrixId) {
auto itr = this->entries.find(matrixId);
if (itr != this->entries.end()) {
return itr->second;
}
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM LootMatrix where LootMatrixIndex = ?;");
query.bind(1, static_cast<int32_t>(matrixId));
auto tableData = query.execQuery();
while (!tableData.eof()) {
this->entries[matrixId].push_back(ReadRow(tableData));
tableData.nextRow(); tableData.nextRow();
} }
tableData.finalize(); return this->entries[matrixId];
}
std::vector<CDLootMatrix> CDLootMatrixTable::Query(std::function<bool(CDLootMatrix)> predicate) {
std::vector<CDLootMatrix> data = cpplinq::from(this->entries)
>> cpplinq::where(predicate)
>> cpplinq::to_vector();
return data;
}
const std::vector<CDLootMatrix>& CDLootMatrixTable::GetEntries(void) const {
return this->entries;
} }

View File

@@ -4,26 +4,26 @@
#include "CDTable.h" #include "CDTable.h"
struct CDLootMatrix { struct CDLootMatrix {
unsigned int LootMatrixIndex; //!< The Loot Matrix Index
unsigned int LootTableIndex; //!< The Loot Table Index unsigned int LootTableIndex; //!< The Loot Table Index
unsigned int RarityTableIndex; //!< The Rarity Table Index unsigned int RarityTableIndex; //!< The Rarity Table Index
float percent; //!< The percent that this matrix is used? float percent; //!< The percent that this matrix is used?
unsigned int minToDrop; //!< The minimum amount of loot from this matrix to drop unsigned int minToDrop; //!< The minimum amount of loot from this matrix to drop
unsigned int maxToDrop; //!< The maximum amount of loot from this matrix to drop unsigned int maxToDrop; //!< The maximum amount of loot from this matrix to drop
unsigned int id; //!< The ID of the Loot Matrix
unsigned int flagID; //!< ??? unsigned int flagID; //!< ???
UNUSED(std::string gate_version); //!< The Gate Version UNUSED(std::string gate_version); //!< The Gate Version
}; };
typedef uint32_t LootMatrixIndex;
typedef std::vector<CDLootMatrix> LootMatrixEntries;
class CDLootMatrixTable : public CDTable<CDLootMatrixTable> { class CDLootMatrixTable : public CDTable<CDLootMatrixTable> {
private:
std::vector<CDLootMatrix> entries;
public: public:
CDLootMatrixTable(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause
std::vector<CDLootMatrix> Query(std::function<bool(CDLootMatrix)> predicate);
const std::vector<CDLootMatrix>& GetEntries(void) const; // Gets a matrix by ID or inserts a blank one if none existed.
const LootMatrixEntries& GetMatrix(uint32_t matrixId);
private:
CDLootMatrix ReadRow(CppSQLite3Query& tableData) const;
std::unordered_map<LootMatrixIndex, LootMatrixEntries> entries;
}; };

View File

@@ -1,7 +1,43 @@
#include "CDLootTableTable.h" #include "CDLootTableTable.h"
#include "CDClientManager.h"
#include "CDComponentsRegistryTable.h"
#include "CDItemComponentTable.h"
#include "eReplicaComponentType.h"
//! Constructor // Sort the tables by their rarity so the highest rarity items are first.
CDLootTableTable::CDLootTableTable(void) { void SortTable(LootTableEntries& table) {
auto* componentsRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();
auto* itemComponentTable = CDClientManager::Instance().GetTable<CDItemComponentTable>();
// We modify the table in place so the outer loop keeps track of what is sorted
// and the inner loop finds the highest rarity item and swaps it with the current position
// of the outer loop.
for (auto oldItrOuter = table.begin(); oldItrOuter != table.end(); oldItrOuter++) {
auto lootToInsert = oldItrOuter;
// Its fine if this starts at 0, even if this doesnt match lootToInsert as the actual highest will
// either be found and overwrite these values, or the original is somehow zero and is still the highest rarity.
uint32_t highestLootRarity = 0;
for (auto oldItrInner = oldItrOuter; oldItrInner != table.end(); oldItrInner++) {
uint32_t itemComponentId = componentsRegistryTable->GetByIDAndType(oldItrInner->itemid, eReplicaComponentType::ITEM);
uint32_t rarity = itemComponentTable->GetItemComponentByID(itemComponentId).rarity;
if (rarity > highestLootRarity) {
highestLootRarity = rarity;
lootToInsert = oldItrInner;
}
}
std::swap(*oldItrOuter, *lootToInsert);
}
}
CDLootTable CDLootTableTable::ReadRow(CppSQLite3Query& tableData) const {
CDLootTable entry{};
if (tableData.eof()) return entry;
entry.itemid = tableData.getIntField("itemid", -1);
entry.MissionDrop = tableData.getIntField("MissionDrop", -1) == 1 ? true : false;
entry.sortPriority = tableData.getIntField("sortPriority", -1);
return entry;
}
void CDLootTableTable::LoadValuesFromDatabase() {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
@@ -12,8 +48,6 @@ CDLootTableTable::CDLootTableTable(void) {
tableSize.nextRow(); tableSize.nextRow();
} }
tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); this->entries.reserve(size);
@@ -21,32 +55,32 @@ CDLootTableTable::CDLootTableTable(void) {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootTable"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootTable");
while (!tableData.eof()) { while (!tableData.eof()) {
CDLootTable entry; CDLootTable entry;
entry.id = tableData.getIntField("id", -1); uint32_t lootTableIndex = tableData.getIntField("LootTableIndex", -1);
entry.itemid = tableData.getIntField("itemid", -1);
entry.LootTableIndex = tableData.getIntField("LootTableIndex", -1);
entry.id = tableData.getIntField("id", -1);
entry.MissionDrop = tableData.getIntField("MissionDrop", -1) == 1 ? true : false;
entry.sortPriority = tableData.getIntField("sortPriority", -1);
this->entries.push_back(entry); this->entries[lootTableIndex].push_back(ReadRow(tableData));
tableData.nextRow(); tableData.nextRow();
} }
for (auto& [id, table] : this->entries) {
tableData.finalize(); SortTable(table);
}
} }
//! Queries the table with a custom "where" clause const LootTableEntries& CDLootTableTable::GetTable(uint32_t tableId) {
std::vector<CDLootTable> CDLootTableTable::Query(std::function<bool(CDLootTable)> predicate) { auto itr = this->entries.find(tableId);
if (itr != this->entries.end()) {
return itr->second;
}
std::vector<CDLootTable> data = cpplinq::from(this->entries) auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM LootTable WHERE LootTableIndex = ?;");
>> cpplinq::where(predicate) query.bind(1, static_cast<int32_t>(tableId));
>> cpplinq::to_vector(); auto tableData = query.execQuery();
return data; while (!tableData.eof()) {
CDLootTable entry;
this->entries[tableId].push_back(ReadRow(tableData));
tableData.nextRow();
}
SortTable(this->entries[tableId]);
return this->entries[tableId];
} }
//! Gets all the entries in the table
const std::vector<CDLootTable>& CDLootTableTable::GetEntries(void) const {
return this->entries;
}

View File

@@ -6,20 +6,21 @@
struct CDLootTable { struct CDLootTable {
unsigned int itemid; //!< The LOT of the item unsigned int itemid; //!< The LOT of the item
unsigned int LootTableIndex; //!< The Loot Table Index unsigned int LootTableIndex; //!< The Loot Table Index
unsigned int id; //!< The ID
bool MissionDrop; //!< Whether or not this loot table is a mission drop bool MissionDrop; //!< Whether or not this loot table is a mission drop
unsigned int sortPriority; //!< The sorting priority unsigned int sortPriority; //!< The sorting priority
}; };
typedef uint32_t LootTableIndex;
typedef std::vector<CDLootTable> LootTableEntries;
class CDLootTableTable : public CDTable<CDLootTableTable> { class CDLootTableTable : public CDTable<CDLootTableTable> {
private: private:
std::vector<CDLootTable> entries; CDLootTable ReadRow(CppSQLite3Query& tableData) const;
std::unordered_map<LootTableIndex, LootTableEntries> entries;
public: public:
CDLootTableTable(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDLootTable> Query(std::function<bool(CDLootTable)> predicate); const LootTableEntries& GetTable(uint32_t tableId);
const std::vector<CDLootTable>& GetEntries(void) const;
}; };

View File

@@ -1,7 +1,6 @@
#include "CDMissionEmailTable.h" #include "CDMissionEmailTable.h"
//! Constructor void CDMissionEmailTable::LoadValuesFromDatabase() {
CDMissionEmailTable::CDMissionEmailTable(void) {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
@@ -48,7 +47,7 @@ std::vector<CDMissionEmail> CDMissionEmailTable::Query(std::function<bool(CDMiss
} }
//! Gets all the entries in the table //! Gets all the entries in the table
std::vector<CDMissionEmail> CDMissionEmailTable::GetEntries(void) const { const std::vector<CDMissionEmail>& CDMissionEmailTable::GetEntries() const {
return this->entries; return this->entries;
} }

View File

@@ -20,9 +20,9 @@ private:
std::vector<CDMissionEmail> entries; std::vector<CDMissionEmail> entries;
public: public:
CDMissionEmailTable(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDMissionEmail> Query(std::function<bool(CDMissionEmail)> predicate); std::vector<CDMissionEmail> Query(std::function<bool(CDMissionEmail)> predicate);
std::vector<CDMissionEmail> GetEntries(void) const; const std::vector<CDMissionEmail>& GetEntries() const;
}; };

View File

@@ -1,7 +1,6 @@
#include "CDMissionNPCComponentTable.h" #include "CDMissionNPCComponentTable.h"
//! Constructor void CDMissionNPCComponentTable::LoadValuesFromDatabase() {
CDMissionNPCComponentTable::CDMissionNPCComponentTable(void) {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
@@ -45,7 +44,7 @@ std::vector<CDMissionNPCComponent> CDMissionNPCComponentTable::Query(std::functi
} }
//! Gets all the entries in the table //! Gets all the entries in the table
std::vector<CDMissionNPCComponent> CDMissionNPCComponentTable::GetEntries(void) const { const std::vector<CDMissionNPCComponent>& CDMissionNPCComponentTable::GetEntries() const {
return this->entries; return this->entries;
} }

View File

@@ -16,12 +16,12 @@ private:
std::vector<CDMissionNPCComponent> entries; std::vector<CDMissionNPCComponent> entries;
public: public:
CDMissionNPCComponentTable(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDMissionNPCComponent> Query(std::function<bool(CDMissionNPCComponent)> predicate); std::vector<CDMissionNPCComponent> Query(std::function<bool(CDMissionNPCComponent)> predicate);
// Gets all the entries in the table // Gets all the entries in the table
std::vector<CDMissionNPCComponent> GetEntries(void) const; const std::vector<CDMissionNPCComponent>& GetEntries() const;
}; };

View File

@@ -1,7 +1,6 @@
#include "CDMissionTasksTable.h" #include "CDMissionTasksTable.h"
//! Constructor void CDMissionTasksTable::LoadValuesFromDatabase() {
CDMissionTasksTable::CDMissionTasksTable(void) {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
@@ -56,16 +55,14 @@ std::vector<CDMissionTasks*> CDMissionTasksTable::GetByMissionID(uint32_t missio
for (auto& entry : this->entries) { for (auto& entry : this->entries) {
if (entry.id == missionID) { if (entry.id == missionID) {
CDMissionTasks* task = const_cast<CDMissionTasks*>(&entry); tasks.push_back(&entry);
tasks.push_back(task);
} }
} }
return tasks; return tasks;
} }
const std::vector<CDMissionTasks>& CDMissionTasksTable::GetEntries(void) const { const std::vector<CDMissionTasks>& CDMissionTasksTable::GetEntries() const {
return this->entries; return this->entries;
} }

View File

@@ -24,12 +24,12 @@ private:
std::vector<CDMissionTasks> entries; std::vector<CDMissionTasks> entries;
public: public:
CDMissionTasksTable(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDMissionTasks> Query(std::function<bool(CDMissionTasks)> predicate); std::vector<CDMissionTasks> Query(std::function<bool(CDMissionTasks)> predicate);
std::vector<CDMissionTasks*> GetByMissionID(uint32_t missionID); std::vector<CDMissionTasks*> GetByMissionID(uint32_t missionID);
const std::vector<CDMissionTasks>& GetEntries(void) const; const std::vector<CDMissionTasks>& GetEntries() const;
}; };

View File

@@ -2,8 +2,7 @@
CDMissions CDMissionsTable::Default = {}; CDMissions CDMissionsTable::Default = {};
//! Constructor void CDMissionsTable::LoadValuesFromDatabase() {
CDMissionsTable::CDMissionsTable(void) {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;

View File

@@ -65,12 +65,12 @@ private:
std::vector<CDMissions> entries; std::vector<CDMissions> entries;
public: public:
CDMissionsTable(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDMissions> Query(std::function<bool(CDMissions)> predicate); std::vector<CDMissions> Query(std::function<bool(CDMissions)> predicate);
// Gets all the entries in the table // Gets all the entries in the table
const std::vector<CDMissions>& GetEntries(void) const; const std::vector<CDMissions>& GetEntries() const;
const CDMissions* GetPtrByMissionID(uint32_t missionID) const; const CDMissions* GetPtrByMissionID(uint32_t missionID) const;

View File

@@ -1,7 +1,6 @@
#include "CDMovementAIComponentTable.h" #include "CDMovementAIComponentTable.h"
//! Constructor void CDMovementAIComponentTable::LoadValuesFromDatabase() {
CDMovementAIComponentTable::CDMovementAIComponentTable(void) {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
@@ -37,7 +36,6 @@ CDMovementAIComponentTable::CDMovementAIComponentTable(void) {
tableData.finalize(); tableData.finalize();
} }
//! Queries the table with a custom "where" clause
std::vector<CDMovementAIComponent> CDMovementAIComponentTable::Query(std::function<bool(CDMovementAIComponent)> predicate) { std::vector<CDMovementAIComponent> CDMovementAIComponentTable::Query(std::function<bool(CDMovementAIComponent)> predicate) {
std::vector<CDMovementAIComponent> data = cpplinq::from(this->entries) std::vector<CDMovementAIComponent> data = cpplinq::from(this->entries)
@@ -47,8 +45,7 @@ std::vector<CDMovementAIComponent> CDMovementAIComponentTable::Query(std::functi
return data; return data;
} }
//! Gets all the entries in the table const std::vector<CDMovementAIComponent>& CDMovementAIComponentTable::GetEntries(void) const {
std::vector<CDMovementAIComponent> CDMovementAIComponentTable::GetEntries(void) const {
return this->entries; return this->entries;
} }

View File

@@ -19,10 +19,10 @@ private:
std::vector<CDMovementAIComponent> entries; std::vector<CDMovementAIComponent> entries;
public: public:
CDMovementAIComponentTable(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDMovementAIComponent> Query(std::function<bool(CDMovementAIComponent)> predicate); std::vector<CDMovementAIComponent> Query(std::function<bool(CDMovementAIComponent)> predicate);
// Gets all the entries in the table // Gets all the entries in the table
std::vector<CDMovementAIComponent> GetEntries(void) const; const std::vector<CDMovementAIComponent>& GetEntries() const;
}; };

View File

@@ -1,7 +1,6 @@
#include "CDObjectSkillsTable.h" #include "CDObjectSkillsTable.h"
//! Constructor void CDObjectSkillsTable::LoadValuesFromDatabase() {
CDObjectSkillsTable::CDObjectSkillsTable(void) {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
@@ -33,7 +32,6 @@ CDObjectSkillsTable::CDObjectSkillsTable(void) {
tableData.finalize(); tableData.finalize();
} }
//! Queries the table with a custom "where" clause
std::vector<CDObjectSkills> CDObjectSkillsTable::Query(std::function<bool(CDObjectSkills)> predicate) { std::vector<CDObjectSkills> CDObjectSkillsTable::Query(std::function<bool(CDObjectSkills)> predicate) {
std::vector<CDObjectSkills> data = cpplinq::from(this->entries) std::vector<CDObjectSkills> data = cpplinq::from(this->entries)
@@ -43,7 +41,6 @@ std::vector<CDObjectSkills> CDObjectSkillsTable::Query(std::function<bool(CDObje
return data; return data;
} }
//! Gets all the entries in the table const std::vector<CDObjectSkills>& CDObjectSkillsTable::GetEntries() const {
std::vector<CDObjectSkills> CDObjectSkillsTable::GetEntries(void) const {
return this->entries; return this->entries;
} }

View File

@@ -15,12 +15,12 @@ private:
std::vector<CDObjectSkills> entries; std::vector<CDObjectSkills> entries;
public: public:
CDObjectSkillsTable(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDObjectSkills> Query(std::function<bool(CDObjectSkills)> predicate); std::vector<CDObjectSkills> Query(std::function<bool(CDObjectSkills)> predicate);
// Gets all the entries in the table // Gets all the entries in the table
std::vector<CDObjectSkills> GetEntries(void) const; const std::vector<CDObjectSkills>& GetEntries() const;
}; };

View File

@@ -1,8 +1,6 @@
#include "CDObjectsTable.h" #include "CDObjectsTable.h"
//! Constructor void CDObjectsTable::LoadValuesFromDatabase() {
CDObjectsTable::CDObjectsTable(void) {
#ifdef CDCLIENT_CACHE_ALL
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM Objects"); auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM Objects");
@@ -20,25 +18,24 @@ CDObjectsTable::CDObjectsTable(void) {
CDObjects entry; CDObjects entry;
entry.id = tableData.getIntField("id", -1); entry.id = tableData.getIntField("id", -1);
entry.name = tableData.getStringField("name", ""); entry.name = tableData.getStringField("name", "");
entry.placeable = tableData.getIntField("placeable", -1); UNUSED_COLUMN(entry.placeable = tableData.getIntField("placeable", -1);)
entry.type = tableData.getStringField("type", ""); entry.type = tableData.getStringField("type", "");
entry.description = tableData.getStringField("description", ""); UNUSED_COLUMN(entry.description = tableData.getStringField("description", "");)
entry.localize = tableData.getIntField("localize", -1); UNUSED_COLUMN(entry.localize = tableData.getIntField("localize", -1);)
entry.npcTemplateID = tableData.getIntField("npcTemplateID", -1); UNUSED_COLUMN(entry.npcTemplateID = tableData.getIntField("npcTemplateID", -1);)
entry.displayName = tableData.getStringField("displayName", ""); UNUSED_COLUMN(entry.displayName = tableData.getStringField("displayName", "");)
entry.interactionDistance = tableData.getFloatField("interactionDistance", -1.0f); entry.interactionDistance = tableData.getFloatField("interactionDistance", -1.0f);
entry.nametag = tableData.getIntField("nametag", -1); UNUSED_COLUMN(entry.nametag = tableData.getIntField("nametag", -1);)
entry._internalNotes = tableData.getStringField("_internalNotes", ""); UNUSED_COLUMN(entry._internalNotes = tableData.getStringField("_internalNotes", "");)
entry.locStatus = tableData.getIntField("locStatus", -1); UNUSED_COLUMN(entry.locStatus = tableData.getIntField("locStatus", -1);)
entry.gate_version = tableData.getStringField("gate_version", ""); UNUSED_COLUMN(entry.gate_version = tableData.getStringField("gate_version", "");)
entry.HQ_valid = tableData.getIntField("HQ_valid", -1); UNUSED_COLUMN(entry.HQ_valid = tableData.getIntField("HQ_valid", -1);)
this->entries.insert(std::make_pair(entry.id, entry)); this->entries.insert(std::make_pair(entry.id, entry));
tableData.nextRow(); tableData.nextRow();
} }
tableData.finalize(); tableData.finalize();
#endif
m_default.id = 0; m_default.id = 0;
} }
@@ -49,12 +46,10 @@ const CDObjects& CDObjectsTable::GetByID(unsigned int LOT) {
return it->second; return it->second;
} }
#ifndef CDCLIENT_CACHE_ALL auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM Objects WHERE id = ?;");
std::stringstream query; query.bind(1, static_cast<int32_t>(LOT));
query << "SELECT * FROM Objects WHERE id = " << std::to_string(LOT); auto tableData = query.execQuery();
auto tableData = CDClientDatabase::ExecuteQuery(query.str());
if (tableData.eof()) { if (tableData.eof()) {
this->entries.insert(std::make_pair(LOT, m_default)); this->entries.insert(std::make_pair(LOT, m_default));
return m_default; return m_default;
@@ -88,7 +83,6 @@ const CDObjects& CDObjectsTable::GetByID(unsigned int LOT) {
if (it2 != entries.end()) { if (it2 != entries.end()) {
return it2->second; return it2->second;
} }
#endif
return m_default; return m_default;
} }

View File

@@ -26,7 +26,7 @@ private:
CDObjects m_default; CDObjects m_default;
public: public:
CDObjectsTable(); void LoadValuesFromDatabase();
// Gets an entry by ID // Gets an entry by ID
const CDObjects& GetByID(unsigned int LOT); const CDObjects& GetByID(unsigned int LOT);
}; };

View File

@@ -1,7 +1,6 @@
#include "CDPackageComponentTable.h" #include "CDPackageComponentTable.h"
//! Constructor void CDPackageComponentTable::LoadValuesFromDatabase() {
CDPackageComponentTable::CDPackageComponentTable(void) {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
@@ -43,7 +42,7 @@ std::vector<CDPackageComponent> CDPackageComponentTable::Query(std::function<boo
} }
//! Gets all the entries in the table //! Gets all the entries in the table
std::vector<CDPackageComponent> CDPackageComponentTable::GetEntries(void) const { const std::vector<CDPackageComponent>& CDPackageComponentTable::GetEntries() const {
return this->entries; return this->entries;
} }

View File

@@ -14,9 +14,9 @@ private:
std::vector<CDPackageComponent> entries; std::vector<CDPackageComponent> entries;
public: public:
CDPackageComponentTable(void); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDPackageComponent> Query(std::function<bool(CDPackageComponent)> predicate); std::vector<CDPackageComponent> Query(std::function<bool(CDPackageComponent)> predicate);
std::vector<CDPackageComponent> GetEntries(void) const; const std::vector<CDPackageComponent>& GetEntries() const;
}; };

View File

@@ -1,46 +1,35 @@
#include "CDPhysicsComponentTable.h" #include "CDPhysicsComponentTable.h"
CDPhysicsComponentTable::CDPhysicsComponentTable(void) { void CDPhysicsComponentTable::LoadValuesFromDatabase() {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PhysicsComponent"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PhysicsComponent");
while (!tableData.eof()) { while (!tableData.eof()) {
CDPhysicsComponent* entry = new CDPhysicsComponent(); CDPhysicsComponent entry;
entry->id = tableData.getIntField("id", -1); entry.id = tableData.getIntField("id", -1);
entry->bStatic = tableData.getIntField("static", -1) != 0; entry.bStatic = tableData.getIntField("static", -1) != 0;
entry->physicsAsset = tableData.getStringField("physics_asset", ""); entry.physicsAsset = tableData.getStringField("physics_asset", "");
UNUSED(entry->jump = tableData.getIntField("jump", -1) != 0); UNUSED(entry->jump = tableData.getIntField("jump", -1) != 0);
UNUSED(entry->doublejump = tableData.getIntField("doublejump", -1) != 0); UNUSED(entry->doublejump = tableData.getIntField("doublejump", -1) != 0);
entry->speed = tableData.getFloatField("speed", -1); entry.speed = tableData.getFloatField("speed", -1);
UNUSED(entry->rotSpeed = tableData.getFloatField("rotSpeed", -1)); UNUSED(entry->rotSpeed = tableData.getFloatField("rotSpeed", -1));
entry->playerHeight = tableData.getFloatField("playerHeight"); entry.playerHeight = tableData.getFloatField("playerHeight");
entry->playerRadius = tableData.getFloatField("playerRadius"); entry.playerRadius = tableData.getFloatField("playerRadius");
entry->pcShapeType = tableData.getIntField("pcShapeType"); entry.pcShapeType = tableData.getIntField("pcShapeType");
entry->collisionGroup = tableData.getIntField("collisionGroup"); entry.collisionGroup = tableData.getIntField("collisionGroup");
UNUSED(entry->airSpeed = tableData.getFloatField("airSpeed")); UNUSED(entry->airSpeed = tableData.getFloatField("airSpeed"));
UNUSED(entry->boundaryAsset = tableData.getStringField("boundaryAsset")); UNUSED(entry->boundaryAsset = tableData.getStringField("boundaryAsset"));
UNUSED(entry->jumpAirSpeed = tableData.getFloatField("jumpAirSpeed")); UNUSED(entry->jumpAirSpeed = tableData.getFloatField("jumpAirSpeed"));
UNUSED(entry->friction = tableData.getFloatField("friction")); UNUSED(entry->friction = tableData.getFloatField("friction"));
UNUSED(entry->gravityVolumeAsset = tableData.getStringField("gravityVolumeAsset")); UNUSED(entry->gravityVolumeAsset = tableData.getStringField("gravityVolumeAsset"));
m_entries.insert(std::make_pair(entry->id, entry)); m_entries.insert(std::make_pair(entry.id, entry));
tableData.nextRow(); tableData.nextRow();
} }
tableData.finalize(); tableData.finalize();
} }
CDPhysicsComponentTable::~CDPhysicsComponentTable() {
for (auto e : m_entries) {
if (e.second) delete e.second;
}
m_entries.clear();
}
CDPhysicsComponent* CDPhysicsComponentTable::GetByID(unsigned int componentID) { CDPhysicsComponent* CDPhysicsComponentTable::GetByID(unsigned int componentID) {
for (auto e : m_entries) { auto itr = m_entries.find(componentID);
if (e.first == componentID) return e.second; return itr != m_entries.end() ? &itr->second : nullptr;
}
return nullptr;
} }

View File

@@ -23,12 +23,11 @@ struct CDPhysicsComponent {
class CDPhysicsComponentTable : public CDTable<CDPhysicsComponentTable> { class CDPhysicsComponentTable : public CDTable<CDPhysicsComponentTable> {
public: public:
CDPhysicsComponentTable(); void LoadValuesFromDatabase();
~CDPhysicsComponentTable();
static const std::string GetTableName() { return "PhysicsComponent"; }; static const std::string GetTableName() { return "PhysicsComponent"; };
CDPhysicsComponent* GetByID(unsigned int componentID); CDPhysicsComponent* GetByID(unsigned int componentID);
private: private:
std::map<unsigned int, CDPhysicsComponent*> m_entries; std::map<unsigned int, CDPhysicsComponent> m_entries;
}; };

View File

@@ -1,7 +1,6 @@
#include "CDPropertyEntranceComponentTable.h" #include "CDPropertyEntranceComponentTable.h"
CDPropertyEntranceComponentTable::CDPropertyEntranceComponentTable() { void CDPropertyEntranceComponentTable::LoadValuesFromDatabase() {
// First, get the size of the table // First, get the size of the table
size_t size = 0; size_t size = 0;

View File

@@ -11,12 +11,12 @@ struct CDPropertyEntranceComponent {
class CDPropertyEntranceComponentTable : public CDTable<CDPropertyEntranceComponentTable> { class CDPropertyEntranceComponentTable : public CDTable<CDPropertyEntranceComponentTable> {
public: public:
CDPropertyEntranceComponentTable(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
CDPropertyEntranceComponent GetByID(uint32_t id); CDPropertyEntranceComponent GetByID(uint32_t id);
// Gets all the entries in the table // Gets all the entries in the table
[[nodiscard]] std::vector<CDPropertyEntranceComponent> GetEntries() const { return entries; } [[nodiscard]] const std::vector<CDPropertyEntranceComponent>& GetEntries() const { return entries; }
private: private:
std::vector<CDPropertyEntranceComponent> entries{}; std::vector<CDPropertyEntranceComponent> entries{};
CDPropertyEntranceComponent defaultEntry{}; CDPropertyEntranceComponent defaultEntry{};

View File

@@ -1,6 +1,6 @@
#include "CDPropertyTemplateTable.h" #include "CDPropertyTemplateTable.h"
CDPropertyTemplateTable::CDPropertyTemplateTable() { void CDPropertyTemplateTable::LoadValuesFromDatabase() {
// First, get the size of the table // First, get the size of the table
size_t size = 0; size_t size = 0;

View File

@@ -10,7 +10,7 @@ struct CDPropertyTemplate {
class CDPropertyTemplateTable : public CDTable<CDPropertyTemplateTable> { class CDPropertyTemplateTable : public CDTable<CDPropertyTemplateTable> {
public: public:
CDPropertyTemplateTable(); void LoadValuesFromDatabase();
static const std::string GetTableName() { return "PropertyTemplate"; }; static const std::string GetTableName() { return "PropertyTemplate"; };
CDPropertyTemplate GetByMapID(uint32_t mapID); CDPropertyTemplate GetByMapID(uint32_t mapID);

View File

@@ -1,7 +1,6 @@
#include "CDProximityMonitorComponentTable.h" #include "CDProximityMonitorComponentTable.h"
//! Constructor void CDProximityMonitorComponentTable::LoadValuesFromDatabase() {
CDProximityMonitorComponentTable::CDProximityMonitorComponentTable(void) {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
@@ -33,7 +32,6 @@ CDProximityMonitorComponentTable::CDProximityMonitorComponentTable(void) {
tableData.finalize(); tableData.finalize();
} }
//! Queries the table with a custom "where" clause
std::vector<CDProximityMonitorComponent> CDProximityMonitorComponentTable::Query(std::function<bool(CDProximityMonitorComponent)> predicate) { std::vector<CDProximityMonitorComponent> CDProximityMonitorComponentTable::Query(std::function<bool(CDProximityMonitorComponent)> predicate) {
std::vector<CDProximityMonitorComponent> data = cpplinq::from(this->entries) std::vector<CDProximityMonitorComponent> data = cpplinq::from(this->entries)
@@ -43,8 +41,7 @@ std::vector<CDProximityMonitorComponent> CDProximityMonitorComponentTable::Query
return data; return data;
} }
//! Gets all the entries in the table const std::vector<CDProximityMonitorComponent>& CDProximityMonitorComponentTable::GetEntries() const {
std::vector<CDProximityMonitorComponent> CDProximityMonitorComponentTable::GetEntries(void) const {
return this->entries; return this->entries;
} }

View File

@@ -15,9 +15,9 @@ private:
std::vector<CDProximityMonitorComponent> entries; std::vector<CDProximityMonitorComponent> entries;
public: public:
CDProximityMonitorComponentTable(void); void LoadValuesFromDatabase();
//! Queries the table with a custom "where" clause //! Queries the table with a custom "where" clause
std::vector<CDProximityMonitorComponent> Query(std::function<bool(CDProximityMonitorComponent)> predicate); std::vector<CDProximityMonitorComponent> Query(std::function<bool(CDProximityMonitorComponent)> predicate);
std::vector<CDProximityMonitorComponent> GetEntries(void) const; const std::vector<CDProximityMonitorComponent>& GetEntries() const;
}; };

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