Compare commits

...

1420 Commits
v1.0 ... v2.1.0

Author SHA1 Message Date
0bc12141c3 chore: default size to 33 on LU(W)Strings since that's the most common lenght (#1410)
Was doing this on other places, but not the main one
2024-01-12 14:23:44 -06:00
David Markowitz
8b6fb8fb44 Add ghost component (#1409)
will be used to migrate other Player functionality in a future PR.

Tested that I can login still.
2024-01-12 13:18:28 -06:00
David Markowitz
929d029f12 chore: Simplify and move Player functionality to relevant component (#1408)
* Moving and organizing Player code

- Move code to CharacterComponent
- Remove extraneous interfaces
- Simplify some code greatly
- Change some types to return and take in const ref (only structs larger than 8 bytes benefit from this change.)
- Update code to use CharacterComponent for sending to zone instead of Player*.

* Moving and organizing Player code

- Move code to CharacterComponent
- Remove extraneous interfaces
- Simplify some code greatly
- Change some types to return and take in const ref (only structs larger than 8 bytes benefit from this change.)
- Update code to use CharacterComponent for sending to zone instead of Player*.
- Remove static storage container (static containers can be destroyed before exit/terminate handler executes)

* remove player cast

* Remove extra includes
2024-01-12 11:39:51 -06:00
David Markowitz
66cc582a9a chore: update noninformative comments to be informative (#1407)
* better comments

* more comments
2024-01-10 20:57:41 -08:00
David Markowitz
e0ddbce8e7 chore: remove non cstdint integer types in client ORM (#1405) 2024-01-08 23:54:14 -08:00
jadebenn
4a50c60559 chore: Assorted pet improvements (#1402)
* Assorted pet improvements

* remove unecessary include

* updates to address some feedback

* fixed database code for testing

* Removed reference member (for now)

* Removed cmake flag
2024-01-08 15:32:09 -08:00
Daniel Seiler
fbdcc17bb5 fix: Docker Compose README (#1403)
* fix: Docker Compose README

* fix: add password requiremnts hint

* fix: note on sudo / docker compose

* fix: add note on UGCUSE3DSERVICES

* fix: reorder

* fix: duplicate word

* fix: move broken line

* fix(compose): enable USER_ENABLE_REGISTER by default
2024-01-08 09:13:28 -06:00
David Markowitz
e4469f997e fix: activity id not using overridden id (#1400)
* patch activity id not using overridden id

Update ActivityComponent.h

* Update ActivityComponent.cpp

* Update ActivityComponent.cpp
2024-01-07 07:43:53 -06:00
dbe4a0ced3 chore: continue work on removing raw packet reading (#1404)
* chore: continue work on removing raw packet reading
tested that logging in, deleted a char, renaming a char, and transfeering to a zone all work still

* Address Feedback
2024-01-07 02:02:27 -06:00
David Markowitz
b683413a60 Remove deps from dNet (#1401) 2024-01-07 08:05:57 +01:00
David Markowitz
14c20fbd62 change timers to not use ptrs (#1399)
add comments as to why logic may seem confusing.
2024-01-06 03:45:23 -06:00
325598cd99 feat: fully reading auth packets and use stamps (#1398)
* feat: fully reading auth packets and use stamps

* fix the stupid define

* Address feedback

* no more Stamp(...)
2024-01-06 02:16:10 -06:00
David Markowitz
0c104e819d chore: Consolidate logger setup and add better handling of packets (#1389)
* Logger to Server class

Dont handle master packets from our clients

* move to namespace

Revert "remove extra headers"

This reverts commit ac7b901ece22165cdb0f38fca4be7d8fdf004de8.

remove extra headers

no changes otherwise.

* Merge branch 'main' into server_consolidation_of_work

* Update WorldServer.cpp

* fix submodule version

---------

Co-authored-by: Aaron Kimbre <aronwk.aaron@gmail.com>
2024-01-05 23:32:09 -06:00
David Markowitz
0dc6763a3c chore: Remove pointer management in PlayerContainer (#1397)
* const

use cbegin, remove null checks

they are references now, they cant be null themselves

Change to reference instead of ptr

Remove getter

const

* allow duplicate request

without the reply you apparently need to re-log for some reason.

Update PlayerContainer.cpp
2024-01-05 22:42:30 -06:00
jadebenn
440dc8b88f replace macro with anonymous namespace function (#1394) 2024-01-05 18:55:42 -06:00
Demetri Van Sickle
3deec6499d Update Commands.md (#1396)
> Added `spawngroup` command
> Recorded some commands that were out of order from least to greatest GM level
> Filled in missing admin levels
> Added alt spellings of commands
> Fixed incorrect GM level of `fly` command from 4 to 6
2024-01-05 18:49:56 -06:00
David Markowitz
15a461d857 fix crash (#1395)
Update SlashCommandHandler.cpp
2024-01-05 18:49:21 -06:00
David Markowitz
2804dc3ec2 fix: make include paths consistent (#1390)
* fix: bad header includes

tests pass

* fix-up more include paths
2024-01-05 06:33:52 -06:00
David Markowitz
870b56fe02 chore: cleanup objectIdManager overloading and classes (#1391)
* objectIdManager fixes

* Remove debug log
2024-01-05 06:31:22 -06:00
Gie "Max" Vanommeslaeghe
66ac5a1b7a Merge pull request #1388 from DarkflameUniverse/fix--make-all-settings-have-sane-defaults-where-possible
fix: don't crash if some configs values aren't present
2024-01-05 11:34:50 +01:00
321d354e96 fix: don't crash if some configs aren't present
remove not starting if ini's aren't present since everything can run from env vars now
2024-01-04 18:21:03 -06:00
72b69c7899 fix: dont crash if resServer doesn't exist (#1386)
and try to make it as well
2024-01-03 22:18:27 -06:00
Daniel Seiler
d283bbd1c4 fix: split apart big Cmake libraries (#1381)
* fix: split apart big Cmake libraries

* fix: formatting

* fix: newline

* fix: add quotes
2024-01-03 18:41:46 -06:00
David Markowitz
10baa98f00 Update build-and-push-docker.yml (#1385)
change name to be caps like the other
2024-01-03 14:41:35 +01:00
David Markowitz
c7c84c21ef feat: partially functioning property behavior ui (no saving or loading yet) (#1384)
* Add addstrip handling

add SendBehaviorBlocksToClient serialization
add id generation and auto updating
add behaviorlisttoclient serialization

* fix crash

happened if you added state 0 and 6 and nothing in between

* Section off code

Use proper encapsulation to hide code away and only let specific objects do certain jobs.

* Organize serialization

Section off into operational chunks
Write data at the level most appropriate

* Remove and simplify BlockDefinitions

Remove pointer usage for BlockDefinitions and move to optional.

* ControlBehaviors: Add addaction handling

* re-organization

remove const from return value
change to int from uint
use generic methods to reduce code clutter

* add strip ui position handling

* add split strip functionality

* fix issues

fix an issue where if you were on an empty state, the server would allow you to remain on that state
fix an issue where the ui would not open on the previously opened state
fix an issue where deleting strips in order caused the wrong strips to be deleted

* update how you remove behaviors from models

* Add remove actions and rename

* migrate actions

* update action and rearrange strip

* merge strips

* add and move to inventory

* Remove dead code

* simplify code

* nits and move finish MoveToInventory

constify serialize

further include path fixes

use const, comments

fix amf message

Update ModelComponent.cpp

replace operator subscript with at

* Update ModelComponent.cpp

* Update MigrateActionsMessage.h

* const

* Move to separate translation units

* include amf3

its precompiled, but just in case
2024-01-03 07:34:38 -06:00
David Markowitz
09fb1dfff9 Update docker-compose.yml (#1383) 2024-01-03 06:00:49 -06:00
9116317834 fix: improve our docker config (#1373)
* greatly simplify docker

* back to gcc since I can't the libs to load properly

* fix typo
add set -e to entrypoint
better copy of entrypoint.sh and use proper entrypoint

* use debian instead of gcc for runtime
comment and organize it a bit
drop gcc to 12 since we are using debian 12 as well

* explicitly include mariadb libs

* Make the server not crash in the case we are using only env-vars
make the dockerfile have configs in the expected location incase of bypassing entrypoint.sh

* remove unneede var from example, since it's in the container now

* coments to dockerfile

* Revert master server changes

* Resolve conflicting port options between chat, master, and world
move chat_server_port to shared since it's used by world and chat

* Don't error if file does not exists when updating a config option
move update before and use bin dir var
2024-01-03 02:36:17 -06:00
David Markowitz
a84ca1f00d crash and log fix (#1382) 2024-01-03 06:52:11 +00:00
David Markowitz
bb79528c0e fix: nullptr access for logger in master (#1380)
* fix nullptr access for logger

* fix nullptr access for logger

fix no save on crash

* Update MasterServer.cpp
2024-01-02 18:28:17 -06:00
David Markowitz
b1134b340f Add config update function (#1379)
Update CMakeLists.txt

FINALLY

dont ignore cmake module directory

move to separate file

very cool feature
tested that this still works

Co-authored-by: Aaron Kimbrell <aronwk.aaron@gmail.com>
2024-01-02 18:25:57 -06:00
David Markowitz
1941679d27 feat: Bump standard to 20 (#1376)
* Bump to 20

* fix warnings and errors

* thanks RakNet
2024-01-02 07:53:00 +00:00
Daniel Seiler
85672e060a fix: signal handling (#1375)
* fix: signal handling

* fix: flush WorldServer logger before main loop

* fix: consolidate signal code
2024-01-01 21:50:00 -06:00
Daniel Seiler
18feea5fed fix: optional party phrases (#1377)
* fix: optional party phrases

Don't return early if there are no party phrases

* Update VanityUtilities.cpp
2024-01-01 17:08:38 -06:00
David Markowitz
e54faa3820 chore: organize build flags (#1371)
* chore: organize build flags

* Remove ambiguous include path

Don't be default incluyde bcrypt so you need to specify the folder.  Allows pre-processor to find the correct file.

* Revert settings

* working

f
2023-12-31 00:26:49 -06:00
David Markowitz
4ecb6ae30e fix: joining lobby twice (#1374) 2023-12-31 00:14:58 -06:00
Gie "Max" Vanommeslaeghe
c708246f73 Merge pull request #1247 from maxdelayer/main
Fix edge case where leaderboard viewing would cause unhandled exception
2023-12-31 00:43:37 +01:00
Gie "Max" Vanommeslaeghe
295ba628c2 Merge pull request #1372 from DarkflameUniverse/feature/update-connector
fix: bump connector version
2023-12-31 00:32:52 +01:00
Xiphoseer
d8f74f008f fix: bump connector version 2023-12-31 00:22:39 +01:00
Daniel Seiler
42a71bbeab feat: add DLU_CONFIG_DIR env var (#1370)
* feat: add DLU_CONFIG_DIR env var

* fix: PascalCase
2023-12-30 07:07:49 -06:00
Daniel Seiler
98d2f25af2 feat: get & print std::current_exception (#1366) 2023-12-30 08:04:26 +01:00
Daniel Seiler
dd9d94f75f feat: allow env var override for game config (#1367) 2023-12-30 08:04:09 +01:00
Daniel Seiler
f08df25085 feat: split out system() calls from the rest of MasterServer (#1368) 2023-12-30 08:00:43 +01:00
1bdce8384f fix: LUP Exhibit component type and use delta compression on serialization (#1365)
* fix: component type and use delta compression on serialization

* sorry jett, emo made me do it
2023-12-28 22:24:45 -06:00
15954413ae chore: rename rebuild to quickbuild (#1364)
* rename rebuild to quickbuild

* fix includes
2023-12-28 22:24:30 -06:00
fddf99946f chore: make scripted activity derived from activity (#1363)
* chore: make scripted activity derived from activity
this paves the way for other component being properly derived from the activity component

* use a dirty flag instead

* address feedback
2023-12-28 19:11:19 -06:00
jadebenn
ef6f2f133e chore: Eradicate C-style casts and further clean up some code (#1361)
* cast and code cleanup

* cast cleanup

* bug fixes and improvements

* no getBoolField method exists

* fixes

* unbroke sg cannon scoring

* removing comments

* Remove the c-style cast warning I added from CMakeLists now that they're gone (it triggers on 3rd party dependencies and slows down compilation)

* (Hopefully) fix MacOS compilation error

* partially-implemented feedback

* more updates to account for feedback

* change bool default

---------

Co-authored-by: jadebenn <jonahebenn@yahoo.com>
2023-12-27 22:18:20 -06:00
David Markowitz
46ac039a3b fix: mission offering (#1359)
fixes an issue where NPCs would offer the incorrect missions which caused odd blocks.  Consolidated logic for mission offering and removed redundant code.
2023-12-26 15:45:10 -08:00
David Markowitz
ffa2f9986c AssetManager: fix deleting no file (#1358) 2023-12-25 08:48:57 -06:00
Jett
d2d67384a7 fix: update trigger loading code after typo (#1357) 2023-12-24 21:45:27 +01:00
David Markowitz
dbf37c2d2b fix: more than 1 zone control object causing issues with scripted minigames (#1355)
* fix: more than 1 zone control object

Fixes an issue when players cannot load into Avant Gardens Survival and other script based minigames with more than 1 zone control object in the level files.  (why are there 26 zone control objects in BoNS and AGS)

* Update Level.cpp
2023-12-24 11:17:04 -06:00
David Markowitz
81dc4e2216 fix: remove cancelOnLogout handling (#1354) 2023-12-24 08:01:47 -06:00
jadebenn
6de224a2fa chore: miscellaneous code, formatting, and syntax cleanup (#1351)
* miscellaneous code, formatting, and syntax cleanup

* update

* update again

* updated to account for feedback
2023-12-23 18:11:00 -06:00
David Markowitz
5e9355b1ff fix: shooting gallery bugs (#1347)
fix: reset some more vars

Co-authored-by: Aaron Kimbre <aronwk.aaron@gmail.com>
2023-12-23 17:50:14 +00:00
David Markowitz
6b9798595e fix: leavezone command (#1345)
Players do not need access to leave Return to the Venture Explorer (rttve) via a slash command.  They can leave through the usual zone method.

Tested that you cannot leavezone in rttve
2023-12-23 11:28:32 -06:00
David Markowitz
e58218cfbc chore: Speed up and cleanup level and zone loading; Add safer asset buffer reading (#1314)
* Remove std::couts littered throughout the base

* working

End of optimizations for now

going faster

* Remove extraneous compare function

std::less<LWOSCENEID> already does this in a map.

* gaming

* Update Zone.cpp

* dlu is moving to bitbucket again

* Update Level.cpp

---------

Co-authored-by: Jettford <mrjettbradford@gmail.com>
2023-12-23 11:24:16 -06:00
jadebenn
fcf4d6c6fa feat: Improve console output to show packet enum names (magic_enum) (#1344)
* add enum stringification functionality from third party source

* squashed commit

* Macros: Add test and improve speed

Space macros out
utilize cache locality
ensure no lost functionality

* moved stringify code to dCommon

* Rename #defines in stringify enum tests

* Revert "moved stringify code to dCommon"

This reverts commit 33fa5f8d2f.

* improve macro functionality

change function handle

formatting and function definition tweaks

* typo fixes

* moved code to dCommon/dEnums and tests to dCommonTests/dEnumsTests

* initial magic_enums alternate implementation of enum stringification

* deleted unused tests

* reverted compile flag oopsy and fixed output types

* fixed testing suite

* test formatting improvement

* formatting again :(

* added gm string to "aborting gm!" message

* Push my suggestion for CI tests.

* updated magic enum test

* fix test variable type

* added gm test

* making sure magic_enum is on a release branch

* tidying up console outputs

* re-implemented enum array access for performance

* now it is bugged :(

* nvm, working

* helping out the snowflake compilers

* changed return type too

* optimization too

* formatting too I guess because why not

* being even more painfully specific

* Update WorldServer.cpp to match emo's feedback

* Update MagicEnumTests.cpp to use srand(time(NULL))

* Update eGameMessageType.h - formatting

* Trying to fix the crash but can't actually compile the code to check on my own rn

* Update WorldServer.cpp - third try at this

* Update MagicEnumTests.cpp - use better macro definitions

* Update MagicEnumTests.cpp - c string comparison fix

* addressing all but the cmake feedback

* fixed cmake to the best of my very limited ability

* added tests to verify magic enum arrays are pre-sorted

* updated

---------

Co-authored-by: David Markowitz <EmosewaMC@gmail.com>
Co-authored-by: Jettford <mrjettbradford@gmail.com>
2023-12-23 10:51:59 -06:00
David Markowitz
c1e8546d48 fix: add Nexus Tower missing scripts (#1349)
add final missing scripts for nt

also fix the turnin for the breadcrumb missions not showing the completion window.

Fix another missing script

Add another script

fix include guards

Fix dirt clouds not appearing on mission accept
2023-12-22 23:53:21 -08:00
jadebenn
c07c909a57 fix: Character access after deletion (#1348)
* assorted skill debug plus crash fix

* removed uncleaned debug
2023-12-21 22:12:52 -06:00
42ffd00478 feat: implement handling vendorStatusRequest (#1346)
this fixes the crafting menu on johny umami not being there on the initial internaction
2023-12-20 22:25:21 -06:00
jadebenn
799269c79e fix: Using 'leave-zone' in Return to the Venture Explorer allows players to return to the original Venture Explorer map (#1341)
* fixed VE zone bug and added config option to renable it

* add zero back to LWOMAPID initialization

* typo

* removed config option to enable bug
2023-12-20 15:12:01 -06:00
jadebenn
e2391665b9 imagination costs that equal your capacity no longer abort qbs (#1338) 2023-12-16 19:35:16 -06:00
David Markowitz
24c2361248 fix: achievements counting twice when accepted (#1337)
Tested that new achievements progress exactly once
Tested that already accepted achievements progress as expeected
Tested that tiered achievements only count the progress to the current tier and not the next one as well

Update MissionComponent.cpp
2023-12-16 12:27:14 -06:00
David Markowitz
511672c5cb fix: general crashes (#1336)
* Fix crashes

fix crash with chat filter
fix ldf_config being empty in database on windows debug

* WorldServer: Fix further crashes on windows

address multi threaded signal handling on worldservers
Remove iterator invalidation code in zone manager
2023-12-16 12:27:06 -06:00
Gie "Max" Vanommeslaeghe
c0b969e3f0 Merge pull request #1333 from DarkflameUniverse/chore-rename-zonecontrol-to-minigamecontrol
chore: rename zonecontrolcomp to minigamecontrolcomp
2023-12-06 14:39:21 +01:00
1f399a7277 chore: rename zonecontrolcomp to minigamecontrolcomp 2023-12-04 20:59:08 -06:00
3d85f6639e chore: rename VehiclePhysics to HavokVehiclePhysics (#1331)
since that is it's true name
and there's another VehiclePhysics component that is simply named that
2023-12-04 09:20:41 -06:00
David Markowitz
731b828c12 properties: fix visiting multiple owned by same person (#1325) 2023-12-01 10:13:01 -06:00
David Markowitz
eca87c7257 fix: Buff FX not playing and general BuffComponent improvements (#1296)
* fix: Buff FX not playing

Fixes an issue where buff effects would not play at all.

Tested that frakjaw and maelstrom dagger now play their respective effects when you are effected by them

fix: buffs general improvements

add new arguments

* Remove duplicated code

* fix times and remove buff
2023-12-01 10:12:48 -06:00
David Markowitz
0b9dbaedbf Add HailStorms guide to README (#1329) 2023-11-30 16:11:45 -08:00
7de07a7722 fix: use defaults when getting variables for jetpack behavior (#1328)
Tested that the hover jetpack now works and that the normal jetpack still works
2023-11-30 02:21:18 -08:00
David Markowitz
62a1e135c3 Fix backwards name check (#1327)
Untested.  Fixes not being able to rename a character at character create
2023-11-29 00:25:06 -08:00
Gie "Max" Vanommeslaeghe
de0b560a8c Merge pull request #1326 from DarkflameUniverse/use-more-tacarc-vars
fix: tacarc not using offset or checking upper/lower bounds
2023-11-28 22:44:00 +01:00
e8a0f50ec9 use std::abs 2023-11-27 22:18:27 -06:00
b3564cb9ea fix: tacarc not using offset or checking upper/lower bounds 2023-11-27 22:16:31 -06:00
jadebenn
3df3552467 fix: respawn rotation (#1323)
* fixed respawn rotation

* even though the condensed calls work, splitting em
2023-11-26 14:30:39 -08:00
David Markowitz
a1f8ab763d Entity: Fix death behavior of 0 (#1319) 2023-11-25 22:50:28 -06:00
David Markowitz
0c32be01ba fix: nexus tower smashable (#1320) 2023-11-25 22:50:20 -06:00
David Markowitz
8a15906885 fix: Racing end of race leaderboards now work (#1317)
* Fix UB in remote input info

Yes i should have made this first
no this wouldnt have happened with rust

* fix end of race leaderboard

Tested that with two players, both players see the others time at the end of the race and all other metrics are shown correctly.

Technically the outBitStream->Write(static_cast<uint16_t>(m_RacingPlayers.size())); should only be written once but how we do it now it is written as we load players in and this is the cheap option compared to the number of bits we are supposed to waste at the end of races
2023-11-24 01:46:26 -08:00
Gie "Max" Vanommeslaeghe
af70f871cb Merge pull request #1307 from DarkflameUniverse/985
feat: Implement ignore list
2023-11-24 00:38:03 +01:00
David Markowitz
fd20baaf09 Fix UB in remote input info (#1316)
Yes i should have made this first
no this wouldnt have happened with rust
2023-11-23 05:48:06 -06:00
jadebenn
0217f88c44 pet emote fix (#1315) 2023-11-22 08:06:09 -06:00
David Markowitz
198b3371c5 chore: Update old character create code (#1291)
* create new character fixes

Don't use persistentIds, guarantee ids are unique by using do while to generate the id

* Update queries to actually use prep stmt

* Update UserManager.cpp

* Update UserManager.cpp
2023-11-21 18:14:30 -08:00
David Markowitz
4e5facd0c5 Merge branch 'main' into 985 2023-11-21 18:11:46 -08:00
David Markowitz
c931f5d456 Merge branch 'main' into 985 2023-11-21 18:10:45 -08:00
df83f0d847 feat: Reward codes (#1308)
* feat: reward codes
this is for giving rewards across characters as the did in live.
Tested that the default config works
Tested that all claim codes work
Tested that saving and loading claim codes work
Tested that mail sends correctly

* newlines

* include array

* delete cascade

* newline

* address feedback
2023-11-21 18:05:15 -08:00
David Markowitz
9c5388c70e feat: Add ability to toggle skipping of cinematics (#1312)
* Cinematics: Add ability to toggle skipping them

* Add docs

* Move sections
2023-11-21 18:04:44 -08:00
David Markowitz
1a199151da Remove std::couts littered throughout the base (#1313) 2023-11-21 18:04:23 -08:00
David Markowitz
98dc291b57 fix gating (#1306) 2023-11-19 12:01:34 -06:00
David Markowitz
1001e41528 simplify code path 2023-11-18 20:33:30 -08:00
David Markowitz
59bf91b14f fix up enum names
Update ChatIgnoreList.cpp

Add extra check for size on adding

Cant happen without hacks, but worth checking anyways

Update ChatIgnoreList.cpp
2023-11-18 20:21:13 -08:00
David Markowitz
50ad2a29ec Merge branch 'lol' into 985 2023-11-18 19:16:56 -08:00
David Markowitz
81b1b73f04 fix gating 2023-11-18 19:15:57 -08:00
David Markowitz
12ea2dfb2e Works for online players now 2023-11-18 18:37:06 -08:00
David Markowitz
d193fe61be Database working for ignores 2023-11-18 18:05:26 -08:00
David Markowitz
511407c8ea Removing ignore works now 2023-11-18 17:33:52 -08:00
David Markowitz
df3515f474 IgnoreList: Add and Populate fully working 2023-11-18 03:55:12 -08:00
8e84cafdfa feat: add configurable feature and versions (#1298)
* feat: add configurable feature and versions
to allow for easily swithing it out to enable features in the client for funsies
tested that this doesn't break anything and added test

* cleanup
2023-11-18 03:33:23 -06:00
David Markowitz
57e3a4f4ef fix: general issues with dismantling (#1304) 2023-11-18 01:15:47 -06:00
David Markowitz
98822d400f fix: ChatServer crash on startup (#1303) 2023-11-18 01:15:31 -06:00
David Markowitz
7f623d358c refactor: Database abstraction and organization of files (#1274)
* Database: Convert to proper namespace

* Database: Use base class and getter

* Database: Move files around

* Database: Add property Management query

Database: Move over user queries

Tested at gm 0 that pre-approved names are pre-approved, unapproved need moderator approval
deleting characters deletes the selcted one
refreshing the character page shows the last character you logged in as
tested all my characters show up when i login
tested that you can delete all 4 characters and the correct character is selected each time
tested renaming, approving names as gm0

Database: Add ugc model getter

Hey it works, look I got around the mariadb issue.

Database: Add queries

Database: consolidate name query

Database: Add friends list query

Update name of approved names query

Documentation

Database: Add name check

Database: Add BFF Query

Database: Move BFF Setter

Database: Move new friend query

Database: Add remove friend queries

Database: Add activity log

Database: Add ugc & prop content removal

Database: Add model update

Database: Add migration queries

Database: Add character and xml queries

Database: Add user queries

Untested, but compiling code

Need to test that new character names are properly assigned in the following scenarios
gm 0 and pre-approved name
gm 0 and unapproved name
gm 9 and pre-approved name
gm 9 and unapproved name

Database: constify function arguments

Database: Add pet queries

* Database: Move property model queries

Untested.  Need to test
placing a new model
moving existing one
removing ugc model
placing ugc model
moving ugc model(?)
changing privacy option variously
change description and name
approve property
can properly travel to property

* Property: Move stale reference deletion

* Database: Move performance update query

* Database: Add bug report query

* Database: Add cheat detection query

* Database: Add mail send query

* Untested code

need to test mailing from slash command, from all users of SendMail, getting bbb of a property and sending messages to bffs

* Update CDComponentsRegistryTable.h

Database: Rename and add further comments

Datavbase: Add comments

Add some comments

Build: Fix PCH directories

Database: Fix time

thanks apple

Database: Fix compiler warnings

Overload destructor
Define specialty for time_t
Use string instead of string_view for temp empty string

Update CDTable.h

Property: Update queries to use mapId

Database: Reorganize

Reorganize into CDClient folder and GameDatabase folder for clearer meanings and file structure

Folders: Rename to GameDatabase

MySQL: Remove MySQL Specifier from table

Database: Move Tables to Interfaces

Database: Reorder functions in header

Database: Simplify property queries

Database: Remove unused queries

Remove extra query definitions as well

Database: Consolidate User getters

Database: Comment logs

Update MySQLDatabase.cpp

Database: Use generic code

Playkey: Fix bad optional access

Database: Move stuff around

WorldServer: Update queries

Ugc reduced by many scopes
use new queries
very fast
tested that ugc still loads

Database: Add auth queries

I tested that only the correct password can sign into an account.
Tested that disabled playkeys do not allow the user to play the game

Database: Add donation query

Database: add objectId queries

Database: Add master queries

Database: Fix mis-named function

Database: Add slash command queries

Mail: Fix itemId type

CharFilter: Use new query

ObjectID: Remove duplicate code

SlashCommand: Update query with function

Database: Add mail queries

Ugc: Fix issues with saving models

Resolve large scope blocks as well

* Database: Add debug try catch rethrow macro

* General fixes

* fix play key not working

* Further fixes

---------

Co-authored-by: Aaron Kimbre <aronwk.aaron@gmail.com>
2023-11-17 18:47:18 -06:00
b68823b4cb fix: properly check friend list limits (#1300)
* fix: properly check friend list limits
added a config for friend list limit for the brave that want to mod the client to sanely go over 50
moved the best friend limit config to chatconfig.ini where it should be
cleanup loading these configs options a bit

Tested that the BFF limit works and that the new friend limit works as well

* fix typo

* fix member variable naming
2023-11-17 18:44:48 -06:00
jadebenn
7bbe5ffc39 Fix falling from Spider Cave not smashing you (#1302) 2023-11-17 18:43:01 -06:00
David Markowitz
0ddd20e2b5 fix: ugc Save rocket and car modular assembly data to database (#1279)
* Ugc: Use persistent Id for rocekts and cars

* Remove comment

* Ugc: Save rocket and car IDs to the database

* Correct names

* Database: formatting
2023-11-15 19:32:30 -06:00
David Markowitz
f59ca8b1da fix: Ugc model pickup (#1275)
* Ugc: Make it so we dont bin the model

Users must dismantle the model as opposed to accidentally picking it up in model mode

* Fix editing model in brick mode

* PropEntrance: Remove debug log
2023-11-15 19:32:17 -06:00
David Markowitz
a44f998bd1 Navmesh: Update Avant Gardens (#1288) 2023-11-15 19:30:59 -06:00
78d8c57752 feat: make the help menu top 5 issues work and configurable (#1293)
* feat: make make the help menu questions work

* address feedback

* typo

* update defaults

* fix and address feedback

* newline
2023-11-15 19:30:46 -06:00
David Markowitz
8b270ca97a fix: Dismantling basically being O(n!) (#1295) 2023-11-15 19:29:53 -06:00
David Markowitz
59303a232e Slash commands: Update compares (#1270)
use case insensitive compare
use character name for kill instead of account name

Use correct Id for muting when a player is found
2023-11-15 19:29:00 -06:00
8cd5bf7b8d feat: implement consume item behavior (#1098)
* feature: implement consume item behavior

* Cleanup

* tested with skill 456 and fixed some things

* remove logs
2023-11-14 19:38:52 -06:00
8a9883c224 feat: use more zoneTable options (#1273)
* feat: use more zoneTable options

Allow setting framrate for the zone
Allow setting if pets are allowed in the zone
Allow setting if mounts are allowed in a zone
Allow disabling saving location to a zone

* address feedback
2023-11-14 07:02:17 -06:00
Gie "Max" Vanommeslaeghe
79ff6e7ee4 Merge pull request #1292 from DarkflameUniverse/fix-dismantling
fix: Models leak
2023-11-14 13:38:32 +01:00
Gie "Max" Vanommeslaeghe
4167d98667 Merge pull request #1272 from DarkflameUniverse/vanity-reload-and-spawners
feat: Vanity reload and vanity spawners
2023-11-14 13:34:14 +01:00
David Markowitz
23c5d13151 Models: Fix leak 2023-11-13 22:51:45 -08:00
jadebenn
68e5737b74 Fix: Pets can no longer dig treasure without completing Bella Pepper's "Lost Tags" mission (#1287)
* Added mission check to pet digs

* Little formatting change

* More formatting clean-up
2023-11-13 02:41:27 -08:00
jadebenn
411dce7457 Adding damage cooldown/"invincibility frames" as in Live (#1276)
* Added cooldown handling

* Made most of the logs hidden outside of debug mode

* removed weird submodule

* kill this phantom submodule

* updated to reflect reviewed feedback

* Added IsCooldownImmune() method to DestroyableComponent

* friggin typo

* Implemented non-pending changes and added cooldown immunity functions to DestroyableComponentTests

* add trailing linebreak

* another typo :(

* flipped cooldown test order (not leaving immune)

* Clean up comment and add DestroyableComponent test
2023-11-12 05:53:03 -06:00
175b354e68 address feedback 2023-11-10 22:01:25 -06:00
4c3949e5d8 remove logs 2023-11-09 21:29:29 -06:00
f727e3951c consolidate code 2023-11-09 21:28:52 -06:00
4867136133 fix spawners and cleanup 2023-11-09 18:59:43 -06:00
6e07798023 try to kill spawners, they don't exist? 2023-11-09 18:44:51 -06:00
3dc7b6ef7f add spawner handeling and reload to deleted exsiting entities
spawned don't get deleted yet
2023-11-09 18:33:39 -06:00
Nathan Ogden
2c9a98313a chore: Notes for running as system service (#1252)
* Note for running as system service
Note for running as system service

* Additional detailing of linux service.

* Added darkflame.service file

changed readme to reference new file
2023-11-08 19:15:46 -08:00
David Markowitz
d1dc9f5403 fix: add Onedrive log message (#1269)
* fix: Onedrive log message

* Update README.md
2023-11-08 17:56:59 -08:00
David Markowitz
52b5994b98 Ugc: Add subkey for rockets and cars (#1266)
Tested that, if a user has followed the guide and turned UGCUSE3DSERVICES from 1 to 0, the do not get booted to login for having a rocket with a subkey in their inventory.

Add bouncer logic

Ugc: Use random Id
2023-11-08 12:18:02 -06:00
Gie "Max" Vanommeslaeghe
4c10faa852 Merge pull request #1265 from DarkflameUniverse/ugc_patch
fix: Ugc Remove async and second id usage
2023-11-07 19:09:37 +01:00
Gie "Max" Vanommeslaeghe
070d4a1fa8 Merge pull request #1267 from DarkflameUniverse/dummyfix
fix: Nexus Tower Combat Challenge exploding dummy
2023-11-07 19:03:12 +01:00
David Markowitz
6795dd189c CombatChallenge: Fix exploding dummy 2023-11-06 14:49:53 -08:00
David Markowitz
f40fce7711 Ugc: Remove async and second id usage 2023-11-06 01:41:28 -08:00
David Markowitz
797abb176a ChatFilter: Fix incorrect segment highlighting (#1255) 2023-11-05 17:19:26 -06:00
David Markowitz
0f9e951162 Database: Use null for accounts (#1253) 2023-11-05 01:00:31 -08:00
David Markowitz
cea0b98edf WorldServer: Fix crash from deleting last char (#1254)
Revert "WorldServer: Fix crash from deleting last char"

This reverts commit d9adafa1fef0ac88ed2b3b8ca6b97c2421a603e2.

Update WorldServer.cpp
2023-11-05 01:00:19 -08:00
David Markowitz
1e2d5605eb fix: Navmesh updates to Frostburgh and Forbidden Valley (#1251)
* Navmesh: Add Frostburgh mesh

* Navmesh: Add Frostburgh mesh

Also edit Forbidden Valley mesh
2023-11-04 10:42:39 -05:00
David Markowitz
32cf111810 Script: Fix incorrect kill method (#1248) 2023-11-04 10:42:28 -05:00
Max
a19bead268 Fix edge case where leaderboard viewing would cause unhandled exception 2023-10-29 22:40:06 -04: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
9375c36c7b fix: remove hardcoded rotations now that vehicles orient correctly (#1132) 2023-07-03 11:58:49 -05:00
Raine
5cc7479f29 Update credits (#1133) 2023-07-01 15:40:34 -07:00
David Markowitz
c4135eac46 Revert playerflags functions to uint instead of int (#1130)
Prevents issue with negative numbers resulting in bugs.
2023-06-26 00:51:28 -07:00
41898bef86 foot race player flag fix (#1125)
and include fixes
2023-06-23 08:50:15 -05:00
David Markowitz
787dac7cd9 Update Dockerfile (#1126)
Fixes #1124
2023-06-23 08:49:58 -05: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
David Markowitz
fe23c7c5f7 Allow default scripts (#1117)
Fix an issue where vanity script overwrote always
2023-06-20 10:40:16 -05:00
David Markowitz
132d31d3ab Fix vehicle serialization during races (#1122)
* Fix vehicle serialization during races

- Add missing frame stats reading
- correct the inversion of rotation
- correct serialization order
- use proper dirty flags

Tested that racers are no longer sideways on certain vertical slopes and stay in sync throughout the whole race.

* Update ClientPackets.cpp

* Update ClientPackets.cpp

* Update VehiclePhysicsComponent.h
2023-06-20 09:19:21 -05:00
David Markowitz
2d31b7e4bb Fix incorrect serialization of SendTeleport (#1121)
* Fix incorrect serialization of SendTeleport

- Fixes all incorrect teleports in the game
- remove hacks in mast teleport
- ...
- ......

Update GameMessages.cpp

* Remove stupid argument

there got it all out

* remove extra true
2023-06-18 00:00:36 -07:00
David Markowitz
f46bc33dd4 Fix prereq bug (#1118) 2023-06-17 19:20:05 -05:00
David Markowitz
0d6bd33f9e Remove unused problematic code (#1115) 2023-06-16 23:30:28 -05:00
1a74c028c2 fix: make vanity npc's use default equipment if none is specified (#1116) 2023-06-16 16:09:46 -05:00
David Markowitz
2a0f63c0a1 Fix all smashables not playing animations (#1112)
Fixes an issue where most smashables did not explode into bricks upon death.  This included anything that was spawned or didnt have the flag is_smashable set.
Tested that in races, all objects smash into bricks
Tested that the player properly explodes in their car if they crash
Tested that Shooting Gallery plays the special smash animation when a ship is smashed
Tested that all spawned objects play smash animations

* Fix warning, Fix modular assembly not smashing

* Rename variable to correct name
2023-06-14 15:44:22 -07:00
David Markowitz
12d7ab9034 Remove null check in GetPosition (#1109)
Get ready for null pointer errors
2023-06-06 22:48:41 -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
David Markowitz
b589755655 Fix out of bounds access in dpGrid (#1106)
Fixes an issue where we would try to access an array out of the physics bounds
2023-06-03 16:28:27 -07:00
David Markowitz
8ae1e1bc6b Fix: remove ability to buy items from a vendor if they don't sell said item (#1105) 2023-06-03 00:40:46 -07:00
David Markowitz
9fabff16e4 Update AMFDeserialize (#1096)
Per ISO C++ standard 9.7.1 5.3,
"Otherwise the type of the enumerator is the same as that of the preceding enumerator unless the
incremented value is not representable in that type, in which case the type is an unspecified integral
type sufficient to contain the incremented value. If no such type exists, the program is ill-formed."
it is not undefined behavior to set a scoped enum to a value outside of its constant range because all values of the underlying type can represent the scoped enum
2023-06-02 06:44:49 -05: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
e47169fec5 Fix: Some platforms not using the same RNG for every roll (#1103)
* Test changes

* Update ObjectIDManager.h

* Revert "Update ObjectIDManager.h"

This reverts commit 3e4d169718.

* Revert "Test changes"

This reverts commit 8e16573f93.

* Use random engine
2023-05-26 23:22:31 -05:00
David Markowitz
238751f14e Remove extra cout (#1101) 2023-05-25 15:29:46 -05:00
59387e5fe3 fix: update type in am blue x script (#1095)
Fixes #1094
2023-05-17 13:17:34 -05:00
Gie "Max" Vanommeslaeghe
f9b52ad01c Merge pull request #1025 from EmosewaMC/more-cdclient-cleanup
Implement animation table
2023-05-14 15:08:18 +02:00
David Markowitz
1f3df08730 Update GameMessages.cpp 2023-05-13 16:22:13 -07:00
9708ea28dc refactor: removed hardcoded ag laser logic (#1079)
* Removed hardcoded laser logic

* Address feedback
2023-05-13 18:21:17 -05:00
David Markowitz
8a065ad074 Merge remote-tracking branch 'upstream/main' into more-cdclient-cleanup 2023-05-13 16:16:58 -07:00
Jett
2117a18d62 Enable artifact uploading and replace upload parameters (#1091) 2023-05-13 17:23:09 -05:00
David Markowitz
4fe335cc66 Refactor: Amf3 implementation (#998)
* Update AMFDeserializeTests.cpp

Redo Amf3 functionality

Overhaul the whole thing due to it being outdated and clunky to use

Sometimes you want to keep the value

Update AMFDeserializeTests.cpp

* Fix enum and constructors

Correct enum to a class and simplify names.
Add a proper default constructor

* Update MasterServer.cpp

* Fix bugs and add more tests

* Refactor: AMF with templates in mind

- Remove hard coded bodge
- Use templates and generics to allow for much looser typing and strengthened implementation
- Move code into header only implementation for portability

Refactor: Convert AMF implementation to templates

- Rip out previous implementation
- Remove all extraneous terminology
- Add proper overloads for all types of inserts
- Fix up tests and codebase

* Fix compiler errors

* Check for null first

* Add specialization for const char*

* Update tests for new template specialization

* Switch BitStream to use references

* Rename files

* Check enum bounds on deserialize

I did this on a phone
2023-05-13 17:22:00 -05:00
9d105a287d fix: not everything attached to a path is a moving platform (#1090) 2023-05-13 13:47:28 -07:00
1af70161eb fix: orient player correctly when using pirate mast in FV (#1087)
* fix: frient player correctly when using pirate mast in FV

* only get mast name once
2023-05-13 09:31:13 -05:00
739eae5244 feature: Implement FallSpeedBehavior (#1084)
* Hacky FallSpeedBehavior

* Fixup

* Make it more robust like speedboost
add check for default
Fix error in GetActiveSpeedboosts

* simplify and address feedback
2023-05-13 09:30:59 -05:00
Gie "Max" Vanommeslaeghe
07803a7ca2 Merge pull request #1085 from DarkflameUniverse/issue-436
fix: not exiting shooting gallery when clicking activity close button
2023-05-13 14:11:16 +02:00
Gie "Max" Vanommeslaeghe
61ae619886 Merge pull request #1032 from EmosewaMC/FixWingreaper
Fix Wingreaper birds not moving
2023-05-13 14:04:37 +02:00
Gie "Max" Vanommeslaeghe
8a8006bee5 Merge pull request #1088 from EmosewaMC/movingPlatformsFix
Fix deserialization errors for MovingPlatforms
2023-05-13 14:03:24 +02:00
David Markowitz
c5afd7d4a3 Fix deserialization errors for MovingPlatforms
- Fixes deserialization errors for MovingPlatforms that did not have an attached_path, but had a MovingPlatform component >= id 0.
2023-05-13 04:04:15 -07:00
a809f36548 Address feedback 2023-05-11 09:23:48 -05:00
0e01948414 Define comp 103 as Gate Rush Control comp (#1078)
Fix typo in 115
2023-05-11 06:54:41 -05:00
6e6a05fc1d fix: prevent negative imagination (#1083)
* fix: prevent negative imagination
And fail switch if we don't have enough imagination

* Make better
2023-05-11 06:37:02 -05:00
5af5b0f1c1 fix: not exiting shooting gallery when clicking activity close button
Fixes #436
Fixes crash when replaying as well
2023-05-10 19:26:04 -05:00
bf0ae6f181 fix: add check for arg nums on handlepushobject (#1081) 2023-05-10 07:44:21 -05:00
b1cd2776fa fix: make exiting the race work (#1082) 2023-05-10 04:05:56 -05: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
4ff5afd9f7 Fix race exit dialogue always exiting (#1077)
Fixes #1048
Tested that closing the dialog via esc, the x in the top right, or the big red x doesn't exit the race
Tested that the green check button does exit the race
2023-05-09 00:40:00 -05:00
David Markowitz
ce931c2cfe Fix erroneous GM message ID (#1076) 2023-05-09 00:39:43 -05: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
7aad6e4bc2 Make header skips more obvious (#1074)
* Make header skips more obvious

seeing inStream.Read(LWOOBJID) is much less clear than a macro which very clearly skips the header.

* Formatting pass
2023-05-08 06:31:10 -05:00
David Markowitz
1c7ac93d4b Fix various bugs and make code cleaner.
Still have work to go.
2023-05-08 03:55:10 -07:00
Gie "Max" Vanommeslaeghe
64a947e338 Merge pull request #1069 from EmosewaMC/NullChecks
Add more null checks and split out code
2023-05-08 12:10:58 +02: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
8ceabadcde Removed some hardcoded logic for racing (#1075)
Including return world and what activity ID to use for rewards
2023-05-08 04:38:08 -05: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
7e61638595 Reinforce PacketUtils writing (#1073)
Ensure the correct size is written to the bitstream.  It is always supposed to write 64 bits.
2023-05-06 23:45:07 -07:00
David Markowitz
33c12f3bc5 Fix bounds check (#1071)
Fix Chat Crash

Update CMakeVariables.txt

Add checks for all servers
2023-05-06 13:32:53 -05:00
David Markowitz
7949907517 Fix bounds check (#1070) 2023-05-06 13:32:46 -05:00
David Markowitz
cffb1449d8 Add better logs to saving (#1068)
* Fix overread in projectile behavior

* Fix stuns

* Correctly read in bitStream

* Fix projectile behavior

* Address movement type issues

* Update shutdown time to be accurate

* Fix small issues

* Fix missing template

* Add note for compile jobs

* Add bounds check for speed division

* Add better logs
2023-05-06 13:32:38 -05:00
5479cf4428 Fix typing of some player flag variables (#1067)
Mainly on properties

Tested that the spider queen mission can now be progressed
2023-05-06 13:32:26 -05:00
David Markowitz
df3265c82e Add more null checks and split out code
Makes crash logs more apparent for what stage they crashed in for the engine updating.
2023-05-05 23:31:30 -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
e297aacc68 Breakout message identifiers (#1065)
and make them scope enums
2023-05-03 16:38:32 -05: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
c17b5fa586 prevent ressurecting with more than max stats (#1064)
for health and imagination
2023-05-03 01:31:50 -05:00
David Markowitz
b5e3bd22e3 Merge remote-tracking branch 'upstream/main' into first-draft-leaderboard-re-write 2023-05-02 15:49:23 -07:00
6aa90ad5b2 Breakout rest of the enums from dCommonVars and clean it up (#1061)
* Breakout rest of the enums from dcommonvars
so we don't have to deal with merge conflicts
ePlayerFlags is not a scoped enum, yet, due to it's complexity

* address feedback

* make player flag types consistent

* fix typo
2023-05-02 17:39:21 -05:00
David Markowitz
e8590a5853 Add tests for LDF parsing and serialization. Cleanup LDF (#1062)
* Add tests and cleanup LDF header

Also implements a speedup by using overloaded operators to put numbers directly to a stream as opposed to doing to_string first.

Stage 2 of re-write

Reduce scoping
Add further optimizations
Fix more edge cases
Split out tests to many smaller ones

Use EXPECT_NO_THROW

Add edge cases to test

Added these first with the before to confirm they failed, and now will be adding the remaining fixes needed to make the tests pass.

Add edge case testing for LDF strings

Add further tests

Use characters instead of char*

Update AMFDeserializeTests.cpp

Add null tests

* Add Test Fixture for dCommon

* Add speed test

* Convert to using string_view

* Add explanation on early return

* Remove "testing" code
2023-05-02 17:19:20 -05:00
2f919d101f Fix bad lot comparison in AG Jet Effect Server (#1063) 2023-05-02 03:27:16 -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
4976701f37 breakout object bits into scoped enum (#997)
* breakout object bits into enum class
tested that things still work as expected
use the inplace set bits where appropiate

* add inline
2023-04-25 13:17:40 -05:00
Gie "Max" Vanommeslaeghe
de1ddd3125 Merge pull request #1019 from EmosewaMC/inventoryTypeCorrections
Correct incorrect inventory types
2023-04-23 12:49:43 +02:00
David Markowitz
58951dced0 Remove all need for a local ugc server (#1054) 2023-04-22 12:32:32 -07:00
2e284eb2ce Implement Timer handlers in triggers and ontimerdone trigger event (#1031)
* Works, but AOE is broken

* Address Feedback

* fix typo
2023-04-18 12:48:03 -05:00
EmosewaMC
89f427ace0 Further work on leaderboards 2023-04-18 01:26:35 -07:00
David Markowitz
da6ca82ae2 add missing overrides (#1060) 2023-04-18 01:40:33 -05:00
f60ea40acc Add random end of race behavior (#1056)
* randominze between 0 and 7 inclusive
for the different animation types

* Make the end behavior deterministic unpon loading
So that all players see the same animations for each other
2023-04-18 01:40:20 -05: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
fbfa778d3d Patch ghosting exclusions (#1059) 2023-04-17 14:19:26 -05: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
David Markowitz
4734996c7c Resolve most compiler warnings (#1053) 2023-04-12 11:48:20 -05:00
ce51438bc8 Implement some scripts for alpha FV (#1049)
* Implement maelstrom fog for alpha FV
add OnOffCollisionPhantom call to cppscripts
Add physics shape for gas blocking volume

* Add Ninja Sensie Script for alpha FV
and migration

* Fix private var casing

* And ninja wild scripts
they keep making me add more things

* address feedback

---------

Co-authored-by: Gie "Max" Vanommeslaeghe <gievanom@hotmail.com>
2023-04-12 11:46:31 -05:00
Gie "Max" Vanommeslaeghe
9c721abebb Merge pull request #1050 from DarkflameUniverse/pickup-scripts
Implements all the pickup scripts
2023-04-12 16:19:13 +02:00
David Markowitz
308d56968a Use epsilon comparison 2023-04-11 22:25:02 -07:00
David Markowitz
268155fc98 Fix more invisible enemy issues (#1052) 2023-04-11 00:42:12 -07:00
d2d075ef52 remove debug log 2023-04-09 13:50:26 -05:00
09e9bb2c15 fix scripts
split speed out to use target as caster
fix armor skill
2023-04-09 13:21:57 -05:00
bed269ffbe Merge branch 'main' into pickup-scripts 2023-04-09 12:11:54 -05:00
2cf92a16d2 Add scripts for a few wild creatures (#1051)
ignore frog script
2023-04-09 10:17:05 -05:00
87e36aaf72 remove log 2023-04-09 09:40:57 -05:00
172b398b7b fix consolidation
add speed buff
2023-04-09 09:38:56 -05:00
5cdff8bcaf Simplify
tested that things still work as intended
2023-04-09 08:54:14 -05:00
9e4de544a6 fix 2023-04-09 01:10:23 -05:00
37fe935a3a Implements all the old pickup scripts
Testsed to make sure they work
Tested to make sure existing script works still
killing it immedialtely is live accurate, the timer was not accurate
2023-04-08 22:07:25 -05:00
David Markowitz
33f9e9c8cb Allow case insensitive commands (#1047) 2023-04-08 15:45:45 -05:00
David Markowitz
541250176c Resolve many issues with invisible enemies and End Behavior nodes not firing (#1044)
* Finall fix invisible enemies

* Add garbage collection

* Add comment

* Add constexpr for lagFrames
2023-04-05 08:57:47 -05:00
Gie "Max" Vanommeslaeghe
3202b5a36e Merge pull request #1042 from EmosewaMC/FixSkills
Fix SwitchMultiple incorrect handling
2023-04-03 20:52:22 +02:00
Gie "Max" Vanommeslaeghe
d25b7729b6 Merge pull request #1043 from DarkflameUniverse/update-change-orientation-behavior
Fix and fully implement ChangeOrientation behavior
2023-04-03 20:51:39 +02:00
930735860b use z axis 2023-04-03 13:10:51 -05:00
David Markowitz
426a84daf9 Update InterruptBehavior.cpp 2023-04-03 09:37:29 -07:00
dffcbcd4d4 cleanup 2023-04-03 08:29:39 -05:00
a5ff93351d remove empty line
remove undeeded header
2023-04-03 08:25:47 -05:00
1fb086ccbd Fully implement Change orientation
fix bug where you would always look at self
added to_angle handline
2023-04-03 08:21:23 -05:00
David Markowitz
b8251c06b8 Fix incorrect SwitchMultiple handling 2023-04-03 04:11:02 -07:00
David Markowitz
a26f29baf6 Fix some models not disassembling into bricks (#1041) 2023-04-02 23:26:44 -07:00
595afe42e5 fix the lookat 2023-04-02 22:37:24 -05:00
David Markowitz
54d8c45b52 Don't interrupt players 2023-04-02 18:05:42 -07:00
David Markowitz
801ca69778 Fix nameplate command (#1040) 2023-04-01 18:30:08 -07:00
David Markowitz
49d695a153 Remove extra bit in BasicAttackBehavior write (#1039) 2023-04-01 02:45:29 -07:00
David Markowitz
152c8ea712 Add npc (#1038) 2023-03-31 16:50:17 -05:00
David Markowitz
cbef4a140e Fix Spider Queen boss battle crash (#1034) 2023-03-30 06:01:15 -07:00
David Markowitz
47445ada54 Fix Wingreaper birds not moving
Fix an issue where the Wingreaper birds no longer moved.  The client seems to do the following:
Default speed set to 10.0f
Check the PhysicsComponent table for the column speed and if it exists set speed to that value and if the value was null set it to the default again.
2023-03-27 01:13:34 -07:00
David Markowitz
426bc963fe Add Animation Table logic 2023-03-26 05:18:45 -07:00
David Markowitz
1e4e1b914c Merge remote-tracking branch 'upstream/main' into more-cdclient-cleanup 2023-03-26 03:00:21 -07:00
David Markowitz
b432a3f5da Remove inlines
Clean up macros

more tomorrow

Cleanup and optimize CDActivities table

Remove unused include

Further work on CDActivityRewards

Update MasterServer.cpp

Further animations work

Activities still needs work for a better PK.

fix type

All of these replacements worked

Create internal interface for animations

Allows for user to just call GetAnimationTIme or PlayAnimation rather than passing in arbitrary true false statements
2023-03-26 02:59:46 -07:00
c415d0520a Implement some more trigger event calls and command handlers (#989)
* Implement some trigger event calls
and command handlers

* add zone summary dimissed GM

* break and remove log

* some cleanup in Gather Targets
and blocking out

* fix default value of unlock for play cinematic

* Log on errors
add enum for physics effect type
simplify nipoint3 logic
check arg count
add enum for End behavior

* tryparse for nipoint3

* totally didn't forget to include it

* bleh c++ is blah

* ???

* address feedback

* Fix for #1028
2023-03-25 05:26:39 -05:00
72ca0f13ff breakout gmlevel into a scoped enum (#996)
* breakout gmlevel enum and make it a class
tested that things still work
slash command,
chat restrictions,
packets and serializations

* fix GM level for some slash commands

* fix new use of this enum
2023-03-24 18:16:45 -05:00
David Markowitz
b967cc57d1 Allow name billboards to be toggled (#1026)
* Allow name billboards to be toggled

* Allow name billboards to be toggled

* Add comments

* Move logic to Character

* Use Entity in Character instead
2023-03-23 09:49:31 -05:00
David Markowitz
7671cc6865 CDClient cleanup and optimization (#1023)
* CDClient cleanup and optimization

- Use static function to get table name
- Remove unused GetName function
- Replace above function with a static GetTableName function
- Remove verbose comments
- Remove verbose initializers
- Remove need to specify table name when getting a table by name
- Remove unused typedef for mac and linux

* Re-add unused table

Convert tables to singletons

- Convert all CDClient tables to singletons
- Move Singleton.h to dCommon
- Reduce header clutter in CDClientManager
2023-03-17 07:36:21 -07:00
David Markowitz
bd79e9433c Increase Battle of Nimbus Station end of match timer to 60 seconds (#1018)
as per the live script
This is now the third time this has been updated lol
2023-03-17 02:48:47 -07:00
David Markowitz
2bcf862f93 Development inventory command improvements (#1022) 2023-03-14 05:50:12 -07:00
David Markowitz
c3723371cf Patch divide by zero when advancing waypoints (#1020) 2023-03-14 04:12:26 -07:00
David Markowitz
f0451616a4 Correct incorrect inventory types 2023-03-13 03:16:14 -07:00
David Markowitz
137a5e5c3d Players no longer respawn if they were alive at the end of Battle of Nimbus Station (#1017) 2023-03-12 07:21:27 -07:00
David Markowitz
a532bc15d8 Fix zombie bug (#1014) 2023-03-08 07:32:03 -06:00
ff0336793c add stun immunity script (#1015)
several summons use this script to be immune to stuns
2023-03-08 07:31:45 -06:00
David Markowitz
49047a267b Fix racing imagination loss on death (#1006)
* Fix imagination on death

* Fix defaults

* Fix visuals
2023-03-05 14:34:59 -06:00
9d65d871d0 fix compatibility with nexus dash (#1011)
* add some more utility to the masterserver -a command
fix compatability with nexus dash

* cleanup code some more
user logger where it makes sense
only take in password if it is needed
log a better error if account cannot be created

* update message

* return before success statement if catching error
2023-03-05 13:11:32 -06:00
e524b86e12 breakout the component types into a scoped enum (#1002)
* breakout the component types into a scoped enum

tested that things are the same as they were before

* fix missed rename

* fix brick-by-brick name to be crafting
because that's what it is
2023-03-04 01:16:37 -06:00
David Markowitz
2837f68f44 Fix stuns with mast teleport (#1003) 2023-03-03 22:59:37 -08:00
David Markowitz
a0c0a87956 Fix Trigger Missions (#1010) 2023-03-03 22:58:29 -08:00
David Markowitz
3e482602d4 Fix non-parallel timers in CombatAIComponent (#1008)
* Fix non-parelell timers
2023-03-03 18:45:01 -08:00
David Markowitz
b6fc959433 Fix shark stinky fish death animation (#1004) 2023-02-28 17:30:28 -06:00
6d989f37f1 Breakout ServerDisconnectIdentifiers into an enum (#995) 2023-02-19 04:29:14 -08:00
David Markowitz
d138b7b878 Make ControlBehavior messages far more modular (#991)
* Make case consistent

* How modular can you go?

Holy modular

* Add comments

* Initialize values
2023-02-16 11:30:33 -06:00
484488e47d add bounds check to prevent crashing (#992) 2023-02-16 11:14:23 -06:00
David Markowitz
72c93c8913 Further implement Property Behavior parsing (#936)
Further implements the ControlBehavior processing and adds preparations for cheat detection
2023-02-13 18:55:44 -08:00
3cd0d1ec3d Make wrapper for casting skills (#987)
* Make wrapper for casting skills
this is to reduce magic numbers in the code base

Only updated one use of this to demo that this works.
Will be do more in a sepearate PR.

Also, inadvertantly fix damage stacking and self-damage in the teslapack

* add skill<->behavior caching

* explicit by reference

* address emo's feedback
2023-02-10 02:30:17 -06:00
91c0c1fcfb Split out LUTriggers into it's own component (#986)
* Split out LUTriggers into it's own component

* some cleanup

* fix debug log

* use emplace and tryParse

* slight refactor to make the work on startup
rather than at runtime
Also TODO's for getting targets via all the possible methods

* address feedback
2023-02-10 02:29:53 -06:00
David Markowitz
d17f51183e Allow landing animation in Return to the Venture Explorer (#977) 2023-01-26 21:41:40 -05:00
Jett
6aa69de4fd Resolution of accidental shifting of eItemType enum (#976) 2023-01-25 16:21:12 -08:00
Gie "Max" Vanommeslaeghe
cdffd5ff30 Fix: 968 bug using lookup command with no parameters crashes instance (#970)
* Update SlashCommandHandler.cpp

* Update SlashCommandHandler.cpp
2023-01-24 17:09:32 -06:00
ac5f08f601 Merge pull request #963 from DarkflameUniverse/enum-cleanup
cleanup enums to make them more consistent style wise
2023-01-24 16:38:41 -06:00
Jett
90d184ba93 Remove Clang Tidy configurations. (#969) 2023-01-24 22:36:30 +00:00
bff14fd391 add blame ignore 2023-01-22 17:39:38 -06:00
faf42d2f8c cleanup enums to make them more consistent 2023-01-22 17:38:47 -06:00
David Markowitz
cff94b6c22 Fix hash collisions in achievements (#962) 2023-01-21 09:37:09 -06:00
David Markowitz
c8cd51ef63 Fix warning for overrides (#961) 2023-01-20 00:07:25 -08:00
6fd80e3117 Don't enable HC on minigame worlds (#959)
* Fix max's ouchi

* use smarter logic

* fix whitespace

* clone
2023-01-20 01:50:46 -06:00
David Markowitz
14085d09bd Add note for compiling with multiple jobs (#948)
* Fix overread in projectile behavior

* Fix stuns

* Correctly read in bitStream

* Fix projectile behavior

* Address movement type issues

* Update shutdown time to be accurate

* Fix small issues

* Fix missing template

* Add note for compile jobs
2023-01-17 13:26:50 -06:00
David Markowitz
7418e02365 Update AmTeapotServer.cpp (#949) 2023-01-17 06:07:34 -06:00
David Markowitz
fbaf1cbb25 Dont preemptively delete objects (#958)
Let finalizeShutdown take care of it
2023-01-17 06:06:09 -06:00
872270704c Hardmode cleanups (#954)
* load values once
so that it doesn't check every time
don't return, just skip
don't realod char

* address feedback

* don't drop the only item you can't get again

* address most feedback

* move settings for HC mode

* fix comment

* claenup whitespace
2023-01-12 13:16:24 -06:00
David Markowitz
7bca43ffc1 Fix tests (#953) 2023-01-11 22:36:03 -08:00
wincent
7aacfc1bf0 Fixed crashes related to hardcore mode 2023-01-11 21:51:14 +01:00
5557a98129 fix hardmode example config options (#952) 2023-01-11 14:10:48 -06:00
Gie "Max" Vanommeslaeghe
45d739499a Merge pull request #950 from DarkflameUniverse/vanity-ldf-reading
Add ldf controlls to vanity npc tools
2023-01-11 20:22:21 +01:00
Gie "Max" Vanommeslaeghe
5b30f4a5ae Merge pull request #951 from DarkflameUniverse/hardcore-mode
Hardcore mode
2023-01-11 20:18:56 +01:00
Gie "Max" Vanommeslaeghe
bfa4fbd5a9 add hardcore_mode to settings 2023-01-11 20:11:06 +01:00
Gie "Max" Vanommeslaeghe
e7bc4ef773 add hardcore mode 2023-01-11 20:08:54 +01:00
ce39e3ad6b Add ldf controlls to vanity npc tools
make vanity npc use more forgiving
2023-01-11 01:10:14 -06:00
David Markowitz
e67f310632 Fix missing template override for AMFFormats (#946) 2023-01-08 10:01:53 +01:00
David Markowitz
8920cd1063 Use field names instead of numbers for CDClient tables (#945) 2023-01-07 01:48:59 -08:00
David Markowitz
a580e3a2f5 Update lookup command (#909)
* Update lookup command

* Fix bugs

Update SlashCommandHandler.cpp
2023-01-07 00:17:09 -06:00
David Markowitz
a28a2e60cf Add property Teleport behavior (#846)
* Add property Teleport behavior

Untested.  Will mark pr as ready for review when this has been tested

* Fix issues
2023-01-07 00:16:43 -06:00
5374c555f5 Implement bubble seriliaztion in controllable physics (#942)
* bubble

* "Correct" serialization and enum

* Enum update

* figured out what things do

* accurate types and cleanup

* add sanity check
add getter
add slash command for testing

* fix default

* cleanup slash command

* handle game message probably
remove funny slash command
add all bubble GM's

Co-authored-by: Jett <55758076+Jettford@users.noreply.github.com>
2023-01-07 00:14:51 -06:00
80f8dd8003 Imminuty updates (#925)
* WIP Immunities

* Immunity getters

* remove redundent variable
replace it use with it's equivalent

* remove unused lookups, fix typos

* fix tests

* added imunity test

* address feedback

* more immunity tests

* explicit this
2023-01-06 23:59:19 -06:00
David Markowitz
1ac898ba00 Remove GameConfig (#874)
* Remove GameConfig

* Fully remove GmeConfig

* Update worldconfig.ini

Co-authored-by: Aaron Kimbrell <aronwk.aaron@gmail.com>
2023-01-06 23:21:40 -06:00
David Markowitz
fc75d6048f dGame Precompiled header improvements (#876)
* moving branch

* Add deleteinven slash command

* Change name of BRICKS_IN_BBB

* Use string_view instead of strcmp

* Clean up include tree

* Remove unneeded headers from PCH files

Removes unneeded headers from pre-compiled headers.  This increases compile time, however reduces development time for most files.

* Update Entity.h

* Update EntityManager.h

* Update GameMessages.cpp

* There it compiles now

Co-authored-by: Aaron Kimbrell <aronwk.aaron@gmail.com>
2023-01-06 23:17:05 -06:00
David Markowitz
8bcb4bd36d Fix smashables not counting towards whole team (#944) 2023-01-06 23:06:24 -06:00
David Markowitz
bad3845d83 Address Docker issues and remove need to extract cdclient.fdb (#895)
* Implement a server res directory

* Only convert if neither exist

* Remove unzip, Update RegEx

* readme updates

Run setup after setting working dir

Address several docker issues

Revert "Run setup after setting working dir"

This reverts commit fd2fb9228e82a350204c1ef61f7ba059479bb12f.

Fix docker

* Remove extra submodules

* Rework logic

* Switch if block

* Remove need to extract fdb from client

* Change log name

* Update FdbToSqlite.cpp
2023-01-06 23:04:20 -06:00
Gie "Max" Vanommeslaeghe
7fcc8a6e84 Merge pull request #935 from EmosewaMC/WorldConfig
Eliminate WorldConfig Based Magic Numbers
2023-01-07 03:41:40 +01:00
David Markowitz
1a34f6f74a Fix debug logging newline (#940) 2023-01-04 08:15:06 -06:00
David Markowitz
1789ec7f20 delta compression fixes (#937) 2023-01-03 11:22:04 -06:00
David Markowitz
dc7d0ce142 Fix Stuns of duration zero (#938) 2023-01-03 11:21:57 -06:00
David Markowitz
203a150a56 Update DestroyableComponent.cpp 2023-01-01 16:36:10 -08:00
EmosewaMC
19be0a61b2 Eliminate WorldConfig Magic Numbers
Add comments for fields

Use the name directly
2023-01-01 05:20:03 -08:00
David Markowitz
09157506bf Fix Complete Overhaul (#934)
Check your pointers :)
2022-12-31 11:44:09 -08:00
David Markowitz
737eaba54d Serialize target with GameMessageStartSkill (#933) 2022-12-31 03:56:30 -08:00
David Markowitz
fab4414204 Fix serratorizer chargeup time (#931) 2022-12-31 03:56:12 -08:00
34b5f0f9d6 add uncast to speed behavior (#932) 2022-12-31 02:46:25 -06:00
David Markowitz
9adbb7aa86 Address World Server Packet timing and erroneous log (#929)
* Fix overread in projectile behavior

* Fix stuns

* Correctly read in bitStream

* Fix projectile behavior

* Address movement type issues

* Update shutdown time to be accurate

* Fix small issues
2022-12-29 08:34:53 -06:00
David Markowitz
bd28e4051f Fix Hash Collisions in CDBehaviorParameter table (#930)
* Fix hashing

* Update CDBehaviorParameterTable.cpp
2022-12-29 03:43:52 -06:00
David Markowitz
99c0ca253c Basic Attack Behavior Live Accuracy Improvements (#926)
* Overhaul BasicAttack Behavior so it matches the live 1.10.64 client
2022-12-28 14:04:37 -08:00
David Markowitz
0e9c0a8917 Fix MovementSwitch Behavior (#927) 2022-12-28 14:03:07 -08:00
David Markowitz
e41ed68447 Update README (#806)
* Update README

The README is very out of date, the following changes have been made
- Update what the file tree should look like
- Remove client Avant Gardens Survival script fix
- Update some incorrect commands or commands that were missing packages.
- Add packed client setup instructions
- Add *config.ini setup instructions
- Describe what configs should be modified and what you may want to change
- More detail in the verify step
- Change Account Manager link to Nexus Dashboard
- Remove table of commands and reference Commands.md instead
- Specify that UGCSERVERIP may need to be changed to localhost as well

* Fix Avant Gardens Survival

This addresses the Avant Gardens Survival bug.  Squeezing it in with the README changes since it is a small change.

* Remove Locale

* Update README.md

Co-authored-by: Jonathan Romano <jonathan@luxaritas.com>

* Remove dLocale again?

* Saving for the night

* Revert "Fix Avant Gardens Survival"

This reverts commit b1a1ce2d84.

* Update Mission.cpp

* Update README.md

Move comments and add pre-processor define

Update README.md

Update README.md

Update CMakePresets.json

Update CMakeVariables.txt

Update README.md

i love readmes

Update README.md

Update README.md

Update README.md

Update README.md

Update README.md

Update README.md

Update README.md

* Update README.md

Co-authored-by: Daniel Seiler <me@xiphoseer.de>

* Address feedback

* Update README.md

* Update Database.cpp

* Update README.md

* Revert tcp specification

Co-authored-by: Jonathan Romano <jonathan@luxaritas.com>
Co-authored-by: Aaron Kimbrell <aronwk.aaron@gmail.com>
Co-authored-by: Daniel Seiler <me@xiphoseer.de>
2022-12-28 13:58:53 -08:00
5cc7d47074 sanity check on opening packages (#923) 2022-12-24 14:41:13 -08:00
David Markowitz
1470af99c3 Correct Property FX incorrect skill cast (#920) 2022-12-24 04:06:27 -08:00
David Markowitz
85ab573665 Fix duping issue (#921) 2022-12-24 09:51:59 +01:00
6ec921025d Use new logic for applying speed changes in ApplyBuff (#919) 2022-12-24 00:49:31 -08:00
David Markowitz
bbd5a49ea2 Update DarkInspirationBehavior.cpp (#897) 2022-12-23 18:05:30 -08:00
David Markowitz
675cf1d2a4 Fix baseEnemyApe stuns and fix IdleFlags serialization (#914)
* Fix baseEnemyApe stuns

* Correct serialization
2022-12-23 00:14:51 -06:00
9ebb06ba24 Qb team credit (#912)
* give credit to whole team for qb's

* fix compiling
2022-12-22 07:24:59 -06:00
David Markowitz
96313ecd69 Calculate world shutdown timer (#910) 2022-12-22 05:16:35 -08:00
David Markowitz
015cbc06ea Fix racing spawn positions (#913) 2022-12-22 05:16:18 -08:00
David Markowitz
dff02773a0 Fix dragon stuns (#915) 2022-12-22 05:16:08 -08:00
David Markowitz
d052ed6a63 Update MigrationRunner.cpp (#911) 2022-12-22 06:06:59 -06:00
David Markowitz
fd9757d121 Implement a server res directory for server required client files (#891) 2022-12-21 22:34:11 -08:00
David Markowitz
bd7f532a28 Implement the Imaginite Backpack and Shard armor scripts (#886)
* Imaginite Pack now works

* Remove unused params

* Address issues

* Add TeslaPack script

Co-authored-by: aronwk-aaron <aronwk.aaron@gmail.com>
2022-12-21 14:33:41 -08:00
David Markowitz
51dd56f0a0 Add MTU config option (#908)
* Add config option

* Add reloading
2022-12-21 10:51:27 -06:00
David Markowitz
38eb441ca1 Correct Projectile behavior bitStream reads (#907) 2022-12-21 00:26:17 -08:00
Gie "Max" Vanommeslaeghe
559894024c Merge pull request #889 from EmosewaMC/MoreImprovements
Continued improvements to Servers
2022-12-20 23:11:24 +01:00
Neal Spellman
0a31db9d44 Updated README and CREDITS (#904)
- README now has proper capitalization for categories in the credits.
- New layout with former contributors moved to below active contributors.
- LEGO Universe credits linked for the special thanks.
- Aronwk properly recognized as DLU team member after mistakenly not included.
- Vanity credits updated to more closely mirror categories in README's credits.
2022-12-20 14:10:54 -08:00
David Markowitz
f2fa81b5c3 Fix lobbies (#901) 2022-12-20 15:20:44 -06:00
David Markowitz
2fdcf62ec6 Fix overread in projectile behavior and address broken stuns (#898)
* Fix overread in projectile behavior

* Fix stuns

* Correctly read in bitStream
2022-12-19 14:52:00 -06:00
David Markowitz
d69f733772 Fix trading taking the wrong item (#900)
* Fix trading taking the wrong item

* Add missing returns

* Improve further

Do all verification first.  Then actually do the trade.  Prevents possible cheating attempts
2022-12-19 14:51:44 -06:00
157a05239e Add speedbase readling and writing to the level prograssion component and impli proper character versions for fixes (#856)
* Add speed base readling and writing
to the level prograssion component
Add retroactive fix to the  world transfer
TODO: see about versioning charxml fixes to make them not run every time

* version all current changes

* cleanup speed behavior
add calculate for future use in scripts
make < 1 speed multiplier possible
tested wormholer and it plays anims correctly

* cap the lower end of the speed multiplier
until the ending the behavior on hit properly works

* address feedback
add emun for character version
make set ignore multipliers consistent in speed behavior
switch case for char version upgrades

* remove the ability to stack speed boosts

* update value on level ups
2022-12-19 13:45:50 -06:00
David Markowitz
9f47b1f0bb Merge remote-tracking branch 'upstream/main' into MoreImprovements 2022-12-19 03:53:51 -08:00
David Markowitz
f311685dda Fix Some missions not progressing if they are the last item in the inventory (#899) 2022-12-19 00:07:43 -08:00
David Markowitz
84c5d74450 Add Delete Inventory Slash Command (#865)
* moving branch

* Add deleteinven slash command

* Change name of BRICKS_IN_BBB

* Use string_view instead of strcmp

* Remove GameConfig

* Revert "Remove GameConfig"

This reverts commit cef5cdeea2.
2022-12-18 09:46:04 -06:00
David Markowitz
b972acbacc Fix stream reads (#894)
No changes expected
2022-12-18 06:49:13 -08:00
Gie "Max" Vanommeslaeghe
f41dfaebdf Merge pull request #887 from EmosewaMC/ServerShutdown
Improve server shutdown process
2022-12-18 15:41:58 +01:00
Gie "Max" Vanommeslaeghe
12ab094082 Merge pull request #892 from DarkflameUniverse/windows-debug-fixes
Resolve some string related issues for Windows Debug
2022-12-18 15:25:17 +01:00
David Markowitz
e1bcde628f Implement lower cap datagram size (#890) 2022-12-17 20:54:41 -08:00
Jett
1da2db9db6 Resolve some string related issues for Windows Debug 2022-12-17 16:03:18 +00:00
David Markowitz
5d0de99390 Merge remote-tracking branch 'upstream/main' into ServerShutdown 2022-12-16 19:09:01 -08:00
David Markowitz
2b56dfbc89 Merge remote-tracking branch 'upstream/main' into MoreImprovements 2022-12-16 19:08:51 -08:00
631365b7f7 Add change idle flags behavior and GM (#871)
* update naming for animation flag enum value 0

* Add change idle flags behaviors and GM

* default to 0 when none is given
2022-12-16 15:24:13 -06:00
32f8bda538 Allow the player to be interrupted (#881) 2022-12-16 15:23:38 -06:00
David Markowitz
cd78a3dec7 Fix cannon super charge speed (#883)
* Fix cannon

* Update SGCannon.cpp
2022-12-16 15:23:09 -06:00
David Markowitz
a2ca273370 Cleanup behavior bitstream reads (#888)
* Add failArmor server side

Address out of bounds reading in behavior

Address the basicAttackBehavior reading out of bounds memory and reading bits that didnt exist, which occasionally caused crashes and also caused the behavior to do undefined behavior due to the bad reads.

Tested that attacking a wall anywhere with a projectile now does not crash the game.  Tested with logs that the behavior correctly returned when there were no allocated bits or returned when other states were met.

Add back logs and add fail handle

Remove comment block

Revert "Add back logs and add fail handle"

This reverts commit db19be0906fc8bf35bf89037e2bfba39f5ef9c0c.

Split out checks

* Cleanup Behavior streams
2022-12-16 15:23:02 -06:00
David Markowitz
04ccd7ebe4 Merge remote-tracking branch 'upstream/main' into ServerShutdown 2022-12-16 04:07:08 -08:00
David Markowitz
b33a3df012 Scale timers 2022-12-16 04:02:54 -08:00
David Markowitz
0d460c0eb3 Update WorldServer timings 2022-12-16 03:46:38 -08:00
David Markowitz
3f1b4339f5 Improve chat and Auth
Also change most uses of int to specified lengths.
2022-12-16 02:24:02 -08:00
David Markowitz
e78dc0b874 Merge branch 'MoreImprovements' of https://github.com/EmosewaMC/DarkflameServer into MoreImprovements 2022-12-16 01:28:52 -08:00
David Markowitz
b1d4153f00 Merge remote-tracking branch 'upstream/main' into MoreImprovements 2022-12-16 01:28:34 -08:00
Daniel Seiler
1ed3af63b9 Log some recvfrom errors on linux (#885) 2022-12-15 22:32:36 -08:00
David Markowitz
213c3c37b0 Fix crash in BasicAttackBehavior (#862)
* Add failArmor server side

Address out of bounds reading in behavior

Address the basicAttackBehavior reading out of bounds memory and reading bits that didnt exist, which occasionally caused crashes and also caused the behavior to do undefined behavior due to the bad reads.

Tested that attacking a wall anywhere with a projectile now does not crash the game.  Tested with logs that the behavior correctly returned when there were no allocated bits or returned when other states were met.

Add back logs and add fail handle

Remove comment block

Revert "Add back logs and add fail handle"

This reverts commit db19be0906fc8bf35bf89037e2bfba39f5ef9c0c.

Split out checks

* Remove case 2

* Update SkillComponent.cpp
2022-12-15 22:10:58 -08:00
EmosewaMC
3c581fffbb Remove magic numbers
Replace magic numbers with constexpr calculated times.

Tested that trying to create a new instance while shutting down doesn't allow a new instance to be created.
2022-12-15 20:39:29 -08:00
EmosewaMC
4775dbf27f Condense frame rates 2022-12-15 19:55:07 -08:00
EmosewaMC
e1cc25759e Merge remote-tracking branch 'upstream/main' into ServerShutdown 2022-12-15 18:43:28 -08:00
David Markowitz
b7341c8106 Resolve warnings, change config init order and remove unused Game variables for all servers (#877)
* Resolve warnings and change init order

Initialize dConfig first, before logger so we know whether or not to log to console
Initialize namespace Game variables to nullptr so they are a known value if accessed before initialization.
Removed unused Game variables
Replaced config with a pointer instead of referencing something on the stack.
Assign return values to system calls to silence warnings.

Tested that the server still compiles, runs and allows me to load into the game.

* Only start Master of config files exist

Also default the logging to console to on on the off chance the files exist but are wrong / corrupted.
2022-12-15 08:13:49 -06:00
EmosewaMC
1afe717563 Properly exit
Properly exit based on the path taken to shutdown master.

Tested that shutting down through sigint or sigterm returns -1
Tested that a segfault exits the program properly
Need to test that players who are trying to connect while master is shutting down are not able to spawn more child worlds.
2022-12-15 05:46:03 -08:00
EmosewaMC
435761f64b Improve shutdown 2022-12-15 04:14:00 -08:00
EmosewaMC
9659000569 Merge branch 'master-logs' into ServerShutdown 2022-12-15 03:11:10 -08:00
David Markowitz
5292f36417 Packages updates (#864)
Update packages to not open if you dont have enough room.  Update packages to no longer allow them selves to be open unless you meet the pre-reqs.
2022-12-11 00:27:01 -08:00
David Markowitz
da910309a0 Remove unneeded commands (#880)
* Remove unneeded commands

* Thank you aron
2022-12-08 15:32:47 -06:00
Gie "Max" Vanommeslaeghe
430c6da4a7 Merge pull request #879 from EmosewaMC/main
Fdb NULL fixes
2022-12-08 13:51:55 +01:00
EmosewaMC
d5613b8034 hot fix 2022-12-08 04:44:56 -08:00
8886bf6547 Address Force movement behaviors triggering twice (#878) 2022-12-07 23:13:25 -08:00
EmosewaMC
a14e16237b Only start Master of config files exist
Also default the logging to console to on on the off chance the files exist but are wrong / corrupted.
2022-12-06 19:30:43 -08:00
Demetri Van Sickle
fde62a4777 Fixed typo (#875) 2022-12-06 08:36:42 -06:00
EmosewaMC
46f085eb4b Resolve warnings and change init order
Initialize dConfig first, before logger so we know whether or not to log to console
Initialize namespace Game variables to nullptr so they are a known value if accessed before initialization.
Removed unused Game variables
Replaced config with a pointer instead of referencing something on the stack.
Assign return values to system calls to silence warnings.

Tested that the server still compiles, runs and allows me to load into the game.
2022-12-06 04:39:09 -08:00
David Markowitz
18a0ae599b Add bandwidth limit of 10kb/s(#863) 2022-12-05 16:08:47 -08:00
David Markowitz
0a616f891f Change File Finder (#873) 2022-12-05 09:04:59 -06:00
David Markowitz
2ba3103a0c Implement FDB to SQLite (#872) 2022-12-05 00:57:58 -08:00
David Markowitz
e8ba3357e8 Add support to reload the config (#868) 2022-12-04 16:25:58 -06:00
David Markowitz
de3e53de6c Fix Model Vault (#870)
Allow pets, rockets and racecars to be stored in vault
2022-12-04 16:25:25 -06:00
Wincent Holm
ab5adea24c Move CDServer migration history table (#867) 2022-12-03 13:17:13 +01:00
David Markowitz
e1af528d9b Add SlashCommand for spawngroup (#858) 2022-12-02 03:47:27 -08:00
d8945e9067 Add migration to make play_key_id nullable (#857)
since there is an option not to use play_keys
2022-12-02 03:46:54 -08:00
2b9c014b86 Quiet activity manager timer logs (#861) 2022-12-02 00:44:20 -08:00
David Markowitz
63460ea00d Fix bricks not creating new stacks (#860)
Unintentionally, bricks were not creating new stacks if you tried to get another stack.  This prevents some missions from being completed.  This issue is now fixed
2022-11-30 01:04:46 -08:00
David Markowitz
09dfb6df3a Address news feed showing up on every world transfer (#855)
Addresses the news feed showing up on every world transfer
2022-11-27 22:19:15 -08:00
David Markowitz
56da3f8543 Remove Locale (#808)
* Remove Locale (finally)
2022-11-27 16:56:55 -08:00
David Markowitz
3222e78815 Implement undo action for pre-built models (#830)
Brick building as of right now does not implement the undo action properly.  This commit addresses the issue with undoing button being non-functional server side and implements the GM needed for addressing further issues.

Implement GameMessage UnUseModel which is called when a model in BrickBuilding is UnUsed.  Important for UGC content down the line.  Final code has been tested as follows:
1. Placed a model in brick build
2. saved placed a brick
3. repeat 2 and 3 twice more for 6 total models
4. Place a new model in brick mode and then edit all 7 models into one brick model instance
5. Pressing undo returns the converted model to the inventory and properly discards the other 6 without crashing.  Intended live behavior is to store this in the inventory instead however behind the scenes work is needed to implement UGC models properly.

Implement enum

Implement the BlueprintSaveResponseType enum so there are less magic numbers sent via packets.
Correct int sizes from unsigned int to uint32_t

Add deserialize test

Add a test for de-serializing a GM that is sent to the client.  Assertions verify the data is in the correct order and has no extra information.
2022-11-27 16:48:46 -08:00
David Markowitz
3939f19b08 Add Remove Buff Behavior and patch infinite use Imagination Backpack(#845)
Testing does not reveal any issues with existing buff removals sending this GM as well and may fix more bugs that were unknown, or cause more.
2022-11-27 16:40:14 -08:00
David Markowitz
1556f580d6 Improve Diagnostics logging (#841)
Improve diagnostics to write the file name and signal to the log file should there be a crash.
2022-11-27 13:47:14 -08:00
David Markowitz
d382eb3bc2 Fix Boogie Down (#854)
- Give entities that have a script component ID of zero a script component still
- Progress scripted entity missions within the for loop as we do for script calls

Tested that Boogie Down is (finally) completable.
Tested that Mission 737 is still completable
Checked that missions progressed inside OnEmoteReceived scripts to not double trigger progression
2022-11-27 04:03:30 -08:00
Jonathan Romano
f8f5b731f1 Allow servers to be run from directories other than build. Read/write files relative to binary instead of cwd (#834)
Allows the server to be run from a non-build directory.  Also only read or write files relative to the build directory, regardless of where the server is run from
2022-11-27 03:59:59 -08:00
David Markowitz
e40a597f18 Property Behavior deserialize definitions (#812)
* Implement basic functionality

Implements the basic functionality and parsing of property behaviors.

Unhandled messages and logged and discarded for the time being.  The only implemented message is a basic one that sends the needed info the the client side User Interface to pop up.
2022-11-27 01:24:35 -08:00
Jonathan Romano
af28d170fb Fix chat whitelist path in UserManager error log (#853) 2022-11-27 01:06:17 -08:00
David Markowitz
e2616c5f11 Move enums to a single directory
A technical change to move all emum files to a single directory
2022-11-26 14:22:00 -08:00
36eecd693d Brick stack sizes are now unlimited
Make brick stacks unlimited as they were in live.  If you have more than uint32_max bricks, the extra bricks are trashed.
2022-11-26 02:30:53 -08:00
Jonathan Romano
4569f62100 Fix three-part names coming across as INVALID with custom client path 2022-11-26 02:29:53 -08:00
Jonathan Romano
afb97a81b5 Address Mac CI using specific versions of OpenSSL
Corrected CI to use the version brew links in opt rather than the specific version in Cellar
2022-11-25 17:28:20 -08:00
Nico Mexis
b17ba56af1 Update workflow actions (#844) 2022-11-23 12:50:45 -06:00
Demetri Van Sickle
9d62a8cd0b Add backwards compatibility with servers using previous setup method
* MasterServer will nolonger require cdclient.fdb

* Added support for packed/unpacked clients not requiring .fdb file if .sqlite exsits
2022-11-21 14:19:37 -08:00
David Markowitz
416021c208 Remove need for Avant Gardens Survival Client Fix
This addresses the Avant Gardens Survival bug
Does not conflict with clients that have the fix.
2022-11-21 14:18:01 -08:00
3fa6ea4cea Fix ninjago crashes (#837)
Fixed reading speed from rail paths
Made the config of rail paths be read in sanely due to not having a type
Fixes #835
2022-11-14 13:57:49 -06:00
37524af549 fix trigger loading (#838)
Fixes #836
2022-11-14 12:55:40 -06:00
Jonathan Romano
53b559bef3 Make build script fail if any command fails (#832) 2022-11-14 08:08:49 -06:00
848c066924 Not every scene has triggers, that is normal (#831)
Quell the onslaught of meaningless logs
2022-11-12 08:44:37 -06:00
7429902a64 Prevent adding movingplatform components to all entites with an attached_path (#829)
* Stop adding movingpla comps where they aren't needed

* move stuff around to make it more congruent

* invert if else block logic patter
Since setting up the comp will be longer han just adding the path
will make the readability flow better

* address feedback
2022-11-12 08:44:27 -06:00
22e5d02400 Use Property path name and desc when claiming (#827) 2022-11-12 08:44:13 -06:00
cf7fa8e52d cleanup and define all unknowns in zone reading (#826)
* cleanup and define all unknowns in zone reading
fix for movement path config reading

* simplify reading and don't use intermediates

* fix spelling

* remove dup variable in struct
read to the proper name that relates to the enum
2022-11-12 08:44:03 -06:00
1eff3ae454 Add checks to AssetBuffers before they are used (#820)
* add checks to buffers before they are used
to avoid crashing

* address feedback
2022-11-10 12:59:31 -06:00
Jack Kawell
7c2437173b Fixed docker installation (#823) 2022-11-07 17:04:20 -06:00
Jonathan Romano
2570c74b71 Remove hardcoded port number in AuthPackets
Removes the hard coded port numbers in AuthPackets
2022-11-07 01:27:48 -08:00
Jonathan Romano
2f48981801 Address socket issues with MariaDB
Use a new method of determining how to send the connection information to the database
2022-11-07 01:26:15 -08:00
David Markowitz
1464762bcd Implement GTest and change windows output path
Implement GTest as a testing infrastructure.
Make windows output binaries to the build folder instead of the release type folder (potentially issue further down the line)
Add a simple unit test for DestroyableComponent
2022-11-07 00:12:35 -08:00
9c58ea5c41 add 1261 to the disable landing animation switch case (#819) 2022-11-05 19:09:39 -05:00
David Markowitz
1d5c71eb9b Fix Pet Taming causing seg fault (#818)
* Fix Pet Taming

* Fix Pet Taming

* fix pet taming path loading
just make it go to build file since the asset managet handles intermediate steps
there is never res in the path in the live db, so no need to check

* special case BrickModels to uppercase if unpacked
remove redundent variable

Co-authored-by: Aaron Kimbrell <aronwk.aaron@gmail.com>
2022-11-05 19:09:26 -05:00
162f84e285 simplify path fixing for packed vs unpacked (#816)
fix slashes for hasfile for unpacked client checking
2022-11-04 19:45:04 -05:00
David Markowitz
8880486c8b Fix chat message reads (#817)
* Fix chat message reads

* Fix teams
2022-11-04 12:28:19 -07:00
David Markowitz
8d37d9b681 Organize dScripts (#814)
* Organize dScripts

whitespace

Remove parent scope

Remove parent scope from initial setter

Remove debug

Remove helper programs

* Fix NtImagimeterVisibility script

Co-authored-by: aronwk-aaron <aronwk.aaron@gmail.com>
2022-11-03 12:57:54 -05:00
Jett
b974eed8f5 Make changes to certain database functions and a debug assert (#804)
- Replace all interaction of std::string and sqlString.
- Add a return before a debug assertion can be triggered by lvl chunks being loaded on server start.
2022-11-02 22:53:45 -05:00
David Markowitz
8edade5f98 Fix client paths (#811) 2022-11-02 20:30:35 -07:00
353c328485 compile fixes and default client_location (#809)
* support for gcc9 on ubuntu 18.04
This is needed to make filesystem work

* fix default for client location
2022-11-02 22:05:52 -05:00
Jett
4a6f3e44ee Add support for packed clients (#802)
* First iteration of pack reader and interface

* Fix memory leak and remove logs

* Complete packed asset interface and begin on file loading replacement

* Implement proper BinaryIO error

* Improve AssetMemoryBuffer for reading and implement more reading

* Repair more file loading code and improve how navmeshes are loaded

* Missing checks implementation

* Revert addition of Manifest class and migration changes

* Resolved all feedback.
2022-11-01 13:21:26 -05:00
David Markowitz
971e0fb3b6 Modularize gargantuan objects (#797) 2022-10-31 17:32:17 -05:00
David Markowitz
62213cd701 Implement basic functionality (#794)
Implements the basic functionality and parsing of property behaviors.

Unhandled messages and logged and discarded for the time being.  The only implemented message is a basic one that sends the needed info the the client side User Interface to pop up.

Tested that the User Interface properly shows up with zero behaviors on it.  No other functionality is changed.
2022-10-31 17:32:07 -05:00
David Markowitz
d4af7d76a2 Add property behaviors migration (#790)
* Add behaviors migration

Add migration for behaviors.  Tested that the tables get altered correctly, names are set correctly.

Tested that I can place models, both regular and Brick-by-Brick ones and that they get deleted properly.  Tested that picking up models and re-placing them down properly updates them in the tables.

* Only update when empty
2022-10-31 17:31:49 -05:00
David Markowitz
89fb66c4a9 Change AMFArray getters to use Templates and fix CI halting when one matrix fails (#796)
* Change AMFArray getters to use Templates

Move Template definition to header

* Add more tests

Add tests for casting to wrong template type
Add tests for going out of bounds in the array.

* Try continue-on-error

* Update build-and-test.yml

* Try continue-on-error

Update build-and-test.yml

* change version

* Update CMakeMariaDBLists.txt

Update CMakeMariaDBLists.txt
2022-10-30 13:06:05 -07:00
David Markowitz
906887bda9 Add automatic cdclient migration runner support and setup (#789)
* Add automatic migrations for CDServer

Add support to automatically migrate and update CDServers with new migrations.  Also adds support to simplify the setup process by simply putting the fdb in the res folder and letting the server convert it to sqlite.

This reduces the amount of back and forth when setting up a server.

* Remove transaction language

* Add DML execution
`poggers`
Add a way to execute DML commands through the sqlite connection on the server.

* Make DML Commands more robust

On the off chance the server is shutdown before the whole migration is run, lets just not add it to our "finished list" until the whole file is done.

* Update README
2022-10-30 00:38:43 -07:00
Jett
a745cdb727 Implement a shared config between servers (#795)
* Implement a shared config between servers

* Auto move config file on CMake run
2022-10-29 16:17:35 -07:00
David Markowitz
d8e73def9d Update GameMessages.cpp (#793) 2022-10-29 10:12:29 +02:00
Demetri Van Sickle
2bdbf129cf removed migration runner from build script (#788) 2022-10-25 15:32:46 -05:00
David Markowitz
c13937bd1f Address Brick-By-Brick builds not properly saving and make migrations automatic (#725)
* Properly store BBB in database

Store the BBB data in the database as the received SD0 packet as opposed to just the raw lxfml.  Addressed several memory leaks as well.

* Add Sd0Conversion

Add brick by brick conversion commands with 2 parameters to tell the program what to do with the data.

Add zlib -> sd0 conversion.  Files look good at a glance but should be tested in game to ensure stability.  Tests to come.

* moving to laptop

ignore this commit.  I need to move this to my laptop

* Add functionality to delete bad models

Adds functionality to delete bad models.  Models are batched together and deleted in one commit.

More testing is needed to ensure data safety.  Positive tests on a live database reveal the broken models were truncated and complete ones were kept around successfully.  Tests should be done to ensure larger sd0 models are properly saved and not truncated since this command should be able to be run any time.

Valgrind tests need to be run as well to ensure no memory leaks exist.

* Delete from query change

Changed from delete to delete cascade and instead deleting from properties_contents as opposed to ugc.

* Address numerous bugs

DELETE CASCADE is not a valid SQL command so this was changed to a better delete statement.

Added user confirmation before deleting a broken model.
Address appending the string model appending bad data, causing excess deletion.
Addressed memory leaks with sql::Blob

* Error handling for string

* Even more proper handling...

* Add bounds check for cli command

Output a message if a bad command is used.

Update MasterServer.cpp

* Remove user interference

-Add back in mariadb build jobs so i dont nuke others systems
- Remove all user interference and consolidate work into one command since 1 depends on the next.

* Add comments

test

Revert "test"

This reverts commit fb831f268b7a2f0ccd20595aff64902ab4f4b4ee.

* Update CMakeMariaDBLists.txt

Test

* Improve migration runner

Migration runner now runs automatically.
- Resolved an issue where extremely large sql queries caused the database to go into an invalid state.
- Made migrations run automatically on server start.
- Resolved a tiny memory leak in migration runner? (discarded returned pointer)
- Moved sd0 migrations of brick models to be run automatically with migration runner.
- Created dummy file to tell when brick migrations have been run.

* Update README

Updated the README to reflect the new server migration state.

* Make model deleter actually delete models

My complicated sql actually did nothing...  Tested that this new SQL properly gets rid of bad data.

* Revert "Update CMakeMariaDBLists.txt"

This reverts commit 8b859d8529.
2022-10-24 17:20:36 -05:00
8d44f2f5da Add missing property path checks for new zones (#783)
Co-authored-by: Jett <55758076+Jettford@users.noreply.github.com>
2022-10-24 00:54:21 -05:00
366c3db7fe fix reading respawn for older maps (#784) 2022-10-23 21:54:59 -05:00
David Markowitz
f02e9c0f6a Address being able to friend yourself (#779)
* Address being able to friend yourself

Fix an issue where players could friend themselves.  Also stops yourself as appearing as a friend on your own friends list.

* Send a Response instead

Send a MYTHRAN response since the player is attempting to friend a Mythran.
2022-10-21 19:35:12 -05:00
409d682c9d fix loading scenes in some older formats (#782)
This fix is based on lcdr's luzviewer
2022-10-21 19:34:38 -05:00
David Markowitz
63af2c8da7 Add ZLIB for Windows (#768)
Added ZLIB for Windows.  Packets for character creation are now compressed on windows before sending and ZCompression can now be used on Windows.
2022-09-05 20:28:47 -07:00
Jett
ce2e6f595b Resolve incorrectly marked consumables being unusable (#770)
A change was made in the mounts pull request that broke consumables without correctly marked types such as the picnic basket
2022-09-05 17:28:32 -05:00
c552f46780 ignore empty.lua and empty scripts (#769)
* ignore empty.lua and empty scripts
and return early if it's an ignored script

* return it else if logic
2022-09-04 21:43:16 -05:00
14d4bf3cc5 Script for aborting a wbl zone transfer (#766) 2022-09-02 13:49:38 -05:00
26f2eb409f Mounts v2 (#726)
* Mounts -v2

* fix stun state and make comments a bit nicer

* remove extra serilization

* update the char position a bit more correctly

* make vehicles face thr player's direction

* address feedback

* fix compiling for real this time

* removed uneeded check
2022-09-02 13:49:19 -05:00
1af3e59348 Scripts for the AG sentinel camp QB wall (#761)
* Scripts for the AG sentinel camp QB wall

* use lookat

* Address feedback

* Fix stromling spawner

* fix aggro and remove logs

Co-authored-by: Jett <55758076+Jettford@users.noreply.github.com>
2022-09-01 21:44:26 -05:00
David Markowitz
e3077aa410 Fix Windows not working due to libbcrypt not working on Ninja (#765) 2022-09-01 19:24:00 -07:00
3b75ecc0b4 Add script to playfx on canisters before consoles are active (#754)
* Add script to playfx on canisters before consoles are active

* remove debug stuff
2022-08-27 21:48:03 -05:00
b70e7334e8 Parrot crash script to become a sneaky ninja and steal the pirate's booty (#752) 2022-08-26 22:58:41 -05:00
500b7885e2 Add pirate rep script (#751)
* Add pirate rep script

* fix formattimg
2022-08-25 21:09:08 -05:00
Demetri Van Sickle
bc132487e9 Updated README (Formatting and flow) (#744)
* Updated flow of database section

* Changed bolded headers to actual headers

Will now allow you to link to them

* Updated Linux build command to match build script

* Updated database wording
2022-08-25 14:16:20 -07:00
47f0830483 Add GF geyser script (#749)
* Add GF geyser script

* remove uneeeded include

* const
2022-08-25 15:51:22 -05:00
e707207ffa Add FV Geyser script (#748)
* Add FV Geyser script

* remove uneeded include

* const
2022-08-25 15:50:13 -05:00
David Markowitz
ceb374591f Move mailbox closing to its script (#740) 2022-08-18 19:42:52 -07:00
David Markowitz
c05562a227 Modularize CMakeLists for submodules (#736)
* Use RecastNavigation CMakeLists

* Use tinyxml2 CMakeLists

* Use bcrypt CMakeLists

* Move variable init to CMakeLists

This has to be done here to prevent missing dependency errors.

* General improvements

Only link dynamic if on gnu
use more thirdparty cmakes

* Disable tinyxml2 testing
2022-08-18 19:23:42 -07:00
f8c1e2fb52 Script for when archway rebuild is done (#739) 2022-08-18 15:33:32 -05:00
e4a15a0f2e Add imagimeter visibility script (#738) 2022-08-18 00:09:14 -05:00
Daniel Seiler
dd8091f60e Hide dependency compilation warnings (#696)
* Hide raknet compilation warnings

* Move out MariaDB Connector/C++ logic

* remove mariadb warnings?

* hide mariadb cmake warnings?
2022-08-17 01:43:54 -07:00
David Markowitz
50b3946548 Fix death planes (#735)
* Correct death plane size

The death plane file size is not in units but is actually in 4x2 tiles.

* Make it a bit bigger for now

* Enjoy your crust

"These things add flavor they said"

Move the position of the death barrier down 13.521004 units so we effectively only extend its hitbox in the -Y direction as opposed to the +Y direction, resolving an issue in Battle of Nimbus Station where the death plane was too tall
2022-08-16 22:28:50 -05:00
976bd3c41b Selective saving for map and location (#732)
* Don't save the map and char location info if
we are in an instanced 
* LUP worlds will be handled in a future PR
* simplify check
2022-08-16 20:53:28 -05:00
David Markowitz
3b7f1dad54 Fix death planes (#733)
* Correct death plane size

The death plane file size is not in units but is actually in 4x2 tiles.

* Make it a bit bigger for now
2022-08-16 18:53:01 -07:00
Demetri Van Sickle
54021458bd Change build command in build script (#729)
The script now uses the cmake build as to be compatible with all platforms as opposed to just platforms that supported gnu make.
2022-08-16 01:49:44 -07:00
Emmett
1e1b6aaa0b Update Docker.md submodule note (#730)
* Update Docker.md 

Changed note to recursively update git submodules, otherwise would lead users into #728
2022-08-14 11:05:07 -07:00
David Markowitz
008f953003 Add physics volume for property orb (#718) 2022-08-08 09:34:56 -05:00
David Markowitz
dc960cb99c Fix landing animation (#720) 2022-08-08 09:34:33 -05:00
2d0faae759 Merge pull request #719 from DarkflameUniverse/unix-line-endings
Unix line endings
2022-08-08 09:33:43 -05:00
932d8030f0 update git blame ignore 2022-08-08 08:31:44 -05:00
Zac Hayes
7f5ab8b9fa Dockerfile: Copy dNavigation to build dir (#722)
Fixes an issue where new directory was not copied over to the correct folder for Docker
2022-08-06 22:59:27 -07:00
Jett
6c97ea8208 Implement flying command (#713)
* Implement flying command

* Add documentation.
2022-08-06 01:19:34 -07:00
72477e01e2 convert to unix line endings 2022-08-05 22:01:59 -05:00
David Markowitz
ea86988521 Revert dZoneManager Initialization order (#717) 2022-08-05 19:20:11 -07:00
d626ac1ed4 Merge pull request #714 from DarkflameUniverse/macro-formatting
Macro formatting consistency
2022-08-05 12:37:29 -05:00
168f837b94 add blame ignore 2022-08-05 08:40:59 -05:00
9e4ce24fd2 add semi-colons to macros consistently 2022-08-05 08:40:12 -05:00
Jett
4112a85906 Fix checks for if the physics world is loaded (#711) 2022-08-05 07:41:07 -05:00
David Markowitz
408163ed35 Add windows docker setup guide to README (#712)
* Add docker windows

* Update README.md
2022-08-05 07:40:27 -05:00
aequabit
4556f13474 Mention option to use Docker in README.md (#702) 2022-08-05 01:04:45 -07:00
Jett
88f316bf93 Add null checks to all free calls to prevent crash on server close. (#709) 2022-08-04 08:54:14 -05:00
Jett
e6c7f744b5 Implement terrain file reading to generate navmeshes in the future (#703)
* Implement terrain file reading to generate navmeshes in the future

* Make Emo's suggested changes.
2022-08-04 01:59:47 +01:00
Daniel Seiler
d2b05a1ac5 Update Diagnostics.cpp (#697) 2022-08-02 08:56:50 -05:00
Daniel Seiler
a429489846 use UTF8ToUTF16 more (#695) 2022-08-02 08:56:20 -05:00
Jett
9ee219ea42 Move Navmesh code away from dPhysics (#701) 2022-08-02 06:30:19 +01:00
a0aa8b2854 standardize line endings (#700) 2022-08-01 22:37:28 -05:00
Jett
c11a4a67d1 Replace the vsprintf used in the logger with vsnprintf. (#694) 2022-08-01 15:23:01 -05:00
Jett
c69d01d77b Merge pull request #688 from DarkflameUniverse/reporter_id_fix
Remove parentheses from ADD reporter_id
2022-07-31 21:06:01 +01:00
Daniel Seiler
50cb9346b8 Merge pull request #689 from DarkflameUniverse/security-policy
Add Security Policy
2022-07-31 20:03:30 +02:00
Gie "Max" Vanommeslaeghe
17d77db1c6 Update SECURITY.md 2022-07-31 15:14:16 +02:00
Daniel Seiler
e97dc6fbff [no ci] update link to darkflame-security-announce 2022-07-31 14:06:05 +02:00
Daniel Seiler
7ec458421f Create SECURITY.md 2022-07-31 13:58:50 +02:00
0b9e97625e Remove parentheses from ADD reporter_id 2022-07-30 22:09:45 -07:00
David Markowitz
d64fa1680d Fix missions re-ordering on reload (#686)
* Fix missions re-ordering on reload

Check for success rather than failure

* Add a comment

* Get base value from database

* Update Mission.h
2022-07-30 20:56:21 -07:00
eddytronpie
f80a26a944 Fix integer issue with BricksCollected (#679)
This fixes an issue where BricksCollected goes to an insane number after selling more bricks than you collected in the area
2022-07-29 20:41:14 -07:00
David Markowitz
26ddeaa429 Fix NPC Proxy items (#684)
* Fix racing lap times

* Address NPC proxies

NPCs are supposed to equip the sub items of items they equip and were not doing so.  This PR adds this functionality and fixes and issue where Neido on Crux Prime was not wearing their sword.

Tested that Neido has their sword and that other NPCs that wear proxies also get their proxies equipped.  Had no issues with any other world crashing.
2022-07-29 19:00:36 -05:00
8b386ae6c5 Merge pull request #685 from DarkflameUniverse/editorconfig
Editorconfig and codebase format
2022-07-29 12:23:27 -05:00
f284e5a6e1 fix filename 2022-07-28 11:35:57 -05:00
1b01abd7d9 Merge branch 'main' into editorconfig 2022-07-28 09:27:06 -05:00
0e46b875a5 blame ignore and contributing update 2022-07-28 08:47:28 -05:00
19e77a38d8 format codebase 2022-07-28 08:39:57 -05:00
David Markowitz
adb6a2c609 Fix racing lap times (#683) 2022-07-27 20:54:42 -07:00
4f7aa11067 add editorconfig 2022-07-27 22:33:36 -05:00
Jett
ffd4477081 Increment DLU patch version 2022-07-27 10:08:04 +01:00
a632ef8ccd Clean up format logs (#682) 2022-07-26 23:52:53 -07:00
Jett
9e08bb20d2 Implement proper bounds checks across the codebase (#681)
* Implement proper bounds checks across the codebase

* Implement strnlen_s for cross platform
2022-07-26 20:52:04 -05:00
Daniel Seiler
9813c3ed2c Better Unicode support in GeneralUtils (#658)
* ASCIIToUTF16: output replacement character instead of failing assert

* Add GeneralUtils::_NextUTF8Char

* Implement GeneralUtils::UTF8ToUTF16

* use string_view everywhere

* use string_view::front instead of begin

* Add PushUTF16CodePoint
2022-07-25 21:11:30 -07:00
e97ae92624 Make logger automatically put a newline (#675)
at the end of the line
remove all the newlines in log calls
2022-07-24 21:26:51 -05:00
a7fb6eb3f3 make LoadFromXml usage consistent across comps (#673) 2022-07-24 21:03:22 -05:00
9ed4a4f47f Remove uneeded include (#674) 2022-07-24 16:17:01 -05:00
b57cacc676 Player forced movement component (#672)
* Split out Level progression component
from Character Component
This is to get to the Player forced movement Comp in a sane way

* move XML to component insted of abusing charComp

* use overrides
should probably make everything that calls that call it correctly

* fix linking issue

* Add proper Player Force movement component
Not used, yet
2022-07-24 13:25:10 -05:00
f2d1c5d26d Split out Level progression component (#671)
* Split out Level progression component
from Character Component
This is to get to the Player forced movement Comp in a sane way

* move XML to component insted of abusing charComp

* use overrides
should probably make everything that calls that call it correctly

* fix linking issue
2022-07-24 13:04:02 -05:00
David Markowitz
ef0a3c6d0b Add Hot Properties struct and address some whitespace (no functionality change) (#667)
* Add GameMessages

* General AMF cleanup

Proper memory management as well as style cleanup

* General AMF cleanup

Proper memory management as well as style cleanup

* General optimizations

Fix AMFArray so values are properly deleted when you leave the scope it was created in.
Add bounds check for deletion so you don't double delete.
Remove all AMFdeletions that are contained in an array since the array now manages its own memory and deletes it when it is no longer needed.

* Better tests and fix de-serialize

Fix de-serialize to be correct and implement a test to check this

* Update AMFDeserializeTests.cpp

* Update GameMessages.h

* Add GM

* Comment out function

* Spacing

* eof
2022-07-22 19:58:20 -07:00
David Markowitz
6a38b67ed5 General AMF cleanup (#663)
* General AMF cleanup

Proper memory management as well as style cleanup

* General optimizations

Fix AMFArray so values are properly deleted when you leave the scope it was created in.
Add bounds check for deletion so you don't double delete.
Remove all AMFdeletions that are contained in an array since the array now manages its own memory and deletes it when it is no longer needed.

* Better tests and fix de-serialize

Fix de-serialize to be correct and implement a test to check this

* Update AMFDeserializeTests.cpp

* Update AMFFormat.cpp
2022-07-21 22:26:09 -07:00
5523b6aafc Refactor UpdateEntities to not lose items if we add them while processing (#664)
* if we are deleting entities, and we add an entity
to delete, dont throw it out

* made it all uniform

* change update back to how it was
since it's an unordere map and
wouldn't be guaranteed to update even in this secnario
2022-07-21 21:09:25 -05:00
David Markowitz
40a9aefb5b Aggro radius (#665) 2022-07-20 20:26:52 -07:00
Jett
91f2cebcc7 Merge pull request #661 from EmosewaMC/bons-fixes
Use Aggro and Tether radii settings from Entity Settings
2022-07-20 10:10:57 +01:00
David Markowitz
45a7dbdadd Add Unimplemented GameMessages (#662) 2022-07-20 01:28:57 -07:00
Daniel Seiler
74bca38253 MSVC: set source / target encoding (#659) 2022-07-20 01:23:53 -07:00
EmosewaMC
082a2a418f Use radii from settings
Override the DB aggro and tether radii from the settings if they are present.
2022-07-19 23:25:50 -07:00
David Markowitz
835cf2b794 Add an AMF Deserializer as well as corresponding Unit Tests (#599)
* Add AMFDeserializer

Add an AMFDeserializer

Reverted unrelated changes

Add unit tests for AMFDeserializer

Added unit tests for the AMFDeserializer

Finish tests

Finish the AMF deserializer tests.  This commit finishes the positive test case and implements a load test case that is expected to take less than 1.5 seconds to process.

Modularized tests

Made tests a bit modular and split into more methods

Specified binary read from file

Specified that on the IO stream we are reading a binary file otherwise windows will terminate reading the binary file on seeing a 1A byte.

Added more tests

Added tests for unimplemented values and edited a test file to be more modular

Updated test text

Fix spacing

Update AMFDeserializeTests.cpp

* Update CMakeLists.txt

* Update AMFDeserializeTests.cpp

f

Actually follow the AMF spec

Update AMFDeserializeTests.cpp

tabs

Add in commented tests

* Follow spec

formatting

Add Integer Tests

Follow Spec more

Follow spec

* Use unique_ptr

* Update AMFDeserialize.cpp

Semantics

Update AMFDeserialize.cpp

Add new lines to EOF

CMake fix

* Add better std string read

Co-authored-by: Daniel Seiler <xiphoseer@mailbox.org>

* make not static

Co-authored-by: Daniel Seiler <xiphoseer@mailbox.org>
2022-07-19 21:51:05 -07:00
David Markowitz
74343be871 Enable _dynamic by default (#656) 2022-07-19 16:52:39 -05:00
David Markowitz
ed5ced0bed Fix Model Component Serialization (#655)
* Fix model component serialization

* Update ModelComponent.h
2022-07-19 16:51:35 -05:00
3dfe363a6b Added Aronwk and Simon to the readme (#657)
* Added myself and Simon to the readme

Me, since I've started to work on implementing mounts again.
Simon for his work in Reverse engineering the client which has been helping over the years.
Venture Vision and moving platforms/simple movers being two recent things that his RE has helped fix.

moved the special thanks out a header at the suggestion of Xipho and Max, since these people have not directly contributed to the DLU codebase.
made a section under the DLU team recognizing Blaster for the Logo that DLU uses
bumped up the credits header to make formatting make more sense

* Update based on feedback

Credit Blaster builder as they requested.
Remove duplicate entries for under DLU Team as requested
2022-07-19 09:29:26 -05:00
Jett
8e5da2cf1f Merge pull request #652 from DarkflameUniverse/blacklist-and-chat-changes
Blacklist and chat changes
2022-07-19 10:40:44 +01:00
Demetri Van Sickle
ec4ed8fa7e Adding migration command to build script (updated) (#653)
* Added checks for migration runner

* Added migration command to build script
2022-07-18 18:44:21 -05:00
David Markowitz
b55606d41e Fix the issue where we would create new worlds on ports that were still being used (#625)
* Wait for world to shutdown

We need to wait for the message that the world has shutdown before shutting it down.

* Dont sent people to dead instances

* Added shutting down check

Added check for isShuttingDown

* Update when we remove from master
2022-07-18 18:08:33 -05:00
Jett
69a0d5a50b Efficiency and naming changes. 2022-07-18 10:01:43 +01:00
Jett
945e572493 Add best friend check and complete blacklist 2022-07-17 09:40:34 +01:00
ef8c2a40f3 Framework for GM's and helpers for mounts (#651)
* Framework for GM's and helpers for mounts

* docs and spacing

* whitespace
2022-07-17 02:35:11 -05:00
Jett
fab8a1e982 Implement new chat features 2022-07-17 07:54:36 +01:00
Jett
0d4f86b20b Resolve missing RakNet replacement (#650)
Repair issue from PR earlier, crucial fix.
2022-07-17 06:57:00 +01:00
David Markowitz
c689b3d3d1 Parent and Child Deletion Improvements (#649)
* Fix timers

* Update Entity.cpp

* Fix timers

Fix timers

Remove debug logs

remove _dynamic

* I like to move it move it

* Child Deletion Improvements

* Check bounds
2022-07-16 21:39:13 -07:00
Jett
77d35019cc Replace the usage of RakString (#648) 2022-07-17 04:40:46 +01:00
9287e5bc4b Split itemType enum into it's own header (#647)
* Split itemType enum into it's own header
add mount item type

* fix whitespace
2022-07-16 20:36:09 -05:00
David Markowitz
f5ae5aa13e Address timers being iterated through poorly (#646)
* Fix timers

* Update Entity.cpp

* Fix timers

Fix timers

Remove debug logs

remove _dynamic

* I like to move it move it
2022-07-16 20:21:35 -05:00
Jett
df0f11c95b Update CMake configuration for easier maintenance (#642)
* Update CMake configuration for easier maintenance

* Incorrect casing fix

* Move package requirement

* Update CTest linking

* Add logs to the CMake

* Add linking for common libraries

Added linking for common libraries in tests subdirectory.

* Move test subdirectory higher up for some reason

* Whitespace a log removal

Missed new line

* Add dCommon to dChatFilter

* Update library output dir

* Correct libBcrypt

* Further refactor CMake behaviour

* Repair bad comments and update library defines

* Revert to old include directory method

* Implement platform defines

* Add missing include

Mac needs a specific include for defining platform.  Does not compile without this.

Co-authored-by: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com>
2022-07-17 00:24:16 +01:00
Jett
9c0819de4f Add MacOS building to the Github Actions (#643)
* Add MacOS to CMakePresets.json

* Update workflow to run MacOS builds

* Update test and build presets

* Add libssl install to integration

* Update workflow to install libssl and openssl

* Prevent brew running as super user
2022-07-16 22:55:54 +01:00
David Markowitz
3d46d703b2 Remove memory leak in player container and warning in Behavior (#640)
* Add friends list migration

* Change friends to use charID

Update friends table to use charID and not LWOOBJID variant.

* Fix remove friend

Fix remove friend and make the query more readable at a glance.

* Add and remove friends in the container

Properly add and remove friends in the player container

* add enums

* Add best friends and basic GM support V1

* Add more features

* not online / doesnt exist implementation

Implements the not online and invalid character response codes

* Address players not being removed

Fix an issue where players would not be marked as offline in the friends list due to the message not being sent in all circumstances.

Tested changes on 3 clients, switching characters, logging out from character select, switching characters, world transfer and my friends list looked as it was supposed to.

* Implement proper friends system

Remove debug logs

Track count of best friends

Add best friends list cap of 5

Add config option and best friend update

Add a config option and implement the last missing best friend serialization

Added comments and fixed remove best friend bug

Added some comments and addressed an issue where removing best friends would not remove them from your internal count of friends.

properties and logs fixes

whoops, had an issue

send reply if already BFFs

Send the correct objectID

I really need to rename these

Fix white space

goon

* Replace queries with unique ptrs

* remove user from player container on deletion

Remove the user from the player container when they delete their character.

* Bump patch version

* Improvements to PlayerContainer

Resolved a memory leak in the player container, removed commented out code and resolved a warning in Behavior.cpp

* Make it a unique ptr

* Improvements to PlayerContainer

Resolved a memory leak in the player container, removed commented out code and resolved a warning in Behavior.cpp

Make it a unique ptr

* Update PlayerContainer.cpp
2022-07-13 09:11:24 -07:00
David Markowitz
9ba297dd2e Add code to complete hidden property mission (#641) 2022-07-13 09:10:02 -07:00
David Markowitz
ccb9f7c499 Move instruction for database
Move the instruction for running the MasterServer migration down to where the command will actually work as well as use a more syntactically correct statement
2022-07-12 20:45:25 -07:00
David Markowitz
24dbd3944d Friends List Overhaul (#630) v103
* Add friends list migration

* Change friends to use charID

Update friends table to use charID and not LWOOBJID variant.

* Fix remove friend

Fix remove friend and make the query more readable at a glance.

* Add and remove friends in the container

Properly add and remove friends in the player container

* add enums

* Add best friends and basic GM support V1

* Add more features

* not online / doesnt exist implementation

Implements the not online and invalid character response codes

* Address players not being removed

Fix an issue where players would not be marked as offline in the friends list due to the message not being sent in all circumstances.

Tested changes on 3 clients, switching characters, logging out from character select, switching characters, world transfer and my friends list looked as it was supposed to.

* Implement proper friends system

Remove debug logs

Track count of best friends

Add best friends list cap of 5

Add config option and best friend update

Add a config option and implement the last missing best friend serialization

Added comments and fixed remove best friend bug

Added some comments and addressed an issue where removing best friends would not remove them from your internal count of friends.

properties and logs fixes

whoops, had an issue

send reply if already BFFs

Send the correct objectID

I really need to rename these

Fix white space

goon

* Replace queries with unique ptrs

* remove user from player container on deletion

Remove the user from the player container when they delete their character.
2022-07-12 20:36:06 -07:00
Jett
5888c9f468 Merge pull request #635 from DarkflameUniverse/improve-cpplinq-min-max-checks
Improve cpplinq checks
2022-07-12 11:17:59 +01:00
Jett
c9cd7a200a Merge pull request #634 from DarkflameUniverse/migration-runner
Add a argument to the MasterServer for running migrations
2022-07-12 11:17:42 +01:00
David Markowitz
b7497a47e4 Lower memory usage of Behavior Parameter Table by 10MB (#627)
* Added caching for table

Added caching for table

Add more caching

Update MasterServer.cpp

grds

Update CDBehaviorParameterTable.cpp

Update CDBehaviorParameterTable.h

Update CDBehaviorTemplateTable.cpp

Update Behavior.cpp

Update Behavior.cpp

change to map

Remove redundant query

* Remove include

* change to enum

* Update Behavior.cpp

* Use already cached table

* Update Behavior.cpp

* Reduce memory usage

Reduces the memory usage for the BehaviorParameter table by 10MB in memory.

* Update CDBehaviorTemplateTable.cpp
2022-07-11 20:43:09 -07:00
Jett
bfa1f57158 Improve cpplinq checks
On certain Windows header versions defining NOMINMAX doesn't work for some odd reason.
2022-07-12 03:06:54 +01:00
Jett
d642de9462 Implement a migration runner 2022-07-12 02:16:08 +01:00
David Markowitz
06217ad5e3 Address friends list IDs and removal of friends (#628)
* Add friends list migration

* Change friends to use charID

Update friends table to use charID and not LWOOBJID variant.

* Fix remove friend

Fix remove friend and make the query more readable at a glance.

* Add and remove friends in the container

Properly add and remove friends in the player container
2022-07-10 17:59:07 -07:00
David Markowitz
325dc5a571 Revert "Wait for world to shutdown (#624)" (#626)
This reverts commit 66edf57b02.
2022-07-09 15:57:45 -07:00
David Markowitz
66edf57b02 Wait for world to shutdown (#624)
We need to wait for the message that the world has shutdown before shutting it down.
2022-07-09 15:27:20 -07:00
David Markowitz
485de6173a Added caching for behavior parameter table (#621)
* Added caching for table

Added caching for table

Add more caching

Update MasterServer.cpp

grds

Update CDBehaviorParameterTable.cpp

Update CDBehaviorParameterTable.h

Update CDBehaviorTemplateTable.cpp

Update Behavior.cpp

Update Behavior.cpp

change to map

Remove redundant query

* Remove include

* change to enum

* Update Behavior.cpp

* Use already cached table

* Update Behavior.cpp
2022-07-08 23:07:52 -07:00
dddc33607b remove unused code and callbacktimers in testmap (#620) 2022-07-08 22:25:44 -05:00
3865a186a7 Possessor and possessable additions (#619)
* possessor-fixup and possessable additions

* comment and docstring fixes

* fix possessable initialization

* split animation flags into it's own header
remove unnecessary checks
2022-07-08 22:25:15 -05:00
David Markowitz
22b2516107 Fix nested preconditions not evaluating costs (#618)
Fixed an issue with some builds that had preconditions not taking items from the players due to the evaluate costs parameter not being passed to nested conditions.

Tested the build in Avant Gardens and it now correctly takes items from the player upon completion.
2022-07-06 19:29:15 -07:00
David Markowitz
0734760d42 Add openssl to list of package requirements
I forgot to add this to the list of needed packages.
2022-07-06 12:05:42 -07:00
David Markowitz
138fffda2c Fix item collection missions (#617)
* Implement Precompiled Headers

* fix cmake

* Fix modular builds not returning parts

Modular builds would not search inventory A for their corresponding item and by default would only look in the models bag.  This PR forces the item to be looked for in the inventory its coming from (inventoryA) as a second resort before doing the final search in the default inventory of the item.

Tested modular building a car and a rocket and when replacing parts the part that was already placed was returned to the inventory correctly.

* Push equipped items upon entering build mode

Fixes an issue where leaving build mode anywhere would not re-equip your items.  This also implements the feature to set your stats back to full, as was done in the live game.

Tested exiting build mode on a property with full venture gear and all gear was re-equipped and stats were set to the expected values.

* Fix item collection missions

Item collection missions are only supposed to take items should they be in the items inventory or the hidden inventory and no others.  This change removes the global inventory find of items and only removes it from the two inventories that items get taken from in live, ITEMS and HIDDEN

Tested completing mission 470 and 477 as well as 622 and the correct items were taken or not taken, based on the inventory the target item was in.
2022-07-06 08:54:41 -07:00
David Markowitz
de5d9182eb Address items not re-equipping upon exiting build mode (#615)
* Implement Precompiled Headers

* fix cmake

* Fix modular builds not returning parts

Modular builds would not search inventory A for their corresponding item and by default would only look in the models bag.  This PR forces the item to be looked for in the inventory its coming from (inventoryA) as a second resort before doing the final search in the default inventory of the item.

Tested modular building a car and a rocket and when replacing parts the part that was already placed was returned to the inventory correctly.

* Push equipped items upon entering build mode

Fixes an issue where leaving build mode anywhere would not re-equip your items.  This also implements the feature to set your stats back to full, as was done in the live game.

Tested exiting build mode on a property with full venture gear and all gear was re-equipped and stats were set to the expected values.
2022-07-06 01:30:13 -07:00
David Markowitz
3cf243b1d7 Address modular build not returning parts upon switching some out (#614) 2022-07-05 23:18:04 -07:00
David Markowitz
8cdb388915 Optimize scripts for faster compilation (#597)
* Implement Precompiled Headers

* First volume of optimizations

* Scripts A-B

Gonna be doing this in alphabetical order now.

* C Scripts and remove unneeded includes from base cppscripts header

Remove the MissionComponent and Loot includes from all base scripts and place their needed includes in the respective scripts.

* D scripts

* F scripts

* F scripts 2

Finish up removing extraneous includes from scripts that start with the letter F

* G scripts

Removing extraneous includes from scripts that start with the letter G

* I scripts

Removing extraneous includes from scripts that start with the letter I

* M-Z scripts

Removing extraneous includes from scripts that start with the letter M-Z

* Revert "Implement Precompiled Headers"

This reverts commit d79d8d4991.

* Revert "Revert "Implement Precompiled Headers""

This reverts commit 0597faf308.

* Add back in PCH

Add back in PCH

* Fix CMake

Whitespace

Remove duplicate file glob

Remove newline
2022-07-04 23:00:10 -07:00
David Markowitz
cc25ec0151 Add Venture Vision Behavior (#609)
Add the Venture Vision behavior and associated functionality.  Pet digs still do not show up however.

The Kit bonus for factions have been tested and properly grant and take away the buff when it is casted and uncasted.  Tested as well using multiple Venture Vision behaviors at once and the vision only went away when there were zero equipped at once.

Remove extra includes

Convert to Tabs

Remove extra forward declaration
2022-07-04 21:48:56 -07:00
David Markowitz
8a54e7ccd2 Implement Precompiled Headers (#591)
When applied, this will speed up compile times dramatically.
2022-07-04 15:24:45 -07:00
Daniel Seiler
6e2936504c Improve CI (#345)
* Don't upload artifacts unless on main

* Fix if/endif mismatch warning

* Add thirdparty CMakeLists

* Keep more warnings around

* Remove more RakNet warnings

* Fix indentation and divided the cmake into libraries and bins

- Each library and binary got their own CMakeLists.txt
- Indentation was fixed everywhere
- Weird if statement flows replaced

* Revert "Fix indentation and divided the cmake into libraries and bins"

This reverts commit 005a12424e.

* Add async value assignments

Resolves a warning where on some compilers this thread would _not_ be run async and would instead be run synchronous with the main thread, halting execution.

* Revert "Add async value assignments"

This commit was meant to be done on a seaparate branch but was accidentally pushed upstream to this branch.

* Fix Merge Conflict

* Resolve errors

Resolve errors with using continue() outside a foreach loop.

* breakout mariadb to thirdparty cmake

Move the mariadb cmake to its own directory to make each cmake file more focussed.

Co-authored-by: Jett <55758076+Jettford@users.noreply.github.com>
Co-authored-by: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com>
2022-07-04 01:30:11 -07:00
jumpy-badger
eaa962f265 Add Aarch64 support (#231)
* added mariadb-connector-cpp submodule

* raknet aarch64 support

* fix compile errors

* mariadb connector swap (in progress)

* update CMakeLists, add preprocessor definition to switch between mysql and mariadb connectors

* update types with missing aarch64 check

* corrected adding extra flag to properly compile mariadbconn in CMakeLists

* updated readme with arm builds section

* fix build failure if test folder does not exist

* Remove mysql connector from all builds, add mariadbconnector to windows build

* readd Linux check for backtrace lib to CMakeLists.txt

* Separate system specific mariadbconncpp extra compile flags

* Copy dlls to exes directory once built

* fetch prebuilt binaries on windows so that ClangCL can be used

* Delay load dll so that plugin directory is set correctly

* Fixed typo in glibcxx compile flag

* whitespacing, spaces -> tabs

* Updated README.md, included instructions to update

* Updated README.md

added libssl-dev requirement and removed mysql connector references from macOS builds section

* apple compile fixes for zlib and shared library name

* add windows arm64 checks to raknet

* remove extra . in shared library location

* Setup plugins directory for the connector to search in, pass openssl_root_dir on for apple

* Fix copy paths for single config generators and non windows

* change plugin folder location, another single config generator fix

* GENERATOR_IS_MULTI_CONFIG is a property not a variable

* Fixed a few errors after merge

* Fix plugin directory path, force windows to look at the right folder

* fixed directory name for make_directory command

* Update README.md

Updated MacOS, Windows build instructions.

* set INSTALL_PLUGINDIR so that the right directory is used

* Support for relative rpath for docker build

* added mariadb-connector-cpp submodule

* raknet aarch64 support

* fix compile errors

* mariadb connector swap (in progress)

* update CMakeLists, add preprocessor definition to switch between mysql and mariadb connectors

* update types with missing aarch64 check

* corrected adding extra flag to properly compile mariadbconn in CMakeLists

* updated readme with arm builds section

* fix build failure if test folder does not exist

* Remove mysql connector from all builds, add mariadbconnector to windows build

* readd Linux check for backtrace lib to CMakeLists.txt

* Separate system specific mariadbconncpp extra compile flags

* Copy dlls to exes directory once built

* fetch prebuilt binaries on windows so that ClangCL can be used

* Delay load dll so that plugin directory is set correctly

* Fixed typo in glibcxx compile flag

* whitespacing, spaces -> tabs

* Updated README.md, included instructions to update

* Updated README.md

added libssl-dev requirement and removed mysql connector references from macOS builds section

* apple compile fixes for zlib and shared library name

* add windows arm64 checks to raknet

* Setup plugins directory for the connector to search in, pass openssl_root_dir on for apple

* Fix copy paths for single config generators and non windows

* change plugin folder location, another single config generator fix

* GENERATOR_IS_MULTI_CONFIG is a property not a variable

* Fixed a few errors after merge

* Fix plugin directory path, force windows to look at the right folder

* fixed directory name for make_directory command

* Update README.md

Updated MacOS, Windows build instructions.

* set INSTALL_PLUGINDIR so that the right directory is used

* Support for relative rpath for docker build

* Rebase on main

* Remove extra git submodule

* Update CMakeLists.txt

* Remove CMakeLists.txt file from mariadb

Remove the CMakeLists.txt file from the mariaDBConnector so we dont build the tests.  Also add a config option to the CMakeVariables.txt so you can build the connector with multiple jobs

* Compile on windows

Specify the mariadbcpp.dll file location with a defined absolute path so windows knows it actually exists.

* default to 1 job

Default mariadb jobs running in parallel to 1 instead of 4

* Move mariadbcpp.dll file to the expected directory on windows

* Changed plugin

Updated the plugin location from the project binary directory to the expected location, the mariadb binary directory.

* Addressed windows dll issues by moving files to the expected directory instead of a directory that wouldnt get created

* Update README

Co-authored-by: Aaron Kimbrell <aronwk.aaron@gmail.com>
Co-authored-by: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com>
2022-07-03 21:33:05 -07:00
1497d9b35a breakout possessor from char comp (#606)
* breakout possessor from char comp
Use the correct component for possessor
cleanup scirps that were using possessor improperly
beginnings of mounts

* fix comments
added bounds check
2022-06-29 18:50:24 -05:00
David Markowitz
a55162775e Address incorrect stun played by growl speakers (#605)
Add the FireFirstSkillonStartup script to allow for scripts that use this to function.

Add comments

Fix QB Stunner scripts

Use SetVar for variable

Remember that variables for scripts need to be stored in the entity since a script can be used across multiple entities.

Remove unused variable

Specify Unsigned Int

Start skill asap, not next tick
2022-06-28 23:17:45 -07:00
David Markowitz
670a2de95b Address issue with Inventor Beehive and Buccaneer Monkey ability on valiant weapon (#604)
* Add Script

Add the FireFirstSkillonStartup script to allow for scripts that use this to function.

* Add comments
2022-06-27 21:36:18 -07:00
94e161df55 Address players leaving Battle of Nimbus Station causing a crash that wont save (#600) 2022-06-24 15:26:09 -05:00
David Markowitz
06dc18fb49 Merge pull request #594 Add new contributors to contributions list
Add new contributors to contributions list
2022-06-22 16:58:38 -07:00
Jett
00f7a5c4d6 Update README.md 2022-06-22 08:57:36 +01:00
5dd4086bd5 yoink
I just want mounts to work, this isn't fun
2022-06-21 20:10:44 -05:00
1b222a64c3 removing myself from the situation 2022-06-21 20:07:44 -05:00
Jett
6a7c6da01a Update to simpler list. 2022-06-22 00:35:24 +01:00
Jett
9bfff533c3 Update Darwins link on the README 2022-06-22 00:04:45 +01:00
Jett
8e9c48cce0 Update README.md 2022-06-21 23:57:47 +01:00
Jett
fb81c0c9a2 Update CREDITS.md with more accurate information 2022-06-21 09:04:31 +01:00
Jett
c0d05b00df Replace list with new formatting 2022-06-21 09:03:31 +01:00
Jett
ef0873075f Reflect the same order as that in the CREDITS.md file 2022-06-21 07:04:41 +01:00
David Markowitz
c89f420204 Merge pull request #593 Fix issue with dropship computer
Fix issue with dropship computer
2022-06-20 22:48:52 -07:00
Jett
ea94de16cd Update Xiphoseers position on the project 2022-06-21 06:48:35 +01:00
Jett
c5f2f4b708 Update CREDITS.md 2022-06-21 06:45:19 +01:00
Jett
cb6d91cfb2 Revert "Update Credits markdown data"
This reverts commit e24ad43dc5.
2022-06-21 06:44:40 +01:00
Jett
e24ad43dc5 Update Credits markdown data 2022-06-21 06:44:21 +01:00
Jett
09d50faf79 Add new contributors to contributions list 2022-06-21 06:40:19 +01:00
EmosewaMC
6b30292efd Fix issue with dropship computer
The dropship computer now no longer gives a player a second mission item should they interact with it again after mission completion
2022-06-20 22:22:32 -07:00
David Markowitz
5f34b7150a Merge pull request #592 Added item precondition checks
Added item precondition checks
2022-06-20 21:41:08 -07:00
EmosewaMC
43377caa3b Added item precondition checks
Added item precondition checks for items so players who do not meet the conditions cannot use the items.  tested with the faction bag tokens and they only gave the tokens when a player met all the preconditions or was a Game Master of level 6+
2022-06-20 21:03:08 -07:00
29199f4755 Update README.md 2022-06-19 18:34:18 -07:00
David Markowitz
f4b89a8925 Merge pull request #590 Fix instances not stopping on all players leaving
Address order of deletion of entities on server to allow scripted activities to properly remove players
2022-06-19 14:26:23 -07:00
EmosewaMC
968114199b The shooting Gallery now properly ends when a player leaves the instance
The shooting Gallery now properly ends when a player leaves the instance

Frakjaw player update

Update the Frakjaw battle instance script to remove players when they leave the instance

Simplify comparison

Simplify comparison for entity pointer to be implicit
2022-06-19 01:40:16 -07:00
EmosewaMC
c871aeef56 Merge branch 'ScritpedActivityFixes' of https://github.com/EmosewaMC/DarkflameServer into ScritpedActivityFixes 2022-06-19 00:14:42 -07:00
EmosewaMC
9cf534dc0a Move to new branch
Added comments

Added some comments and changed a variable name to be less ambiguous.
2022-06-19 00:14:33 -07:00
EmosewaMC
de47210f15 Move to new branch
Added comments

Added some comments and changed a variable name to be less ambiguous.
2022-06-19 00:12:02 -07:00
David Markowitz
ba5037300f Merge pull request #587 Address pets not consuming imagination on summon or while being active
Address pets not consuming imagination on summon or while being active
2022-06-18 20:26:55 -07:00
EmosewaMC
2e224cb151 update name
Pets will take imagination by default now
2022-06-18 13:25:34 -07:00
EmosewaMC
2a0616d0e9 Dont take imagination on initial tame 2022-06-18 00:16:00 -07:00
EmosewaMC
0774ab930d inverted config check
Since most people are not regularly updating their config files, this needs to assume the value is disabled rather than enabled.
2022-06-18 00:09:05 -07:00
EmosewaMC
e415d96a9d Added config setting
Added a config setting to allow players to disable pets consuming imagination.  This value defaults to zero as a feature of DLU.
2022-06-18 00:03:27 -07:00
EmosewaMC
35ea3d35ae Add pet imagination draining
Address an issue where pets did not consume imagination when they were spawned.
2022-06-17 23:53:09 -07:00
EmosewaMC
e28b084395 Add GM
Added GM for UseItemRequirementsResponse that was missing in current implementation
2022-06-17 22:19:28 -07:00
EmosewaMC
136937184e Add to common vars and dnet
Added values to enums on dnet and common vars that were missing
2022-06-17 22:18:46 -07:00
David Markowitz
2403a7fe45 Merge pull request #585 Fix child entities not being removed from their parents correctly on deletion
Fix child entities not being removed from their parents correctly on deletion
2022-06-16 19:34:03 -07:00
EmosewaMC
531c4a594c remove children
We need to make sure we are actually deleting children from the vector of children when they are deleted as entities.
2022-06-16 17:50:33 -07:00
David Markowitz
1fe6c32933 Merge pull request #584 Fix an issue where quickbuilds were sometimes unbuildable
Fix an issue where quickbuilds were sometimes unbuildable
2022-06-16 09:06:45 -07:00
EmosewaMC
4a39221dd0 Address reviews
Changed the activator position parsing to have TryParse so that we dont throw an exception trying to load the position.  Should the loading of the activator position fail the game will default to the position of the entity.

change delimiter value to hex

Updated the character delimiter used for rebuild_activator settings to use hex

Remove extra parsing of activator position

in Entity.cpp we were parsing the activator position but when doing so where we were, this was after we had ended up spawning the activator since that is now in the constructor of the rebuild component.  The extra parsing has been removed.

Simplify dirty parent/child info

Simplify the if condition for parent child info.  This info only needs to be written should it be changed (dirty) or if the packet being sent is a construction, meaning that a requesting player needs all base data and needs to know what parents/children an entity has at that time.

get rid of extra parenthesis

Left over extra parenthesis were around these conditions on accident
2022-06-16 08:50:01 -07:00
EmosewaMC
09c459a083 Added comment 2022-06-15 23:17:44 -07:00
EmosewaMC
7dfcd22a2e Properly place build activator
The build activator as a result of the previous changes was spawning at the wrong position.  This commit pulls the activators position from the settings (should they exist) and sets them accordingly.
2022-06-15 22:59:30 -07:00
EmosewaMC
8bdd5b6e2c Address quickbuilds being unbuildable
Address an issue where quickbuilds would become unbuildable.  The main issue lied within serializing parent/child info too often for some reason / serializing it when the info wasnt dirty.  Only serializing this info when it is actually dirty and has changed has addressed the issue and allows quickbuilds to never break.
2022-06-15 22:58:38 -07:00
David Markowitz
4556faf833 Merge pull request #583 from EmosewaMC/SetLevelCommand
Add setlevel command
2022-06-13 01:06:41 -07:00
EmosewaMC
1179f5a2fe Add setlevel to commands doc 2022-06-13 00:45:29 -07:00
EmosewaMC
a61c6e5e41 Add /setlevel slash command
Add the setlevel slash command.  Command accepts parameters of the requested level and a player to set the level of.  This also adjects the uscore of the player accordingly.  The player must re-log upon using the command to see any updates to themselves or others.
2022-06-13 00:45:17 -07:00
Jett
1f62f169c8 Merge pull request #582 from DarkflameUniverse/revert-581-bons-hotfix
Revert "Don't give activity loot for Battle of Nimbus Station"
2022-06-13 04:20:54 +01:00
Jett
842cb80137 Revert "Don't give activity loot for Battle of Nimbus Station" 2022-06-13 04:19:27 +01:00
David Markowitz
2868465e89 Merge pull request #581 Don't give activity loot for Battle of Nimbus Station
Don't give activity loot for Battle of Nimbus Station
2022-06-12 19:25:56 -07:00
EmosewaMC
ef8ea13d99 Don't give activity loot for Battle of Nimbus Station
Address an issue on Brick Mesa where Battle of Nimbus Station was dropping activity loot.  Tested completing Battle of Nimbus Station and ending early and was not given loot as is expected.
2022-06-12 19:25:28 -07:00
David Markowitz
df9f9f08b6 Merge pull request #580 Address issue with bricks selling 1 at a time
Address issue with bricks selling 1 at a time
2022-06-12 14:15:42 -07:00
David Markowitz
50fd27b973 Merge branch 'DarkflameUniverse:main' into selling-fix-bricks 2022-06-12 11:49:17 -07:00
EmosewaMC
81431cfcbd Address bricks selling 1 at a time
Bricks have a stack size of zero in the cdclient so we need to make sure to give them a full stack size of 999 as we do for the bricks inventory with the selling inventory.
2022-06-12 11:48:52 -07:00
David Markowitz
7af248feeb Merge pull request #578 Fix Selling "random" item
Address issue with selling/moving items grabbing a "random" item
2022-06-12 11:43:36 -07:00
EmosewaMC
fbf0b59ff1 Fix item getter for moving items
This fixes an issue where the item would get overwritten and would effectively fetch a "random" item in the inventory to move instead of the requested one.
2022-06-12 10:56:01 -07:00
David Markowitz
c5dff54e01 Merge pull request #577 Address issue with some kills not contributing towards progress
Address issue with player spawned abilities not getting team
2022-06-11 22:01:41 -07:00
EmosewaMC
30c8326c3e Move owner override
Mover owner override to be earlier so that we dont try to get the team of an entity that doesnt have a team and may be a child entity of a player.  Tested changes with a team of two players and players were correctly given credit for kills
2022-06-11 20:50:01 -07:00
Shane Clark
d8cde40b49 Fix unhealthy docker containers (#574)
* Add curl to brickfix dockerfile.

* Add curl to AccountManager docker.

* Fix issue preventing container from building.
2022-06-11 19:31:58 -05:00
David Markowitz
db773e9778 Merge pull request #573 Fix crash for Footraces on Windows
Corrected ambiguous string to number conversion  which would cause a crash on operating systems where a long is 32 bits and not 64 bits.
2022-06-06 23:09:10 -07:00
EmosewaMC
33cc3a3dd9 Corrected string to long conversion
For Windows, the definition for a long is 32 bits, not 64 bits like on other operating systems.  This caused an issue on Windows only where a number larger than 32 bits was attempted to be converted to a long, the WorldServer would crash.  This commit replaces all instances of `stol` with `stoull` to further define a long and reduce ambiguity of number length.
2022-06-05 21:02:41 -07:00
66215da37a Fix overrides in ActMine (#568) 2022-05-31 00:24:55 -05:00
David Markowitz
73bbe641c6 Merge pull request #567 Address solo activity team sizes
Activities that would now force players into teams no longer make teams of size 1.
2022-05-27 19:04:46 -07:00
c6f871d42b only make teams for minigames
if we have more than one participant
2022-05-27 15:25:57 -05:00
Jett
445c01d485 Add instructions on solving missing DLL issue (#379)
* Add instructions on solving missing DLL issue

* Repair formatting to be consistent
2022-05-25 18:41:42 -05:00
luke-sparks
915b779f03 Update Docker.md with buildkit and submodule notes. (#458)
* Update Docker.md

Add link to enabling docker buildkit. Add note to remember to clone submodules.

* Remove unpacked client option

Unpacked client does not have required directories/files (e.g. /versions/trunk.txt) and thus the packed client is required.

* Add note about renaming CDClient.fdb

DarkflameSetup will fail because it cannot find cdclient.fdb. However, CDClient.fdb exists. Renaming it fixes the issue.

* Remove extra "client"
2022-05-25 12:32:18 -05:00
David Markowitz
731c25741c Merge pull request #563 Fix leaderboard not updating when it is supposed to
Fixed leaderboards not updating when they are supposed to.
2022-05-24 20:36:35 -07:00
HailStorm32
f8d73ccbc5 Fixed display logic for NS Survival leaderboard 2022-05-25 02:03:40 +00:00
HailStorm32
f5caa1f00d Merge branch 'leaderboard-updates' of https://github.com/Verathian/DarkflameServer into leaderboard-fix-resubmit 2022-05-25 02:00:10 +00:00
David Markowitz
769f789a43 Merge pull request #354 Sanitize SQLite Queries
adds support to prevent sql injection via using prepared statements and also fixes an issue with the runmacro command.
2022-05-24 17:31:58 -07:00
e3422ac0c5 Merge branch 'main' into main 2022-05-24 19:00:52 -05:00
Jasper Reddin
cdb2cf0344 Added Comprehensive Slash Command Documentation (#402)
* Added documentation for all available commands

* Adjust formatting, removing backtick characters

* Replace HTML tables with Markdown tables

* Formatting changes

* Suggestions from @sersorrel in #402 and other minor edits

* Add detailed usage for /inspect

(thanks to @sersorrel for this information, in discussion of #402)
2022-05-23 21:59:31 -05:00
David Markowitz
44e17eabca Merge pull request #559 Properly implement climbable setting for climbables
This shouldn't change anything that was available in live but anything that can be spawned in as climbable is able to be done so now.
2022-05-19 12:38:40 -07:00
06df15717c maybe fix it 2022-05-19 08:40:50 -05:00
813aca9d20 resolve comments 2022-05-18 06:36:21 -05:00
David Markowitz
a363d0734c Merge pull request #557 optimized LUP Component
Optimized LUP Component to not use a query to build its list of worlds
2022-05-17 21:30:12 -07:00
David Markowitz
667677dcdd Merge pull request #558 Implement boom trap
Implement Mine Script for boom trap
2022-05-17 21:29:33 -07:00
9169d844e2 explicit set to 0 2022-05-17 21:38:36 -05:00
03a5aa4da0 climbable server side settings 2022-05-17 21:27:08 -05:00
729e79eadb resolves #556 2022-05-17 19:12:43 -05:00
ca55fccb27 remove cdclient include 2022-05-17 10:20:36 -05:00
81af1f382e get zones from settings 2022-05-17 10:18:50 -05:00
David Markowitz
cc23538244 Merge pull request #549 Players hold rockets when interacting with some launch pads 2022-05-12 19:25:58 -07:00
20b45bc27f Merge branch 'main' into proper-rocket-holding 2022-05-12 08:21:17 -05:00
David Markowitz
85cd8c8833 Merge pull request #553 Fix Crux Prime Teapot
Add crux prime tea pot server script
2022-05-10 14:18:28 -07:00
David Markowitz
d6aece44aa Merge pull request #552 Replace survey link with repo link
Replace the survey link with the repo link
2022-05-10 04:16:22 -07:00
aba349301f Add AM Teapot server
Resolves #224
2022-05-09 23:21:20 -05:00
875827d688 Set url from world config instead of hardcoding 2022-05-09 17:33:43 -05:00
d7eb8783a8 replace the survey link with the repo link
(not that anything can load in the in-game browser anyway)
2022-05-09 08:43:31 -05:00
David Markowitz
d39df2e5a1 Merge pull request #551 exclude Frostburgh race track from ghosting
Exclude space blizzard from Zone ghosting
2022-05-09 04:51:37 -07:00
4c7034648b Exclude space blizzard from Zone ghosting 2022-05-08 22:07:07 -05:00
ec207838d4 Proper Rocket Holding
Sanity checks on Prop and LUP launchpads to not open if no valid rocket
Add serialization for sending item configs
so that rockets show for other players
2022-05-08 19:57:36 -05:00
David Markowitz
24745c2e7a Merge pull request #541 Implement the LUP Rocket Launch Component
Implemented the LUP Rocket Launch Component and makes its UI live accurate
2022-05-06 11:54:32 -07:00
David Markowitz
8601976498 Merge pull request #544 address Elephant precondition
Pet Components now read in their preconditions from their settings (if they have any).  Mainly fixes just elephants not taking peanuts.
2022-05-06 04:15:13 -07:00
David Markowitz
ca042bd415 bump patch version
- Quickbuilds jump on completion
- Fong now plays darkitect cutscene on a mission completion
- Nexus Tower panels now play the repair animation
- Vendors can now refresh
- Loot magnet abilities now work
- Spinjitzu Initiate now works
- Achievement items now get moved to the players inventory as they did in live, by popping up from the achievement box
- pop up when you get a new life container now shows up as it did in live
- Parrot in Nexus Tower is no longer an oar
- Fixed an item underflow bug
- Vaults for Items and Models now are the same size and start out at the correct size
- The buy back inventory for vendors now allows you to scroll (only after backing out of the menu first for some reason)
- Untamed pets no longer cause client hitches in Nimbus Station and Forbidden Valley
- When shutting down, the server now shuts down in 1 second instead of 75
- Plunger gun is no longer a main hand item
- Skills for proxy items no longer require a reload to be used
- Resolved some MacOS compilation warnings
- Quickbuilds now play a celebration on completion
- Bug reports are more specific
- Property viewer and plaques now work as they did in live and display all the correct information
- Properties now also save more often instead of every 10 minutes
- Avant Gardens Survival buff station now works
- Exploding dummy for Nexus Tower combat training now works and allows progression
- Racing missions for smashables now work
- Apes now act as they did in live
- Dragons on Crux Prime now spawn the quick build for insta smashes
- Civilian players can no longer use /playanim
- Proxy items no longer grant extra stats
- Shooting gallery daily missions now work
- Operators can now spawn race cars in non-racing worlds
- Level rewards now show their achievement as they did in live

We really need to do this monthly so the notes arent this long lol
2022-05-06 04:01:34 -07:00
06a1949eaa remove sysaddr from call in Game Messages 2022-05-04 19:31:56 -05:00
b11b516641 fix Java doc comments
removed unused param
2022-05-04 19:26:56 -05:00
ad5c679d2d Styling edits 2022-05-04 18:24:28 -05:00
e81acb4c67 Client handles rocket being unequiped
when closing the dialog
and when launching
2022-05-04 07:50:05 -05:00
aa212ae6d8 Add precondition check 2022-05-03 22:38:49 -05:00
bd3e8aee51 Implement Rocket Launch Lup Component 2022-05-03 15:05:29 -05:00
David Markowitz
a1a345326a Merge pull request #534 Quickbuilds jumping again
Addresses quickbuilds not jumping anymore.
2022-05-03 12:18:26 -07:00
EmosewaMC
6b409303af Update RebuildComponent.h
Quickbuilds jump fix

Corrected an error where the builder was erronously changed to an empty lwoobjid when a quickbuild was completed, causing the builds to no longer jump on completion (if configured to do so.)  Packet captures from live show that we do not want to get rid of the builder during resetting or during completion of the build so the file has been changed to not clear the builder in those cases.
2022-05-02 22:50:28 -07:00
David Markowitz
427c4a8c33 Merge pull request #531 Add Fong Architect Script
Added the Fong Architect script and split out the Darkitect method into its own file so it can be used across multiple scripts.
2022-05-01 16:22:12 -07:00
763a1f4a61 Split out Darkitect reveal into it's own file
add reveal to Fong
2022-05-01 08:54:45 -05:00
David Markowitz
12ae6a5525 Merge pull request #528 from EmosewaMC/NTParadoxPanelFix
Added animation for Nexus Tower Panels
2022-04-28 20:20:43 -07:00
EmosewaMC
2435870ec5 Added animation
Added the GM animation and stun for the Nexus Tower Paradox Panels for mission 1281.  Tested on local instance and animation played correctly when having the mission and did not play at all before or after completing the mission
2022-04-28 19:52:03 -07:00
EmosewaMC
59be7d8635 Added back brick inventory resizing 2022-04-28 14:36:55 -07:00
David Markowitz
bbedf5d174 Merge pull request #525 from EmosewaMC/money-fix
Serialize ape when changing armor value
2022-04-28 00:38:33 -07:00
EmosewaMC
2f598dad09 Serialize ape when changing armor value 2022-04-28 00:14:06 -07:00
David Markowitz
16b108f69c Merge pull request #522 from EmosewaMC/vendor-refresh
Added vendor refreshing
2022-04-27 13:21:59 -07:00
David Markowitz
94c00417ff Merge pull request #524 from EmosewaMC/lootBuffFix
Added LootBuff behavior and serialization
2022-04-27 13:21:16 -07:00
EmosewaMC
b713b94841 Added Loot Buff Behavior
Added functions and methods to support the pickup radius.  Functionality includes:
Corrected serialization for ControllablePhysicsComponent which correctly serializes the pickup radius to the client.
A method to add the pickup radius to the list of active pickup radii the component has.
A method to remove and re-calculate the largest active radii the component currently has.

Tested equipping all variations of the LootBuff behavior (passive skills, items, item skills) and all functioned as intended.  Tested equipping multiple items with a loot buff and then unequipping them in different orders.  Tested adding pickup radii of different values and the server correctly adjusted the pickup radius to the largest one currently equipped.
2022-04-27 12:40:43 -07:00
EmosewaMC
843a5b39c0 Vendor refresh change
Changed vendor refresh to happen as soon as it is able to.
2022-04-27 01:35:46 -07:00
EmosewaMC
fa7c4d9c27 added comments 2022-04-26 15:26:30 -07:00
EmosewaMC
cacf4fcd97 corrected serialization 2022-04-26 15:23:29 -07:00
EmosewaMC
5afeb265cd Updated vendor component
Fixed a few issues in VendorComponent.
- Corrected serialization to only happen on construction.
- Added functionality to refresh the vendor based on info from the vendor component table
- some whitespaceing inconsistencies.
- Sorted includes.
Tested the vendor in Nimbus Station and when the player re-enters the world, the vendor inventory refreshes, as opposed to previously where the world would need to reset in order to refresh the inventory.
2022-04-26 03:41:16 -07:00
David Markowitz
aca2bb1090 Merge pull request #520 from EmosewaMC/skill-tasks
Corrected action for OverTimeBehavior
2022-04-25 20:22:19 -07:00
David Markowitz
2bd90ce353 Merge pull request #521 from EmosewaMC/hotfix-for-instruments
Typo in NsConcertInstruments
2022-04-25 18:22:58 -07:00
EmosewaMC
27edf5da1d Typo in NsConcertInstruments 2022-04-25 18:16:47 -07:00
EmosewaMC
7d233a04c0 Corrected action for OverTimeBehavior 2022-04-25 16:56:40 -07:00
David Markowitz
c2c8cf9767 Merge pull request #519 from EmosewaMC/skill-tasks
Skill Task changes (also fixes Spinjitzu Initiate)
2022-04-25 13:42:19 -07:00
EmosewaMC
4117ceb6c1 Skill Tasks changes
Addressed an issue where the Spinjitzu Initiate achievement would not progress.  This also allows mission tasks that specify that the player must get a kill on an enemy with a skill to progress.  Tested mission 1935 and 1139 and both missions progressed and completed as intended.
2022-04-25 03:25:07 -07:00
David Markowitz
58d2cee984 Merge pull request #516 from EmosewaMC/isPlayer-changes
Live accurate item loot sources
2022-04-24 18:56:49 -07:00
EmosewaMC
4fd1467cbf changed loot sources to none
Changed loot sources for some scripts to none so they properly give loot to the player.
2022-04-24 18:40:20 -07:00
David Markowitz
7b32d2f609 Merge pull request #518 from EmosewaMC/popup-fix
Pop up now appears for life containers
2022-04-24 18:39:35 -07:00
EmosewaMC
2e29dce77c removed logs 2022-04-24 17:27:25 -07:00
EmosewaMC
e56732184f commit 2022-04-24 17:26:05 -07:00
EmosewaMC
dc770299d1 removed debug logs 2022-04-23 22:22:21 -07:00
EmosewaMC
18fc01cd49 missed change for forge 2022-04-23 20:44:08 -07:00
EmosewaMC
c6480192f8 Revert "isPlayer changes"
This reverts commit 2e61839d93.
2022-04-23 20:35:39 -07:00
EmosewaMC
7a051afd97 loot source for item drops
Added support for Items to have a loot source attached to them when dropped or rolled.  This fixes the issue where achievements would give the item before it appeared in the achievement window.
2022-04-23 20:35:34 -07:00
EmosewaMC
ceab229a63 Specified enum
the LOOT_SOURCE enum is now attached to all loot sources.
2022-04-23 20:32:31 -07:00
EmosewaMC
8e10f090fd corrected number 2022-04-23 18:52:21 -07:00
EmosewaMC
a4d934913c added lootsource send in GM
WIP commit
2022-04-23 05:13:06 -07:00
EmosewaMC
0eece14b68 Vendor buyback inventory
Fixed vendor buyback inventory so it properly scrolls when the player adds enough items to it.
2022-04-23 04:16:10 -07:00
EmosewaMC
d0233a2cd0 Updated AddItemToInventorySync
AddItemToInventorySync now sends the correct loot source type
2022-04-23 04:14:55 -07:00
EmosewaMC
834b53b4ec Grammar error
Level reward needed an underscore
2022-04-23 04:13:23 -07:00
EmosewaMC
2e61839d93 isPlayer changes
Changed isPlayer to check for whether the entity has a character instead of checking system address of entity.
2022-04-22 00:10:15 -07:00
David Markowitz
e85cf466d4 Merge pull request #513 from aronwk-aaron/fix-parrot-being-oar
A new migration for the CDServer has been added this merge.  Please update your CDServer.sqlite files with the new migration
2022-04-19 20:32:59 -07:00
d42cbb2473 make newline at end of file 2022-04-19 21:36:09 -05:00
d4adb0e6e5 Fix migration 0 for cd server
setting every component to 1901 instead of just component 39
Add migration to fix it for existing users
and set the values back to what they were
2022-04-19 21:30:38 -05:00
4cf9865431 Merge branch 'DarkflameUniverse:main' into main 2022-04-19 19:19:41 -05:00
David Markowitz
6f9caaa8c1 Merge pull request #510 from IAmMajo/frostburgh-solo-racing
Fix solo_racing for Frostburgh's Space Blizzard Racetrack
2022-04-19 16:30:54 -07:00
David Markowitz
c489132f59 Merge pull request #504 from NinjaOfLU/fix-item-removal-underflow
Prevent integer underflow in item removal
2022-04-19 15:21:28 -07:00
c845055e6b Merge pull request #1 from NinjaOfLU/fix-item-removal-underflow
Fix item removal underflow
2022-04-19 11:56:57 -05:00
Majo
a3331d009d Fix solo_racing for Frostburgh's Space Blizzard Racetrack 2022-04-19 12:33:57 +02:00
David Markowitz
80a09881c0 Merge pull request #508 from aronwk-aaron/Frostburgh
Frostburgh Server fixes
2022-04-18 22:58:02 -07:00
263b019262 Merge branch 'main' into Frostburgh 2022-04-18 23:35:40 -05:00
6933b2c301 case for putting you back into FB when leavign space blizzard 2022-04-18 23:33:09 -05:00
8db7dfef75 also apply overrides to AG fans 2022-04-18 21:09:27 -05:00
f3dd71ccb1 cleanup logs, fix overrides, define LOTs in header 2022-04-18 21:02:04 -05:00
8fe5c00984 remove dereference
(I think that's what it is called)
2022-04-18 08:36:11 -05:00
d05601ce64 Fixes 2022-04-18 08:27:37 -05:00
David Markowitz
1defc22caf Merge pull request #509 from EmosewaMC/racing-achievement-fixes
Fixed Racing Missions Try, Try again and Race Series 1
2022-04-18 04:03:32 -07:00
EmosewaMC
5691df9009 Fixed Racing Mission
* Try, Try Again achievement now progresses when the player gets last place in a race of 3 or more players, or when solo racing is enabled.
* Race Series 1 mission from Velocity Lane now progresses correctly.
2022-04-18 01:04:29 -07:00
2122448284 cleaning up some stuff 2022-04-17 21:30:25 -05:00
263eaf03b0 ugh, another semicolon 2022-04-17 20:24:49 -05:00
6cef7a437a scope 2022-04-17 20:24:19 -05:00
0778b4f81c missed semicolon 2022-04-17 20:17:36 -05:00
235934714f honor the logic in the lua script 2022-04-17 20:16:27 -05:00
a343ed9493 rock hydrants work 2022-04-17 19:43:17 -05:00
cc68b0768b remove log 2022-04-17 17:43:25 -05:00
e696d26941 update the Effect ID 2022-04-17 17:41:10 -05:00
a8fcb4c153 make the hydrant match the lua script 2022-04-17 16:44:46 -05:00
1e85ae2035 tabs and log 2022-04-17 15:58:26 -05:00
67615d5688 fix volumen physics name 2022-04-17 12:46:41 -05:00
23677b4bd3 Simplify some stuff
Remove render component in startup
2022-04-17 12:38:12 -05:00
5b0f917485 update script path for fans 2022-04-17 00:05:04 -05:00
b3695c42b2 fix copy past error 2022-04-16 23:35:22 -05:00
0e5a1c9721 fix comparator 2022-04-16 23:33:44 -05:00
b4acf329b4 implement some missing scripts 2022-04-16 23:32:15 -05:00
David Markowitz
8f50e4ff56 Merge pull request #503 from aronwk-aaron/testmap-enhancements
Dynamically check if zone is viable from existence of file
2022-04-14 16:46:37 -07:00
David Markowitz
a3e2aa2a97 Merge pull request #505 from EmosewaMC/Vault-fixes
Addressed vault size issues
2022-04-14 16:30:55 -07:00
3d6d5e58a7 Update GameMessages.cpp
I promise I'm not farming changes. I woke up at like 4AM and realised that I'd screwed up in an obvious way. Note to self: You are ALLOWED to change variables.

Wasn't caught in testing because, well, it turns out it's actually impossible to test the edge case this covers, due to the script for the brick console.
2022-04-14 10:09:40 +01:00
cdbb42badf Added a bracket... -_-
Maybe I should write and test code on my computer rather than using Git as an IDE and commits as the save button...
2022-04-14 00:15:45 +01:00
1d1f479387 Ensure items correctly removed from missions
Doubt it would have affected anyone, but technically if you had a mission to collect something interactable, and you deleted the items at the same time as interacting with something, this would have counted incorrectly. I'm being defensive because I was an idiot who couldn't read, but in my defence, it was late when I made the first edit, and I'm also a blundering idiot!
2022-04-14 00:11:35 +01:00
EmosewaMC
a32c5a2f3c Vault corrections 2022-04-13 01:50:06 -07:00
59ec28a5a4 Prevent integer underflow in item removal
Previously, the only check that the user wasn't trashing more items than they had was clientsided, and this could be bypassed by contacting the server to remove items via a console or the like, and then trashing them before the server could respond, resulting in the count for the items being less than iStackCount. This check prevents that underflow.
2022-04-13 01:58:00 +01:00
959c90985c missed a semicolon 2022-04-12 18:32:52 -05:00
4a98c46fb9 fix tabs/spaces 2022-04-12 18:30:46 -05:00
40d396c7e2 simplify 2022-04-12 18:05:22 -05:00
6b44936c68 check if map exists for testmap 2022-04-12 14:06:03 -05:00
David Markowitz
e92cdc4f14 Merge pull request #493 from EmosewaMC/ugh
Pets no longer cause client hitches in Nimbus Station and Forbidden Valley
2022-04-11 14:35:57 -07:00
David Markowitz
0f738c8d9c Merge pull request #419 from Marcono1234/issue-template-improvements
Improve GitHub issue templates
2022-04-11 02:25:54 -07:00
David Markowitz
7a354b3545 Merge pull request #456 from Marcono1234/marcono1234/zlib-https
Fetch zlib library over HTTPS
2022-04-10 20:04:23 -07:00
David Markowitz
f45cb380e0 Merge pull request #499 from EmosewaMC/master-server-shutdown
Dramatically speed up server shutdown and specify database destruction source in logging message
2022-04-10 17:25:04 -07:00
EmosewaMC
f01c2e1bd3 Updated logging 2022-04-10 17:08:29 -07:00
EmosewaMC
30c7b65150 incorrecly named variable 2022-04-10 17:00:03 -07:00
EmosewaMC
1e514a8b61 more specific logging 2022-04-09 18:48:13 -07:00
EmosewaMC
c08557f37d separated world server to more functions 2022-04-09 18:35:41 -07:00
EmosewaMC
6927bc614e Spacing 2022-04-09 18:33:38 -07:00
EmosewaMC
ae61b23896 Chat log no longer needed 2022-04-09 16:02:27 -07:00
EmosewaMC
aee3290248 Update MasterServer.cpp 2022-04-09 16:02:12 -07:00
EmosewaMC
1efbe2d2c0 added returns 2022-04-09 15:57:18 -07:00
EmosewaMC
d085c0cf10 correct exit 2022-04-09 15:35:40 -07:00
EmosewaMC
3e60b9db4a Destroying database specifier 2022-04-09 15:35:01 -07:00
EmosewaMC
fd13770e87 Sped up server shutdown 2022-04-09 14:17:31 -07:00
David Markowitz
5ef1848474 Merge pull request #498 from EmosewaMC/plunger_gun_migration
Changed 0_initial.sql so it wont accidentally wipe a database if run again
2022-04-09 00:52:07 -07:00
EmosewaMC
77c6350f03 updated initial migration
Made it so people wont accidentally wipe their database if 0_initial.sql is ever run again
2022-04-09 00:48:14 -07:00
David Markowitz
f17e6d6a4a Merge pull request #496 from EmosewaMC/fix-skill-proxies
Addressed proxy items removing skills
2022-04-09 00:37:40 -07:00
David Markowitz
53823a0be5 Added plunger gun CDServer migration
A new migration has been added with this merge to address the plunger gun in the CDServer.  Please run the 3_plunger_gun_fix.sql migration to update your database.
2022-04-09 00:32:34 -07:00
EmosewaMC
3900267fed added comment 2022-04-09 00:31:18 -07:00
EmosewaMC
0a494422b7 Added migration for plunger gun 2022-04-09 00:22:02 -07:00
EmosewaMC
96f1c0a709 Fixed skills proxies 2022-04-08 20:20:42 -07:00
David Markowitz
39089284ff Merge pull request #495 from EmosewaMC/hello-there-obiwan
fixed out of context log for launching to properties
2022-04-08 19:37:36 -07:00
EmosewaMC
5a76cb3b44 fixed erronous log 2022-04-08 19:36:43 -07:00
David Markowitz
92d36496df Merge pull request #490 from EmosewaMC/macos_compilation_warnings
Resolved MacOS (and possibly ARM?) compilation warnings
2022-04-07 12:09:37 -07:00
David Markowitz
9b6caef6b5 Merge pull request #487 from EmosewaMC/quickbuild-fixes
Added a GM send after QB complete
2022-04-07 09:48:40 -07:00
EmosewaMC
7030d937b1 dirty bit 2022-04-06 22:24:50 -07:00
EmosewaMC
e73793c1a3 removed unnccessary work 2022-04-06 22:21:54 -07:00
EmosewaMC
5eb801eb12 uses number of bricks now 2022-04-06 22:21:29 -07:00
EmosewaMC
4b0ab2380c Client does calcs 2022-04-06 22:21:17 -07:00
EmosewaMC
bd0926e0a5 special case for pets 2022-04-06 22:21:08 -07:00
EmosewaMC
9d79fc3d2e resolved MacOS compilation warnings 2022-04-05 05:11:06 -07:00
Gie "Max" Vanommeslaeghe
a0a9936e47 Merge pull request #415 from Marcono1234/UserManager-name-logging
Fix UserManager not logging chosen name properly
2022-04-03 11:33:59 +02:00
Gie "Max" Vanommeslaeghe
5e5fefb501 Merge pull request #416 from Marcono1234/MasterServer-closing-db
Fix MasterServer not always closing database connection on exit
2022-04-03 11:31:53 +02:00
David Markowitz
395d607632 Merge pull request #484 from EmosewaMC/property-fixes
Reputation now saved in charxml.  This is not a retroactive fix for reputation earned before this merge.
2022-04-01 15:25:30 -07:00
David Markowitz
db0f363967 Merge pull request #476 from EmosewaMC/bugReportFixing
Added more specific bug reporting.  There is a new migration called migrations/dlu/2_reporter_id.sql to run on the database.
2022-04-01 15:12:58 -07:00
EmosewaMC
ec463dd4c8 Added a GM send after QB complete 2022-04-01 04:14:28 -07:00
David Markowitz
acbd46afcb Removed debug log 2022-03-31 20:55:47 -07:00
EmosewaMC
8379fba079 added initializer 2022-03-31 18:46:56 -07:00
EmosewaMC
4bc5c8194f Added reputation tracker in charxml 2022-03-31 18:18:13 -07:00
EmosewaMC
ba33c15b2d reputation rewards are now applied to character and not properties 2022-03-31 18:17:58 -07:00
EmosewaMC
0bf2d398ea moved initialization of entity 2022-03-31 18:17:43 -07:00
EmosewaMC
ece83db6ed World packets change
World packets now takes an entity so we can process reputation
2022-03-31 18:17:23 -07:00
EmosewaMC
8ae7bc0f92 Where to send reputation to client 2022-03-31 16:12:36 -07:00
David Markowitz
ccff6746ce Merge pull request #483 from DarkflameUniverse/hot-fix-hard-coded-database
Fixed a hard coded database issue
2022-03-31 14:14:35 -07:00
EmosewaMC
450bebc8a2 i am a big dum 2022-03-31 14:11:43 -07:00
EmosewaMC
cf70881370 simplified conversion 2022-03-31 03:20:13 -07:00
David Markowitz
4724e0ebc1 Merge pull request #481 from EmosewaMC/buff-station-faction
Corrected faction for Buff Station
2022-03-31 02:50:32 -07:00
Gie "Max" Vanommeslaeghe
95010e791f Merge pull request #479 from EmosewaMC/property-fixes
Property fixes
2022-03-31 11:21:37 +02:00
EmosewaMC
33b16a56e3 Added a save and fixed a crash
If am item were to be added to properties_contents and an item with that Primary Key already existed, the world would crash.  This addresses this.
2022-03-30 22:51:09 -07:00
EmosewaMC
cc9b6c05f6 removed include 2022-03-30 22:35:41 -07:00
EmosewaMC
9169acad47 changed to update 2022-03-30 22:14:51 -07:00
EmosewaMC
aed0ecc9fc removed newline 2022-03-30 22:05:09 -07:00
EmosewaMC
0561f60031 Added negative checks 2022-03-30 21:58:59 -07:00
EmosewaMC
e66421d34f clarified variable name 2022-03-30 21:58:43 -07:00
EmosewaMC
8462068a05 clarified variable names, used encapsulation 2022-03-30 21:33:25 -07:00
EmosewaMC
8a8b5b4f44 removed new line 2022-03-30 21:18:29 -07:00
EmosewaMC
bc7c543530 removed debug log 2022-03-30 21:15:50 -07:00
EmosewaMC
f22dab0f72 unapproved properties render correctly 2022-03-30 21:12:22 -07:00
EmosewaMC
002025231e Semantics 2022-03-30 20:33:50 -07:00
EmosewaMC
061d2b394c on the fly property moderating notifications 2022-03-30 20:33:37 -07:00
EmosewaMC
d3f954bdac changed serialized value to old
I am unsure if this is what gets serialized here so I am reverting this back to a zero.
2022-03-30 20:32:59 -07:00
EmosewaMC
c80a90e81e rejection statuses were backwards 2022-03-30 20:31:51 -07:00
EmosewaMC
b903c81a0a Shortened reputation update 2022-03-30 20:31:23 -07:00
EmosewaMC
f72c2dcaa5 Merge branch 'property-fixes' of https://github.com/EmosewaMC/DarkflameServer into property-fixes 2022-03-30 18:38:43 -07:00
David Markowitz
6b759ff54e Merge branch 'DarkflameUniverse:main' into property-fixes 2022-03-30 18:38:07 -07:00
EmosewaMC
041dc8256f comment 2022-03-30 18:34:26 -07:00
EmosewaMC
b79ebf1d40 Corrected faction for Buff Station 2022-03-30 18:25:32 -07:00
EmosewaMC
0bf2f0e92a Added enum for rejection statuses 2022-03-30 16:14:24 -07:00
EmosewaMC
04852ac1d9 Removed const 2022-03-30 16:13:21 -07:00
EmosewaMC
5fa0a16302 more options in BuildQuery method 2022-03-30 16:13:01 -07:00
EmosewaMC
4edb428954 next page query now works 2022-03-30 16:12:42 -07:00
Jett
ff9d736073 Merge pull request #442 from EmosewaMC/AvantGardensSurvivalBuffStation
Fully implemented Avant Gardens Survival Buff Station
2022-03-30 22:22:50 +01:00
Jett
b2890262fb Merge pull request #445 from EmosewaMC/explodingDummyFix
Implemented script for exploding dummy in Nexus Tower Combat Training
2022-03-30 22:21:30 +01:00
Jett
0a6b8f139e Merge pull request #437 from EmosewaMC/racingSpecificSmashFix
Addressed specific race smash missions not progressing
2022-03-30 22:20:38 +01:00
Jett
529b40b66c Merge pull request #474 from EmosewaMC/char-create-fixes
Addressed hard coded character create values for shirts and pants
2022-03-30 22:19:55 +01:00
Jett
2a2fa94b03 Merge pull request #475 from EmosewaMC/ape-fixes
Addressed incorrect ape attacks
2022-03-30 22:18:57 +01:00
Jett
58c6429209 Merge pull request #393 from EmosewaMC/DragonQBFix
Implemented a script that spawns a Golem Quick Build on Crux Prime dragons when they reach zero armor
2022-03-30 22:18:44 +01:00
EmosewaMC
5c16dd11f4 altered table now has a default for performance cost 2022-03-30 00:37:36 -07:00
EmosewaMC
bd6bdddcde clone ID now based on character data 2022-03-30 00:33:31 -07:00
EmosewaMC
fe334d8739 clarified magic nums 2022-03-30 00:20:26 -07:00
EmosewaMC
69cc265fea added performance cost initializer 2022-03-30 00:20:15 -07:00
EmosewaMC
17e9fb0d3c Default time is now the current time rather than 0 2022-03-30 00:20:04 -07:00
EmosewaMC
b676343b02 removed print and rejection send 2022-03-30 00:02:18 -07:00
EmosewaMC
c838f4f422 Added query for friends list next page 2022-03-29 23:59:50 -07:00
EmosewaMC
e244fbccc2 General updates to the property manager
clone id is correctly assigned, reputation now shows up, rejection verdict is sent correctly (not sure about where the reason goes if  it even goes here).
2022-03-29 23:49:04 -07:00
EmosewaMC
36edbf393b Added support to update reputation 2022-03-29 23:46:56 -07:00
EmosewaMC
258174d4e1 Added GameMessage for UpdateReputation 2022-03-29 23:46:23 -07:00
EmosewaMC
fdd3e15b2f Added GM for reputation update 2022-03-29 19:52:07 -07:00
EmosewaMC
94e0ef77a9 performance cost is still a float 2022-03-29 19:49:54 -07:00
EmosewaMC
06671b8d66 performance cost is a float 2022-03-29 19:48:34 -07:00
EmosewaMC
1783904cb6 fixed __int64 in missions table 2022-03-29 19:47:27 -07:00
EmosewaMC
9f16284595 tab spacing 2022-03-29 19:47:15 -07:00
EmosewaMC
af15cc60eb Add GM for performance cost 2022-03-29 19:46:47 -07:00
EmosewaMC
e79d4e66f3 add performance cost column 2022-03-29 19:46:38 -07:00
EmosewaMC
82ebdccdb2 Reputation is sent as a float not an int 2022-03-29 14:54:31 -07:00
75fd425ef6 Remove ability for gmlevel 0 to use /playanim (#391) 2022-03-29 13:06:28 -07:00
EmosewaMC
ec9749ab85 flag for are more being worked on 2022-03-29 03:50:41 -07:00
EmosewaMC
9385c33729 grammar and new line 2022-03-29 02:33:15 -07:00
EmosewaMC
7b536ee079 Best friends is 2 not 1 2022-03-29 01:57:23 -07:00
EmosewaMC
0c41026df0 Fixed friendless crash 2022-03-29 01:00:30 -07:00
EmosewaMC
b0d4993344 owner name change 2022-03-28 21:02:46 -07:00
EmosewaMC
35e576a839 fixed moderator issue 2022-03-28 20:53:09 -07:00
EmosewaMC
69ec1216dc added comments 2022-03-28 20:51:19 -07:00
EmosewaMC
19e82a5150 more cleanup 2022-03-28 20:51:15 -07:00
EmosewaMC
965d4c7af0 cleaned up file and added helper functions 2022-03-28 19:58:50 -07:00
EmosewaMC
17b0de8062 clarified variable name 2022-03-28 19:58:23 -07:00
EmosewaMC
895bbec277 clarified variable name 2022-03-28 19:58:15 -07:00
EmosewaMC
17f773c6cb comment 2022-03-28 04:25:44 -07:00
EmosewaMC
dc74b46e11 off by one moment 2022-03-28 03:58:40 -07:00
EmosewaMC
148c177d27 shortened method 2022-03-28 03:37:12 -07:00
EmosewaMC
c94f0918c9 testing number reverted 2022-03-28 03:26:01 -07:00
EmosewaMC
54de6c6878 FINALLY WORKING JESUS 2022-03-28 03:24:49 -07:00
Daniel Seiler
acb7ad78e8 Merge pull request #478 from EmosewaMC/hp-item-mission-triggers-fix
Fixed mission progression for item proxies
2022-03-28 08:49:31 +02:00
EmosewaMC
0a453e9dca working state 2022-03-27 23:46:43 -07:00
EmosewaMC
0a7fd6f79a updates 2022-03-27 20:05:00 -07:00
EmosewaMC
a7cd2f4d9b comments 2022-03-27 15:37:05 -07:00
EmosewaMC
e43517efe6 comments 2022-03-27 15:28:21 -07:00
EmosewaMC
b459790b2f Fixed mission progression 2022-03-27 15:24:24 -07:00
Daniel Seiler
66b7c6522e Merge pull request #441 from EmosewaMC/ProxyItemFix
Addressed some proxy items granting duplicate skills
2022-03-26 08:17:04 +01:00
Jett
3a959778fe Merge pull request #451 from EmosewaMC/ShootingGalleryScoreFix
Shooting Gallery daily mission fix
2022-03-25 15:59:39 +00:00
EmosewaMC
db3cd33bca fixed incorrect variable name 2022-03-24 17:51:21 -07:00
EmosewaMC
6499139a49 moved addition to new migration. 2022-03-24 01:11:21 -07:00
EmosewaMC
f83ad8bbe4 fixed wrong stun removal
Apes no longer stack their attacks

Apes no longer stack their attacks and excess comments removed
2022-03-24 01:05:36 -07:00
EmosewaMC
819c58df7c semantics 2022-03-24 00:33:05 -07:00
EmosewaMC
4e2c352ab9 Changed pants query and removed extra comments 2022-03-24 00:30:52 -07:00
EmosewaMC
b2c88bb6a7 working query 2022-03-24 00:09:18 -07:00
EmosewaMC
e2bfdcd174 moved char id storage 2022-03-20 20:46:34 -07:00
EmosewaMC
22a00de8cd added char id column 2022-03-20 20:46:15 -07:00
EmosewaMC
68c600facc Added better bug reports 2022-03-20 20:28:26 -07:00
Daniel Seiler
a49f9dc586 Merge pull request #461 from EmosewaMC/mailboxSpecialCase
Addressed special case in GameMessage for interacting with a mailbox
2022-02-24 16:10:10 +01:00
EmosewaMC
6be274b259 fixed issue 2022-02-23 17:38:25 -08:00
EmosewaMC
24d443537a Addressed spacing 2022-02-20 20:01:55 -08:00
EmosewaMC
3d1283675f Updated comment 2022-02-20 20:00:56 -08:00
Jett
ad52facef7 Merge pull request #452 from EmosewaMC/GMRacingCarFix
Addressed GM Operators not being able to spawn in cars in non-racing worlds
2022-02-21 03:55:28 +00:00
EmosewaMC
55def02c8f Added script to CppScripts 2022-02-20 19:51:54 -08:00
EmosewaMC
6905120ac6 Added MailBoxServer files 2022-02-20 19:51:35 -08:00
EmosewaMC
5ffb57d92c Removed special case from GM 2022-02-20 19:51:21 -08:00
Jett
87d3ac15bd Merge pull request #460 from EmosewaMC/HandleLEvelUpFix
Added UI pop up for level rewards
2022-02-21 03:50:31 +00:00
EmosewaMC
1c116fb0c4 Sending rewards works fully 2022-02-20 19:23:17 -08:00
EmosewaMC
1c43d7f38c GameMessage is correct 2022-02-20 19:23:03 -08:00
EmosewaMC
78fbe3c7fe Added support for Windows Native 2022-02-17 03:17:41 -08:00
Marcono1234
4ef5508347 Fetch zlib library over HTTPS 2022-02-16 23:38:40 +01:00
EmosewaMC
afa38ae890 Added call to GM in CharacterComponent 2022-02-12 21:03:04 -08:00
EmosewaMC
352f654ede Added GM in GameMessages 2022-02-12 21:02:52 -08:00
EmosewaMC
2bc9f8f66d Correctly set task value for shooting gallery 2022-02-10 03:08:47 -08:00
EmosewaMC
5fbb1e9cc2 removed comments 2022-02-10 02:16:33 -08:00
EmosewaMC
7c80c12b90 Removed comments 2022-02-10 01:40:57 -08:00
EmosewaMC
9021c5209f backup commit with comments 2022-02-10 01:03:51 -08:00
EmosewaMC
6c5c6b7b8e commit when car work 2022-02-09 21:21:10 -08:00
EmosewaMC
a60738f78f cleaned up SGCannon 2022-02-09 16:42:31 -08:00
EmosewaMC
b077bd937d Fixed bugs with minigame progression 2022-02-09 16:42:17 -08:00
EmosewaMC
1607b506c8 bodgy bodge to fix minigame missions 2022-02-09 16:42:03 -08:00
Gie "Max" Vanommeslaeghe
42f6f2f10b Bump patch version
Should have been done quite a while ago, but ah well
2022-02-09 10:59:43 +01:00
Gie "Max" Vanommeslaeghe
788cd3f807 Merge pull request #449 from DarkflameUniverse/physics-fix
Rehook dPhysics to main framerate
2022-02-09 10:55:21 +01:00
Unknown
d5a18af0e8 Rehook dPhysics to main framerate
Should fix bug causing double enter and exit events
2022-02-09 10:38:09 +01:00
Xiphoseer
cabd220a66 Fix spam-log on master disconnect (#447) 2022-02-08 17:25:14 +01:00
EmosewaMC
e397ed310e Updated script for teams
Updated script to drop buffing items for all members in a team.
2022-02-08 02:02:05 -08:00
EmosewaMC
1122f50c7c Changed time when buff station spawns 2022-02-08 01:55:25 -08:00
Marcono1234
d9874b452e Fix Plunger Gun not being removed from inventory after mission (#444) 2022-02-07 21:45:56 +01:00
EmosewaMC
0253a1fcb4 Added script for exploding asset 2022-02-07 03:43:57 -08:00
EmosewaMC
a22e1bd53d Added new case in CppScripts 2022-02-07 03:43:57 -08:00
Xiphoseer
56765d355b Merge pull request #443 from DarkflameUniverse/log-missing-master-conn-shutdown
Log WorldServer shutdown when MasterServer connection is missing
2022-02-07 10:58:52 +01:00
Xiphoseer
417a1a7485 Improve logging
Log when a WorldServer initiates shutdown because the master server connection went missing or wasn't established in the first place.
2022-02-07 10:19:16 +01:00
EmosewaMC
204f03fd2a removed extra function 2022-02-06 22:19:23 -08:00
EmosewaMC
b297d21a8d Fully implemented buff station script 2022-02-06 22:15:32 -08:00
EmosewaMC
f41e8292e8 Clarified numbers and added comments 2022-02-06 21:34:26 -08:00
EmosewaMC
3de2c3bfc6 set faction of buff station to 6 2022-02-06 21:32:36 -08:00
EmosewaMC
a6ed435038 Added bounds check for proxies 2022-02-06 20:54:04 -08:00
EmosewaMC
679f077772 updated comment 2022-02-06 20:54:03 -08:00
EmosewaMC
9cfb9a0de6 Added specific smashable mission progression 2022-02-06 14:28:37 -08:00
EmosewaMC
56521d35d0 Added associate for 17 2022-02-06 14:28:27 -08:00
EmosewaMC
72b3812716 fixed tab indent 2022-02-06 14:28:15 -08:00
Jett
b7d7146821 Merge pull request #435 from EmosewaMC/ghosting-fix
fixed ghosting issue
2022-02-06 02:25:46 +00:00
EmosewaMC
6ac90f98d1 fixed ghosting issue 2022-02-05 17:56:19 -08:00
Marcono1234
42e20d6db5 Explain in issue templates how to get Git commit SHA 2022-02-05 22:51:44 +01:00
Xiphoseer
b8c1f7629e Merge pull request #359 from AxtonF/HandleSIGTERM
Add handling of SIGTERM
2022-02-05 15:38:49 +01:00
Xiphoseer
448e888d69 Merge pull request #356 from EmosewaMC/UniqueCharacterNamesAddition
Added UNIQUE to charInfo table for names
2022-02-05 15:37:26 +01:00
Xiphoseer
ae6980966d Merge pull request #414 from Marcono1234/docker-read-only-volumes
Make some Docker Compose volumes read-only
2022-02-05 15:18:01 +01:00
cooltrain7
579cf590b4 Implement CDZoneTable PlayerLoseCoinsOnDeath (#251)
* Implement ZoneTable PlayerLoseCoinsOnDeath

- Adds a check on death if the character should drop coins in the current zone

* Refactored PlayerLoseCoinOnDeath into dZoneManager

* Coin death drops use LootGenerator

* Refactored again with use of CDZoneTableTable

* Remove duplicate CDZone call during initialization
2022-02-05 13:27:24 +01:00
Nordegraf
f7009b499b added tracking of Pet Excavator achievement (#213)
* added tracking of the Pet Excavator achievement

* make Pet Extractor Progress Zone specific

* added tracking of Pet Excavator Achievement using player flags
2022-02-05 13:19:25 +01:00
David Markowitz
84cf79906b Frakjaw Battle instance fixes (#409)
* Update NjMonastryBossInstance.cpp

* Changed spawn position to be 1.

* Changed stored variable from vector to int

Added clarifying comments
2022-02-05 13:11:58 +01:00
David Markowitz
933cdee414 Implemented Model Pickup and Reputation achievements (#413)
* Implemented Model Pickup and Reputation achievements

* Moved mission progression to placement

* Changed name to place
2022-02-05 13:08:40 +01:00
David Markowitz
77459af1d3 Removed AI Stopping after they use a skill (#407)
* Removed SkillTime from stopping AI

* Reverted Downtime removal
2022-02-05 13:07:30 +01:00
David Markowitz
828c457614 Added script for Friend of the Ninja mission (#406)
* Added script for Friend of the Ninja mission

* Added comments
2022-02-05 13:00:10 +01:00
David Markowitz
6ba9eea993 Added check to prevent accidental sentinel passive proc (#396)
* Added check to prevent accidental sentinel passive proc

Added a boolean to check if the player is at zero armor already and if so, do not trigger the passive ability.

* Renamed variable and condensed armor check
2022-02-05 12:59:07 +01:00
David Markowitz
fe178bf745 Fully Implemented Shooting Gallery Mission and Achievement Fixes (#381)
* Fixed tab indent

* Fully implemented Achievement tracking for Shooting Gallery

- Removed logging in MissionTask.cpp and moved the checks for mission progression to after checking the instance.

- Implemented the achievement tracking in SGCannon as well as tracking of the maximum hit streak and progression of enemy smashes in the shooting gallery.
2022-02-05 12:54:12 +01:00
David Markowitz
c6f220ee31 Implementing and Fixing All Racing Achievements (#366)
* Grammatical changes in comments

* Grammatical fixes in comments

Small grammatical fixes found in comments throughout the code.

* Added descriptions to functions

Added descriptions to functions that didn't have them to keep the code well documented

* Created RacingTaskParam.h

Created RacingTaskParam so eliminate magic numbers in the original implementation of completing racing missions.

* Updated magic numbers in Mission.cpp

Updated magic numbers in Mission.cpp to a meaningful name.

* Implemented racing smashable task progression

Previously, races did not progress tasks for smashing Entities.  Now all achievements tracking smashables track them correctly.  This has been implemented in the three Entities that can be smashed in a race (imagination boxes, track specific smashables, Forbidden Valley dragon eggs).

* Updated race imagination task progression

Race imagination now no longer uses a magic number when passed to missionComponent.  Instead we use a number defined in an enum located in RacingTaskParam.h

* Updated Race task checks

Racing tasks for completing races without smashing now no longer auto complete the whole chain of missions.  Tasks that track placing on tracks and races overall now properly complete.  Tasks that count how many missions in a zone are completed now function.  Tasks that track race completions in multiple areas now function.

* Updated RacingControlComponent.cpp

Fixed any tasks that required 3 players to now require 3 or more players in a race to progress.  This restriction is ignored if the world config opted in for solo racing to allow progression in solo worlds.  Updated magic numbers sent into missionComponent->Progress to an enum created in this PR.  Fixed some indentation.

* Fixed a grammatical error in variable name

Fixed a grammatical error in the enum for task params
2022-02-05 12:28:17 +01:00
wincent
dc2bd76aba Fixed scripted powerup spawners
When applied this commit fixes scripted powerups
2022-02-05 12:27:24 +01:00
David Markowitz
f0a4324bd4 Fixed an issue where leave-zone was working outside of instanced zones (#431) 2022-02-04 07:32:45 +01:00
Marcono1234
0d0949f5f0 Adjust chosen character name logging 2022-02-03 23:43:47 +01:00
David Markowitz
13980c4133 Added logic to Convert UScore to Coins for Level 45 Characters (#348) 2022-02-03 07:50:02 +01:00
David Markowitz
dac8ec621c Added stun immunity for bosses in Battle of Nimbus Station (#428) 2022-02-01 17:48:23 +01:00
026654b0d0 Update README.md 2022-01-31 04:34:22 -08:00
TheMatt2
59afc63a2f Merge DarkflameServer 2022-01-30 13:40:08 -05:00
Gie "Max" Vanommeslaeghe
344af924fe Merge pull request #405 from EmosewaMC/FvGateCrasherFix
Added missing script for Gate Crasher mission
2022-01-25 15:49:19 +01:00
Marcono1234
676611ed6f Improve GitHub issue templates 2022-01-25 03:18:10 +01:00
Marcono1234
4cd38f1174 Use exit code macros 2022-01-25 01:30:06 +01:00
Marcono1234
910448b0e7 Fix MasterServer not always closing database connection on exit 2022-01-25 01:30:06 +01:00
Marcono1234
477b629faf Fix UserManager not logging chosen name properly 2022-01-25 00:14:21 +01:00
f6558aa31e implement jetpack behavior and remove hardcoded jetpacks (#411) 2022-01-24 14:02:56 -08:00
Marcono1234
4f1df372a2 Make some Docker Compose volumes read-only 2022-01-24 21:52:11 +01:00
David Markowitz
1e01423a93 Added support for flags in macros (#410) 2022-01-24 14:57:50 +01:00
Xiphoseer
20037d12f7 Merge pull request #339 from CodeAX2/fix-aoe-targets
Fix Area of Effect Behavior Targets
2022-01-23 14:12:59 +01:00
EmosewaMC
f605451693 Added pragma once to header file 2022-01-22 17:48:09 -08:00
EmosewaMC
fa747a27db Added missing script for Gate Crasher mission 2022-01-22 17:40:08 -08:00
Gie "Max" Vanommeslaeghe
02bf5937dc Merge pull request #397 from EmosewaMC/AvantGardensSurvivalBuffStation
Fixed an issue where the Avant Gardens Survival buff station was not spawning and implemented its' script
2022-01-22 15:53:58 +01:00
TheMatt2
ef194f8796 Remove <filesystem> dependency (#400) 2022-01-21 17:46:19 +01:00
EmosewaMC
20789bab7f Changed out Timer for CallBackTimer 2022-01-20 16:00:45 -08:00
Gie "Max" Vanommeslaeghe
e248b74ee6 Merge pull request #386 from EmosewaMC/passportflagnotbeingset
Added joined a faction flag
2022-01-20 15:15:50 +01:00
EmosewaMC
e11260a2fe Added comment 2022-01-20 03:54:58 -08:00
EmosewaMC
24f8ea21db Added redundancy for smashing buff station 2022-01-20 03:48:43 -08:00
EmosewaMC
6fc0683ce9 Added comments 2022-01-20 03:26:41 -08:00
EmosewaMC
15831e8d6c Added Script files for Avant Gardens Buff Station 2022-01-20 03:20:39 -08:00
EmosewaMC
2a5f3b8072 Added script for Avant Gardens Survival buff station 2022-01-20 03:20:24 -08:00
EmosewaMC
850ae40f05 Moved retroactive flag check to Character.cpp 2022-01-19 17:34:53 -08:00
Gie "Max" Vanommeslaeghe
3bb1491f09 Merge pull request #387 from EmosewaMC/BonsRepeatMissionTriggers
Fixed Battle of Nimbus Station achievements being repeatable
2022-01-19 21:08:25 +01:00
EmosewaMC
a9389fcabf Merge branch 'passportflagnotbeingset' of https://github.com/EmosewaMC/DarkflameServer into passportflagnotbeingset 2022-01-19 03:37:52 -08:00
EmosewaMC
7cf458cff2 Removed redundant comparison 2022-01-19 03:36:18 -08:00
Jett
2bfff2933a Remove equal checks 2022-01-19 11:35:46 +00:00
EmosewaMC
46f375a58e Added comments to header file 2022-01-19 02:31:22 -08:00
EmosewaMC
097af41392 Deleted unused variables 2022-01-19 02:28:50 -08:00
EmosewaMC
67d5061416 Implemented Dragon Smash Quick Build for Crux Prime Dragons
Implemented a script for the crux prime dragons to spawn the Golem Quick Build that insta kills the Entity if the player hits the dragon after the golem is built.  Tested on Local Ubuntu instance against 1 Crux Prime Maelstrom Dragon and 1 Butterscorch and had no issues building the quick build or with the enemy not smashing.  Enemies also correctly reset to their default behavior after the stun period has expired.
2022-01-19 02:10:04 -08:00
EmosewaMC
d69a4ffaf0 Added retroactive check for player faction flags
Added a retroactive check for player flag when loading into a world.
2022-01-18 17:51:12 -08:00
enteryournamehere
84a376b425 Add zone 1700 to list of accessible zones (#87)
* Add zone 1700 to list of accessible zones

also fix indentation

* Indent using tabs instead of spaces

* Add zone 1500

* Remove zone 1500

and add back 1700 which was accidentally deleted again
2022-01-18 11:48:56 -08:00
Gie "Max" Vanommeslaeghe
179d44fdd3 Merge pull request #385 from TheMatt2/error-handling
Clearer Error Message on Misconfiguration
2022-01-18 12:51:48 +01:00
Jett
2f2e670ef3 Merge pull request #388 from EmosewaMC/ApeQBFix
Changed Script Created for Apes on Crux Prime to allow for Anchor QuickBuilds
2022-01-18 11:19:13 +00:00
EmosewaMC
01ed5106b9 Changed Script Created for Apes on Crux Prime 2022-01-18 02:28:17 -08:00
EmosewaMC
60ba78d639 Fixed BoNS achievements being repeatable 2022-01-17 21:55:01 -08:00
EmosewaMC
3ede7006f9 Added Joined a faction flag
Added logic to set the player flag for joining a faction.  Tested on Ubuntu and had zero issues.
2022-01-17 19:43:37 -08:00
TheMatt2
df77997b0b Clearer Error Message on Misconfiguration
Checks if CDServer.sqlite exists before attempting to open it. Otherwise 
Sqlite will create an empty file only cause a crash when CDClientManager 
tries to Initialize.

Also catches error if CDClientManager tries to initialize, in case an 
empty CDServer.sqlite file already exists.
2022-01-17 15:13:30 -05:00
Nico Mexis
7dd7fdaf71 Update CMake minimum requirement (#380) 2022-01-17 12:46:33 +01:00
Gie "Max" Vanommeslaeghe
789c0890ca Merge pull request #383 from EmosewaMC/bananaFixes
Changed banana drop spawn Y height to prevent them from getting stuck on the trees
2022-01-17 00:51:42 +01:00
EmosewaMC
d883536ebd Reverted change and simply lowered the spawn height to 8 2022-01-15 19:12:07 -08:00
EmosewaMC
fa714aa843 Changed Banana spawn Y height
Changed the Bananas Y spawn height to be 10 Y units lower to prevent bananas from getting stuck on the tree.
2022-01-15 17:55:44 -08:00
TheMatt2
9dfa401b27 Fix whitespace
Convert to tabs and remove trailing whitespace
2022-01-15 14:02:14 -05:00
TheMatt2
4ff84e0730 Fix whitespace 2022-01-15 13:37:43 -05:00
David Markowitz
70af1f9314 Fixed an issue where repeatable missions were not rewarding the items they should be rewarding (#357)
When applied this fixes issues with repeatable mission were not rewarding the correct items.
2022-01-14 14:00:09 +01:00
David Markowitz
24aaa04954 Fixed an issue with shark missions (#372)
Fixed an issue where getting eaten by a shark would accidentally progress the task for entering the Ravencloud gate's left hand side.
2022-01-14 13:48:33 +01:00
David Markowitz
ae06188871 Added Bat Lord Full Set Bonus (#375)
* Added Bat Lord Full Set Bonus
2022-01-14 13:46:41 +01:00
Jett
3eb319af5b Merge pull request #370 from EmosewaMC/AdditionOfExtraMissionItem
Fixed a bug where Chaos Cleaner would accidentally add a Maelstrom Dagger to your inventory
2022-01-14 11:54:08 +00:00
TheMatt2
3de3932503 Comply with Xiphoseer required changes.
Remove the CDClientDatabase::ExecuteQueryWithArgs() function and replace 
it with CDClientDatabase::CreatePreppedStmt().

This prevents a developer from accidently using %s, or incorrectly 
passing std::string, and causing a silent error.
2022-01-12 22:48:27 -05:00
Mick
470bc65239 Merge pull request #290 from Verathian/battle-of-nimbus-adjustments 2022-01-12 08:30:25 +01:00
EmosewaMC
304b03b1d1 Removed add item 2022-01-11 18:18:51 -08:00
Gie "Max" Vanommeslaeghe
d9d27a88fc Merge pull request #293 from Racater/main
Fix issue #268 : wrong shirt colors in the character selection
2022-01-11 23:48:58 +01:00
Gie "Max" Vanommeslaeghe
3fb61f068b Merge pull request #353 from OogwayUniverse/remove-ips-from-logging
Remove IP Logging
2022-01-11 23:45:44 +01:00
Felix Racz
2221945dc8 Add handling of SIGTERM 2022-01-11 22:47:29 +01:00
Gie "Max" Vanommeslaeghe
03fd073e76 Merge pull request #365 from OogwayUniverse/bons-fixes
Change the win delay to increase time to get BONS loot
2022-01-10 22:15:12 +01:00
Mick
0415ada289 Merge pull request #90 from TheNoim/main
Completely automated docker setup
2022-01-10 15:44:05 +01:00
Jett
b7b182c57c Change the win delay to increase time to get BONS loot 2022-01-10 11:59:56 +00:00
EmosewaMC
150dec1cc2 Added file to run on table charinfo to allow for unique names only
Created a new file to run on the MySQL database to alter the MySQL table charinfo.names to only allow unique entries
2022-01-09 00:12:49 -08:00
EmosewaMC
01230e2575 Revert change in 0_initial.sql 2022-01-09 00:09:27 -08:00
Felix Racz
03e2a855b1 Add handling of SIGTERM 2022-01-09 01:25:45 +01:00
Xiphoseer
77826c8691 Merge pull request #352 from DarkflameUniverse/feature/windows-ci
Add windows CI
2022-01-09 00:54:24 +01:00
EmosewaMC
b529b7d3a0 Added UNIQUE for charInfo table
Added UNIQUE for charInfo table.
2022-01-08 00:00:27 -08:00
TheMatt2
e5f7d164cb Additional SQLite lookup sanitizing.
Using CDClientDatabase::ExecuteQueryWithArgs() across all known lookups.
2022-01-06 21:12:47 -05:00
Jett
c1903ca12d Remove IP Logging 2022-01-06 21:54:48 +00:00
TheMatt2
4796b551ad Additional SQLite lookup sanitizing with CDClientDatabase::ExecuteQueryWithArgs() 2022-01-06 16:05:03 -05:00
TheMatt2
590ccc78aa Add proper sanitizing for input to SQLite database.
Adds function `ExecuteQueryWithArgs(query, ...)` to allow for queries 
with user input.

There is a known issue, that the funciton does not work with 
std::string. All strings must be converted to c strings.
2022-01-05 21:52:33 -05:00
Nils Bergmann
eef2ed0b4c Add special character warning 2022-01-05 17:46:59 +01:00
Nils Bergmann
9a7654806f Rename build dir to cmake_build 2022-01-05 17:38:53 +01:00
Nils Bergmann
72e2d24c67 Move AccountManager to submodules 2022-01-05 17:32:30 +01:00
Nils Bergmann
dc39acaa75 Fix build for newest changes 2022-01-05 17:21:25 +01:00
Nils Bergmann
f914799b62 Use LUnpack instead of lcdr utils for unpacking the client 2022-01-05 17:21:11 +01:00
Nils Bergmann
0f3fafde4b Merge branch 'DarkflameUniverse:main' into main 2022-01-05 16:33:13 +01:00
Xiphoseer
852ec4d990 Update requested VS version 2022-01-05 14:29:24 +01:00
Xiphoseer
30fa4c2aa9 Rename CI workflow 2022-01-05 14:28:14 +01:00
Xiphoseer
b21a88d1b0 Pin ubuntu version 2022-01-05 14:23:28 +01:00
Xiphoseer
5e7566c89a Pin to windows-2022 2022-01-05 14:21:59 +01:00
Xiphoseer
adab6cf96f Add windows CI 2022-01-05 14:12:28 +01:00
TheMatt2
f7b3a1ef10 Merge branch 'DarkflameUniverse:main' into main 2022-01-04 12:53:41 -08:00
CodeAX2
a19454f7ae Change destroyable component validator to properly check friends 2022-01-04 11:11:23 -07:00
Xiphoseer
8ed7690b96 Merge pull request #203 from cooltrain7/Log-Line-Cleaning
Added Log content additions
2022-01-04 13:15:24 +01:00
Xiphoseer
4d19459015 Merge pull request #291 from EmosewaMC/EmosewaMC
Implemented sourceType for SendSetCurrency
2022-01-04 12:01:32 +01:00
Xiphoseer
a9c0cfd9c8 Merge pull request #340 from DarkflameUniverse/feature/tests
Add basic CTest infrastructure
2022-01-04 09:27:24 +01:00
Xiphoseer
227b82c446 Add newline at EOF [skip ci] 2022-01-04 09:26:43 +01:00
EmosewaMC
cca5b79e91 Update Mission.cpp 2022-01-03 23:05:56 -08:00
David Markowitz
329d3d66b3 Update dGame/dGameMessages/GameMessages.h
Co-authored-by: Xiphoseer <Xiphoseer@users.noreply.github.com>
2022-01-03 22:37:58 -08:00
David Markowitz
cb9ce85bda Update dGame/Character.cpp
Co-authored-by: Xiphoseer <Xiphoseer@users.noreply.github.com>
2022-01-03 22:37:53 -08:00
David Markowitz
7aed5f0500 Update dGame/Character.h
Co-authored-by: Xiphoseer <Xiphoseer@users.noreply.github.com>
2022-01-03 22:37:49 -08:00
David Markowitz
a92e05c640 Update dGame/dGameMessages/GameMessages.cpp
Co-authored-by: Xiphoseer <Xiphoseer@users.noreply.github.com>
2022-01-03 22:37:40 -08:00
Xiphoseer
f1525028da Merge pull request #289 from Verathian/portal-fixes
Portal Stun Time Reductions
2022-01-04 07:31:35 +01:00
TheMatt2
f2b3b0bf66 Check user input for the "/runmacro" command
Presents users from specifying a file path, and looking up macros in the 
expected folder.
2022-01-03 21:40:07 -08:00
Xiphoseer
64a78532ed Merge pull request #325 from Marcono1234/marcono1234/malformed-character-xml
Fix initial character XML being malformed
2022-01-04 06:12:55 +01:00
EmosewaMC
a9da275673 removed extra tab
removed extra tab
2022-01-03 16:01:54 -08:00
EmosewaMC
f74cc9cb10 Updated variable assignment
Changed the variable assignment to be a ternary operator.
2022-01-03 16:01:28 -08:00
cooltrain7
975654f8e2 Merge branch 'main' into Log-Line-Cleaning 2022-01-03 17:51:13 +00:00
Mick
73718fe9af Merge pull request #14 from maxdelayer/main
Set `build.sh` as executable & update `README.md` to acknowledge  `build.sh`'s existence
2022-01-03 18:48:33 +01:00
Xiphoseer
a06fa39a5d Add newline at EOF; re-merge cmake steps 2022-01-03 16:36:15 +01:00
Xiphoseer
03d4d84eeb Update CI pipeline 2022-01-03 16:28:16 +01:00
Xiphoseer
eb18115c99 Update CMakePresets 2022-01-03 16:25:47 +01:00
Xiphoseer
1100c57e2d Run tests with CI 2022-01-03 16:00:32 +01:00
Xiphoseer
a591dbfe9c Basic tests infrastructure 2022-01-03 16:00:21 +01:00
EmosewaMC
74013e07a8 Encapsulated variable properly
lootSource was not encapsulated properly so this is now fixed.
2022-01-03 03:11:04 -08:00
CodeAX2
d78b2404e2 Refactor CheckValidity
- Change variables names to make it clear they are referring to the target
- Change how the target is decided to be an enemy of friend to use the built-in method
2022-01-02 14:01:29 -07:00
CodeAX2
9f895205d4 Fix formatting and add comments 2022-01-02 14:00:01 -07:00
Jacob Hofer
1ddf7d1f94 Fix for Area of Affect Behaviors targeting incorrect entities 2022-01-02 20:37:03 +00:00
Nils Bergmann
4d6991ea4b Merge branch 'DarkflameUniverse:main' into main 2022-01-02 16:08:18 +01:00
Nils Bergmann
15e8343e75 Merge pull request #8 from VBMCBoy/readme-improvements
Readme improvements as suggested by Marcono1234
2022-01-02 16:08:05 +01:00
Kay Kaprolat
4198379aa8 Removed unnecessary note about slashes 2022-01-02 10:24:01 +01:00
Marcono1234
df369612be Add XML attribute spaces consistently 2022-01-01 18:23:14 +01:00
Raphaël Dunant
f02165b912 Update UserManager.cpp
fix function call
2022-01-01 14:31:13 +01:00
Jett
203e75ef3d Fix resurrecting in BONS (#334) 2022-01-01 02:10:12 -08:00
m888r
14fc049ea0 Damage Buff source fix - inventor beehive bug (#306)
* add HandleUnmanaged overload to account for skill source

* add source to buff damage skill call to credit players for kills

* use LWOOBJID_EMPTY default arg & behaviorcontext constructor
2022-01-01 01:46:05 -08:00
Jett
83107d413d More windows fixes (#329)
- Added World, Chat and Auth servers as deps to Master
- Added "windows-default" CMake preset so that CMake didn't error out on Windows
- Added NOMINMAX define above cpplinq include
2022-01-01 01:38:45 -08:00
Jett
a15f9f38d8 Update script value to that in the lua file (#331) 2022-01-01 00:02:28 -08:00
Wincent Holm
00e841587d Merge pull request #332 from OogwayUniverse/spooky-fixes 2021-12-31 16:59:28 +01:00
Jett
2d5d5b273a remove unneeded log 2021-12-31 15:07:20 +00:00
Nils Bergmann
84b3386eab Merge branch 'DarkflameUniverse:main' into main 2021-12-31 14:14:04 +01:00
Nils Bergmann
824ab7c0c2 Update Docker_Windows.md
Co-authored-by: Marcono1234 <Marcono1234@users.noreply.github.com>
2021-12-31 14:13:41 +01:00
Nils Bergmann
d501a85c51 Improve order of execution for start_server.sh
Suggested by @Marcono1234
2021-12-31 14:12:09 +01:00
Nils Bergmann
f53a43631c Use LF for *.sh files
Suggested by @Marcono1234
2021-12-31 14:07:40 +01:00
Nils Bergmann
9c10a7adef More meaningful error messages
Suggested by @Marcono1234
2021-12-31 14:04:51 +01:00
Nils Bergmann
bb1c7095d7 Update Docker_Windows.md
Co-authored-by: Marcono1234 <Marcono1234@users.noreply.github.com>
2021-12-31 13:58:09 +01:00
Nils Bergmann
0bf03cb66e Update Docker_Windows.md
Co-authored-by: Marcono1234 <Marcono1234@users.noreply.github.com>
2021-12-31 13:57:53 +01:00
Jett
f15b716ea7 Implement master server fix 2021-12-31 02:52:35 +00:00
Marcono1234
7c1f392fdf Fix initial character XML being malformed
XML was missing a space between attributes `lzrw` and `stt`.
2021-12-30 19:42:59 +01:00
Kay Kaprolat
0a737eaa0d Add note about client files and linux performance 2021-12-30 19:35:06 +01:00
Kay Kaprolat
64edb88d36 Changed docker-compose to docker compose 2021-12-30 19:21:53 +01:00
Kay Kaprolat
1e7a2febea Fix Docker Desktop download link 2021-12-30 19:19:27 +01:00
Kay Kaprolat
da0be9f226 Clarify alt-text of step 7 2021-12-30 17:13:37 +01:00
Kay Kaprolat
8af1c92eff Fix typo in step 7 2021-12-30 17:13:07 +01:00
Kay Kaprolat
be008ca439 Indent all images 2021-12-30 17:11:25 +01:00
cooltrain7
6e6eee71b3 Added more missing newline characters 2021-12-28 19:27:46 +00:00
Raphaël Dunant
2ac2dbd650 Update UserManager.cpp
Style fix (CamelCase and space)
2021-12-28 19:56:49 +01:00
cooltrain7
ff8d68f45c Merge branch 'main' into Log-Line-Cleaning 2021-12-28 18:46:44 +00:00
Gie "Max" Vanommeslaeghe
0a7d9c46eb Merge pull request #304 from OogwayUniverse/team_loot_repairs
Team loot fixes
2021-12-26 16:18:23 +01:00
Racater
b6fc49f057 simplify shirt code in character creation 2021-12-26 14:45:21 +01:00
Raphaël Dunant
57e28d4619 Merge branch 'DarkflameUniverse:main' into main 2021-12-26 14:42:16 +01:00
Nils Bergmann
8ba3fe33f3 Merge branch 'DarkflameUniverse:main' into main 2021-12-25 17:05:37 +01:00
Jett
76c9d057cf Update ChatPacketHandler.cpp 2021-12-24 11:57:31 +00:00
EmosewaMC
5e605b30de Grammatical change in a comment
Small grammatical change in a comment
2021-12-23 19:50:17 -08:00
EmosewaMC
e95af79c8a Consolidated if statement
Changed default variable to achievement and removed the else.
2021-12-23 19:43:19 -08:00
EmosewaMC
e84811bdce Refactored if statement for coins
Refactored the if statement for coins so there is only one SetCoins call for the function.
2021-12-23 18:49:01 -08:00
EmosewaMC
6aad799f95 Updated variable names
Updated the variable names to match the enum name update.
2021-12-23 18:48:08 -08:00
EmosewaMC
6ff5ae78aa Corrected enum name
Corrected the enum name and prefixes of the elements in the enum.
2021-12-23 18:46:21 -08:00
Jett
7d40585211 Test frakjaw fix 2021-12-24 01:14:15 +00:00
Jett
9440af0d67 Repaired some bugs
- Fixed Team loot
- LMI dropping for team sizes
- No more > 4 player teams
2021-12-24 00:25:52 +00:00
Wincent Holm
0afba0d1d3 Merge pull request #294 from DarkflameUniverse/fix-loot-crash 2021-12-22 17:55:53 +01:00
Wincent Holm
271e14e2f1 Fix loot crash
When applied this commit fixes a crash with the loot system due to a missing nullptr check.
2021-12-22 17:16:31 +01:00
Raphaël Dunant
ac01edd440 Fix wrong shirt colors in the character selection 2021-12-22 16:02:19 +01:00
EmosewaMC
f772fedf19 Updated description of SetCoins
Updated the description of the Character::SetCoins function to more accurately describe how the function works.
2021-12-22 00:43:42 -08:00
EmosewaMC
29cf7f8998 Changed ambiguous variables
Changed ambiguous variables from int to int32_t to clarify what they are.
2021-12-22 00:15:08 -08:00
EmosewaMC
97f8e9e9fc Added enum for coin sources
Added an enum for coin sources as to avoid leaving a random number in the code.
2021-12-22 00:01:55 -08:00
EmosewaMC
c575294587 Changed variable names
Changed variable names to more accurately match what they are
2021-12-21 23:32:39 -08:00
EmosewaMC
23e269940b Implemented sourceType for SendSetCurrency
Implemented sourceType for the function SendSetCurrency.
2021-12-21 23:26:54 -08:00
Verathian
7b18c81608 BoNS Time Smash Fix 2021-12-22 00:20:53 -05:00
Verathian
eae1a38705 Portal Stun Time Reductions 2021-12-21 22:51:38 -05:00
Verathian
3cb16ddb5f Leaderboard Scoring Updates 2021-12-21 22:30:37 -05:00
Verathian
dcbca46e75 Leaderboard Scoring Updates 2021-12-21 22:15:29 -05:00
Wincent Holm
65b7f49c9b Merge pull request #248 from Xiphoseer/main 2021-12-21 21:23:56 +01:00
Gie "Max" Vanommeslaeghe
1006bd17e3 Merge pull request #276 from cuzitsjonny/main
ChatServer respawn after crash
2021-12-21 20:09:16 +01:00
Wincent Holm
0700b9647b Merge pull request #284 from saltshaker/main 2021-12-21 11:23:26 +01:00
saltshaker
aad4ed6a83 Added include <vector> to Loot.h to allow the server to build on GCP. Resolves #281. 2021-12-21 03:17:35 -07:00
Nils Bergmann
185bed2048 Merge pull request #7 from VBMCBoy/readme-improvements 2021-12-20 14:07:04 +01:00
Jonny
9d52ee7120 WorldServer now attempts to reconnect to ChatServer 2021-12-20 13:50:53 +01:00
Jett
0531365cb5 Make loot accurate to the loot drop rates during live. (#216)
* loot fix (broken)

* Fixed loot

* Update SlashCommandHandler.cpp

* Remove debug command

* Roll loot command

* Remove debug log

* Added const references
When this commit is applied it adds const references to the loot system avoid some unnecessary copies.

Co-authored-by: wincent <wincent.holm@gmail.com>
Co-authored-by: Avery <averysumner@gmail.com>
2021-12-20 02:25:45 -08:00
f7858ab183 Merge pull request #222 from anarcal/main
Add port recycling to instance creation
2021-12-20 01:47:23 -08:00
Jonny
dfb41c7c40 MasterServer now respawns ChatServer on crash 2021-12-20 10:08:57 +01:00
Wincent Holm
c8177563e9 Fix non-standard lambda.
When this commit is applied it fixes use of non-standard lambda.
2021-12-19 14:47:03 +01:00
Wincent Holm
6f6be5ec47 Remove utils module adde in PR by mistake 2021-12-19 13:48:31 +01:00
Wincent Holm
54501bce2a Merge pull request #258 from Nordegraf/fix-wreckin-it 2021-12-19 12:49:14 +01:00
Wincent Holm
46149b19f1 Merge pull request #254 from EmosewaMC/Crux-Prime-Enemy-Fix 2021-12-19 08:43:24 +01:00
EmosewaMC
35e8a374df Required script functions added
Re-added the required script functions.
2021-12-18 00:22:49 -08:00
EmosewaMC
88af3c7681 Change of reset use
Instead of doing a hard reset on the spawner, we simply do a SoftReset.  I also removed some dead code that was doing nothing.
2021-12-17 18:07:52 -08:00
Wincent Holm
93ddd50f76 Merge pull request #236 from ckawell/die-roll-anims-ckawell
Implemented die roll animations for the Lego Dice item
2021-12-17 18:29:15 +01:00
Niklas Conen
3793b1f00b fixed bug where smashedTimes counter cont incremented at the beginning of a race 2021-12-17 17:37:03 +01:00
EmosewaMC
8dd376ae1e Crux Prime named enemy fix
Fixed an issue where named enemies on crux prime would no longer spawn by un-commenting a line that was commented out.
2021-12-17 00:31:19 -08:00
Wincent Holm
f816ce4beb Merge pull request #189 from OogwayUniverse/fdb_checksum
Implement FDB Checksum
Checks the client database with a checksum. This is an optional check to prevent the use of modded or outdated clients.
2021-12-16 23:54:08 +01:00
Jett
6f932fe2cb Spelling and set filestream mode 2021-12-16 22:51:37 +00:00
wincent
49aba62dbb Updated database check
When applied this commit updates the style of the database check, changes some logging statements, and makes developers able to skip the check.
2021-12-16 23:11:51 +01:00
Xiphoseer
630d34f51c Set CMakePresets.json min cmake to 3.12 2021-12-16 20:56:11 +01:00
Xiphoseer
8846524541 Add GitHub Actions Workflow
* Create build.yml
* Create CMakePresets.json
2021-12-16 20:29:48 +01:00
Nils Bergmann
279fa076d6 Merge branch 'DarkflameUniverse:main' into main 2021-12-16 14:51:16 +01:00
Wincent Holm
3cad0214d1 Merge pull request #233 from sersorrel/instanceinfo-is-one-word
Correct documentation for /instanceinfo
2021-12-16 11:30:33 +01:00
Christopher Kawell
9c570b8121 Merge pull request #1 from Nordegraf/add-its-truly-random-achievement
Add its truly random achievement
2021-12-15 20:37:58 -06:00
Niklas Conen
2a00d50672 fixed formatting 2021-12-16 00:36:10 +01:00
Niklas Conen
b05c41fe8f added tracking of the It's Truly Random achievement 2021-12-16 00:30:46 +01:00
Mick
52fa7aaeae Merge pull request #239 from MickVermeulen/main
Fix issue templates
2021-12-15 22:36:16 +01:00
Mick Vermeulen
9f761a9ea5 Fix issue templates
GitHub updated their issue template format, checklists now also need a label attribute.
2021-12-15 22:34:26 +01:00
BuildTools
337383b6fd Changed Log statement to debug log 2021-12-15 14:44:10 -06:00
BuildTools
c4dd85be53 Added error log for die roll 2021-12-15 14:33:16 -06:00
BuildTools
de202ac6cc minor formatting fix 2021-12-15 13:27:57 -06:00
Christopher Kawell
34050f641d Merge branch 'main' into die-roll-anims-ckawell 2021-12-15 13:27:11 -06:00
BuildTools
fb18225f46 Implemented die roll animations for the Lego Dice item 2021-12-15 13:23:49 -06:00
Jett
a5d527d0cf client fdb checksum bug 2021-12-15 18:45:42 +00:00
58229a922e setminifig shirt -> setminifig shirtcolor 2021-12-14 18:55:05 -08:00
a2ed772417 setMinifig -> setminifig 2021-12-14 18:51:41 -08:00
ash
e58af90c8b Correct documentation for /instanceinfo 2021-12-14 21:45:35 +00:00
Kay Kaprolat
0d88357c85 Add Git installation instructions 2021-12-14 21:14:48 +01:00
Jett
ff2f5cb2ce (untested) 2021-12-14 19:25:30 +00:00
Nils Bergmann
0f7986ff36 Building now creates log directory by itself 2021-12-14 20:19:00 +01:00
Nils Bergmann
f96a5e2b1a Update utils url 2021-12-14 20:09:10 +01:00
Nils Bergmann
2b92bbc45f Merge branch 'DarkflameUniverse:main' into main 2021-12-14 20:05:31 +01:00
Nils Bergmann
5ab326142f Merge pull request #6 from jgkawell/pr-comments
Addressing more PR comments
2021-12-14 20:04:21 +01:00
Nils Bergmann
023b7f85fb Merge branch 'main' into pr-comments 2021-12-14 20:03:58 +01:00
Nils Bergmann
79bcf811d6 Merge pull request #5 from VBMCBoy/readme-improvements
Readme: link to Docker Desktop and on stopping the server
2021-12-14 20:01:30 +01:00
Jett
543b231a80 Update WorldServer.cpp 2021-12-14 18:12:44 +00:00
Unknown
c060b01037 fix undeleted dpEntity after enemy smashed
could be the cause of long-soak (hours long) sessions having CPU issues
2021-12-14 16:24:48 +01:00
Jack Kawell
f6a401ac6b Addressing PR comments 2021-12-14 00:08:08 -07:00
Nexus
ca8f0059a3 Add port recycling to instance creation
Made instance creation use previously used ports when available, to prevent
crashes caused by ports being used that are outside of the assigned range.
2021-12-14 11:05:33 +08:00
cooltrain7
995042f130 Added missing log newline character 2021-12-13 19:45:08 +00:00
wincent
259c236b72 Fixes dlogger PR
When applied this commit fixes the unix build of the previous dLogger PR.
This commit also fixes backwards compatability with config files.
2021-12-13 16:57:43 +01:00
Mick
81d25dd574 Merge pull request #150 from OogwayUniverse/script_ignore 2021-12-13 15:44:35 +01:00
Mick
ff3e10d076 Merge pull request #177 from DarkflameUniverse/implement-buccanneer-valiant
Fix #164: Implement Buccaneer Valiant special ability
2021-12-13 14:31:36 +01:00
cooltrain7
9b1fbe6c2c Added extra log information and replaced incorrect print statements
- Added extra Zone and Instance information to ambiguous log calls during loading. chat connection, chat connection loss, and shutdown
- Fixed correct class names in some log lines
- Replaced printf during world shutdown with correct log call with instance and zone info
2021-12-13 01:37:09 +00:00
cooltrain7
ed151e6d45 Added extra information to connection log
- Added correct class name to log calls
 - Added extra zone and instance information in ambiguous log call
2021-12-13 01:33:51 +00:00
cooltrain7
932128a084 Replaced printf with correct logger->log call
-  Use of printf breaks the flow of the console
2021-12-13 01:31:39 +00:00
cooltrain7
8c6ef98b22 Replaced cout with correct logger->log call
-  Use of cout breaks the flow of the console
2021-12-13 01:29:38 +00:00
Jett
9e032223eb Remove unused MD5 functions and fixed memory leak 2021-12-12 15:53:19 +00:00
Jett
830cf22beb Calculate FDB checksum in chunks 2021-12-12 15:14:04 +00:00
Wincent Holm
d7294bda55 Merge pull request #187 from Nordegraf/fix-nstokenconsole-exchangerate
increased the exchange rate of the nimbus station console to 5 faction tokens for 25 maelstrom infected bricks
2021-12-12 08:44:15 +01:00
Jett
49c1cb3aff Implement FDB Checksum
- Added config option `check_fdb`
- Added check in WorldServer.cpp
- Added raw MD5 function in MD5.cpp and MD5.h
2021-12-12 03:41:11 +00:00
Niklas Conen
834b87f4b2 increased the exchange rate of the nimbus station console to 5 faction tokens for 25 maelstrom infected bricks 2021-12-12 03:45:25 +01:00
Gie "Max" Vanommeslaeghe
180db5dea5 Merge pull request #151 from OogwayUniverse/trigger_fixes
Moonbase fix
2021-12-11 19:39:24 +01:00
Wincent Holm
95d1c65011 Merge pull request #180 from OogwayUniverse/coin_exploit
Patched coin exploit
2021-12-11 17:40:59 +01:00
wincent
bb508e91c1 Update the code style
When applied this commit updates the code style used when validating coin pickups.
2021-12-11 17:33:54 +01:00
Jett
94e32a5773 replace the other double cast 2021-12-11 14:24:25 +00:00
Jett
6427b097ab Replace two casts with one 2021-12-11 14:22:39 +00:00
Jett
22de531ab3 Changes asked for by Wincent 2021-12-11 13:57:15 +00:00
Jett
b6453376e4 patched coin exploit 2021-12-11 13:21:00 +00:00
Jett
74742771c4 Added a LogDebug
- Added debug logging
- Created vLog, a root function for all log functions
- Placed failed to load script log under this new LogDebug function
- Updated included config functions
2021-12-11 12:29:34 +00:00
Mick Vermeulen
833ed8a40d Implement Buccaneer Valiant special ability
Adds the ability for the buccaneer valiant to spawn a ship that rams
enemies and smashes them. Next to a script that triggers the ship skill
a few other changes had to be made:
- Force movement behavior server side calculation and sync
- The ship has no physics volume so the FindValidTargets for behaviors
had to be altered to allow ControllablePhysics entities to find entities
within their area. The "target_self" AOE flag has been used to replicate
the old behavior.
2021-12-11 11:59:29 +01:00
Jett
c8991666d2 Potential solution 2021-12-11 10:46:45 +00:00
Mick
e31dc35733 Merge pull request #170 from OogwayUniverse/minifig_editing 2021-12-11 10:50:44 +01:00
Mick
5767ebea38 Merge pull request #132 from StefanH-AT/readme-note-delete-script-pak 2021-12-11 10:48:26 +01:00
Jett
6500b62c52 Minifig editing 2021-12-11 02:02:02 +00:00
Kay Kaprolat
4a1928ba92 removed forgotten TODO from Docker_Windows.md 2021-12-10 22:00:00 +01:00
Kay Kaprolat
6350d8e135 placed images on their own line in Docker_Windows.md 2021-12-10 21:59:20 +01:00
Kay Kaprolat
1dd5ac0ecb resolved merge - removed leading slashes from image paths 2021-12-10 21:54:11 +01:00
Kay Kaprolat
b42c4db400 removed spaces from image names 2021-12-10 21:51:49 +01:00
Kay Kaprolat
dca1361bac Added slashes to image paths 2021-12-10 21:29:42 +01:00
Kay Kaprolat
f7cf0010db clarified CLIENT_PATH 2021-12-10 21:21:22 +01:00
Kay Kaprolat
1073a2e2d1 added all images to Docker_Windows.md 2021-12-10 21:21:06 +01:00
Kay Kaprolat
b6648ff596 cropped images and added highlights 2021-12-10 21:19:47 +01:00
Kay Kaprolat
3a7db82004 added currently used images 2021-12-10 21:03:52 +01:00
Kay Kaprolat
cd3540b085 first draft for Docker usage under Windows 2021-12-10 20:38:51 +01:00
Kay Kaprolat
c7c1500c5e resolved merge conflict 2021-12-10 20:36:05 +01:00
Kay Kaprolat
0316b2189d removed . after command and added link for MacOS 2021-12-10 20:34:21 +01:00
Kay Kaprolat
67ca452993 Make docker-compose consistently docker compose 2021-12-09 22:43:18 +01:00
Nils Bergmann
0bad9d7186 Move utils to submodule 2021-12-09 22:39:54 +01:00
Nils Bergmann
960b090702 Move utils to submodule 2021-12-09 22:39:43 +01:00
Kay Kaprolat
ecbf886e52 Merge TheNoim's current changes. 2021-12-09 22:32:47 +01:00
Nils Bergmann
da5b290809 Merge branch 'DarkflameUniverse:main' into main 2021-12-09 22:29:10 +01:00
Nils Bergmann
d1e0a73f36 Simplify run steps 2021-12-09 22:28:16 +01:00
Jett
a9dc0e0dac to improve (broken) 2021-12-09 21:06:01 +00:00
Kay Kaprolat
22e6caa0e6 added link to Docker Desktop and details on stopping the server 2021-12-09 20:38:15 +01:00
Nils Bergmann
11ade05510 style: fix whitespace 2021-12-09 18:49:46 +01:00
Nils Bergmann
ef7dd0f069 Merge pull request #3 from jgkawell/pr-improvements
Dockerized improvements
2021-12-09 18:46:44 +01:00
Jack Kawell
417ff818d3 Merge pull request #3 from TheNoim/pr-improvements
WIP: make this work independent of the repo directory
2021-12-09 10:44:02 -07:00
Mick
82a1c8a765 Merge pull request #147 from Daystar1998/main
Fix spelling
2021-12-09 18:20:41 +01:00
Mick
1f083cb168 Merge pull request #136 from MickVermeulen/main
Add issue templates
2021-12-09 18:18:24 +01:00
Mick
51600a5329 Merge pull request #134 from DarkflameUniverse/fix-sentry-faction
Update BaseEnemyMech script to change the default faction
2021-12-09 18:17:55 +01:00
Mick
140c736bef Merge pull request #130 from DarkflameUniverse/contributing-commit-guidelines
Update CONTRIBUTING.md to include commit guidelines
2021-12-09 18:17:41 +01:00
Mick Vermeulen
9b085faf07 Add issue templates
Added issue templates to aid with the structural submission of issues.
2021-12-09 18:17:19 +01:00
Nils Bergmann
619eec8335 Merge branch 'pr-improvements' into pr-improvements 2021-12-09 17:43:52 +01:00
Jett
e4de42659e Update Entity.cpp 2021-12-09 13:56:07 +00:00
Jett
bd609dfc90 Add ship shake to not log about being missing
This log was causing confusion and issues when in reality there was no problem present.
2021-12-09 13:09:12 +00:00
Matthew Day
50512cdef8 Fix spelling 2021-12-09 03:17:08 -06:00
Jack Kawell
56f860676d Added admin setup command to docs 2021-12-09 00:37:14 -07:00
Jack Kawell
3b90669d03 Added a link to keygen for flask secret 2021-12-09 00:34:14 -07:00
Jack Kawell
ecd717702d Added client setup check to start_server.sh 2021-12-09 00:20:10 -07:00
Jack Kawell
18d797150e PR comments 2021-12-09 00:10:29 -07:00
Matthew Day
8c16127115 Fix spelling 2021-12-08 23:31:58 -06:00
Mick Vermeulen
f22bf24663 Update BaseEnemyMech script to change the default faction
As part of the base enemy mech script its faction should be updated to 4
to make sure it's seen as an enemy by the client. The AgDarklingMech script
has been deleted as its functionality was essentially that of BaseEnemyMech
and thus no longer necessary.
2021-12-08 20:00:08 +01:00
Stefan Heinz
fdd4e3cc80 Add note to readme for troubleshooting tips with script editing 2021-12-08 18:22:05 +01:00
Mick Vermeulen
e91222b504 Update CONTRIBUTING.md to include commit guidelines
Added commit guidelines to CONTRIBUTING.md to aid people in writing proper
commits.
2021-12-08 18:11:12 +01:00
Nils Bergmann
72ffe50ca6 Merge branch 'DarkflameUniverse:main' into pr-improvements 2021-12-08 15:10:17 +01:00
Nils Bergmann
7f1e392be2 WIP: add master_ip option 2021-12-08 14:57:16 +01:00
Nils Bergmann
51a9f61e88 WIP: make this work independent of the repo directory 2021-12-08 14:39:19 +01:00
Jack Kawell
293aaff2a5 A few more improvements 2021-12-08 01:54:44 -07:00
Jack Kawell
f185c8b5db Moved all the setup of client files into a single use Docker image 2021-12-08 00:50:15 -07:00
Jack Kawell
a38765d02d fixing my mistakes (aka TheNoim is smarter than me) 2021-12-07 23:44:37 -07:00
Jack Kawell
59f053433c External IP configuration as well as other small improvements 2021-12-07 23:33:34 -07:00
a923a2baa7 Merge pull request #116 from DarkflameUniverse/revert-83-main
Revert "separate AgSpaceStuff and AgShipShake"
2021-12-07 18:14:26 -08:00
f68f683e22 Revert "separate AgSpaceStuff and AgShipShake" 2021-12-07 18:14:15 -08:00
Nils Bergmann
0dfc962df5 WIP: connection issue 2021-12-08 02:40:27 +01:00
Nils Bergmann
cf6f69ba93 WIP: try to fix navmesh load 2021-12-08 00:40:15 +01:00
Nils Bergmann
4a3d341c9a WIP: default to BUILD_VERSION=171022 2021-12-07 23:18:20 +01:00
Nils Bergmann
78a04c90e6 WIP: fix migration volume and add ports 2021-12-07 23:17:26 +01:00
Nils Bergmann
9b0ba22ef9 Merge pull request #2 from jgkawell/db-with-volume
DB migrations from volume
2021-12-07 23:09:13 +01:00
Nils Bergmann
0d910e3307 Merge branch 'DarkflameUniverse:main' into main 2021-12-07 23:03:30 +01:00
Jack Kawell
b1e700e2a2 Removed db migrations from script 2021-12-07 14:56:56 -07:00
Jack Kawell
a6190fe29d Add init volume to database 2021-12-07 14:55:19 -07:00
Nils Bergmann
cf79175500 WIP: add basic docker setup instructions 2021-12-07 22:46:02 +01:00
Nils Bergmann
a1f003edd9 WIP: ignore docker-compose.override.yml 2021-12-07 22:44:21 +01:00
Nils Bergmann
0780824e31 WIP: change the example thread size to 1 2021-12-07 22:44:08 +01:00
Nils Bergmann
4cf2f4e7c7 WIP: error if the client path is missing 2021-12-07 22:43:53 +01:00
Nils Bergmann
53c9467bec WIP: use fixed mariadb version 2021-12-07 22:30:08 +01:00
Nils Bergmann
157977e267 Merge pull request #1 from VBMCBoy/main
Add Brick-Building-Fix and AccountManager
2021-12-07 22:28:37 +01:00
Nils Bergmann
e714cacc58 WIP: produce valid MasterServer binary 2021-12-07 22:25:58 +01:00
Kay Kaprolat
ac20be8744 moved healthchecks from Dockerfiles to docker-compose.yml 2021-12-07 22:17:18 +01:00
Kay Kaprolat
2681ab3828 removed AccountManager secret generation from Dockerfile 2021-12-07 22:09:54 +01:00
Kay Kaprolat
7a55db3f21 moved AccountManager secret to environment 2021-12-07 22:08:53 +01:00
Mick
5281253f66 Merge pull request #83 from red031000/main
separate AgSpaceStuff and AgShipShake
2021-12-07 21:53:42 +01:00
red031000
7bead89e39 fix a bug with timer erasing 2021-12-07 20:50:09 +00:00
red031000
002f3b6c0e separate AgSpaceStuff and AgShipShake 2021-12-07 20:50:09 +00:00
Mick
a873de5e9e Merge pull request #68 from Ramen2X/main
Make 0_initial.sql compatible with MySQL
2021-12-07 21:48:44 +01:00
Wincent Holm
73ef2e6c59 Merge pull request #91 from JoachimFlottorp/FixChat
Pull Request to fix chat messages
2021-12-07 21:35:55 +01:00
Kay Kaprolat
b46f833e23 added darkflame network to brickbuildfix 2021-12-07 21:34:06 +01:00
Kay Kaprolat
e01a7be08e added AccountManager 2021-12-07 21:30:08 +01:00
Kay Kaprolat
b35a367ed1 added brick-building fix 2021-12-07 21:25:15 +01:00
wincent
e967bf2398 Updated solution 2021-12-07 21:03:55 +01:00
Nils Bergmann
9387e88dc0 WIP: still no working MasterServer binary 2021-12-07 20:58:18 +01:00
TomNordesen
eede772b53 Nice Commit! :) 2021-12-07 20:43:42 +01:00
TomNordesen
bcb0454916 fixed 2021-12-07 20:38:05 +01:00
TomNordesen
d2fe15679c Nice Commit! :) 2021-12-07 20:35:12 +01:00
TomNordesen
c48f4b08a2 Nice Commit! :) 2021-12-07 20:19:47 +01:00
TomNordesen
bfcce19649 Nice Commit! :) 2021-12-07 19:58:24 +01:00
0db954fa72 Update README.md 2021-12-07 12:15:57 -05:00
Gie "Max" Vanommeslaeghe
6e33f5e545 Merge pull request #88 from OogwayUniverse/windows
Windows fixes (needs proper ZCompresion fix in the future)
2021-12-07 17:30:37 +01:00
Gie "Max" Vanommeslaeghe
eab32c68f3 Update CONTRIBUTING.md 2021-12-07 16:36:38 +01:00
TomNordesen
fe5814d5ba Nice Commit! :) 2021-12-07 16:31:53 +01:00
Nils Bergmann
50221fbd65 WIP: do more post build steps 2021-12-07 16:29:26 +01:00
Nils Bergmann
6f2e306c7e Merge branch 'main' of github.com:TheNoim/DarkflameServer 2021-12-07 14:51:54 +01:00
Nils Bergmann
a59ea5e245 Merge branch 'main' of github.com:TheNoim/DarkflameServer 2021-12-07 14:51:40 +01:00
Nils Bergmann
0add6853bf WIP: completely automated docker setup 2021-12-07 14:50:05 +01:00
Jett
393cce885b Windows fixes
- "Fixed" segfault
- Fixed logger not actually logging time
2021-12-07 11:12:29 +00:00
Mick
b580f19825 Merge pull request #2 from StefanH-AT/readme-cmake-version
Add note to readme about cmake version to build
2021-12-07 10:22:26 +01:00
17e4f2536b Merge pull request #85 from DarkflameUniverse/revert-44-patch/zone_path_casing
Revert "Try to load from original zone path before a lowercased one"
2021-12-07 00:25:33 -08:00
595afc4a93 Revert "Try to load from original zone path before a lowercased one" 2021-12-07 00:25:19 -08:00
Ramen2X
ca287db536 make 0_initial.sql compatible with MySQL 2021-12-06 20:06:12 -05:00
Gie "Max" Vanommeslaeghe
994382b801 Merge pull request #43 from TheLongestRose/patch-1
Important note for WSL2 users
2021-12-06 23:08:41 +01:00
Wincent Holm
d9348054f1 Merge pull request #15 from Arkannex/patch-1
Update NPC.xml
2021-12-06 15:06:34 +01:00
Arkannex
713cb6c6e5 Update NPC.xml 2021-12-06 08:04:19 -06:00
Wincent Holm
d7b443d51b Merge pull request #13 from JoachimFlottorp/main
Modified README specifying CMakeVariables outside the Python box
2021-12-06 15:01:22 +01:00
Wincent Holm
af05371c09 Merge pull request #44 from yuwui/patch/zone_path_casing
Try to load from original zone path before a lowercased one
2021-12-06 14:58:34 +01:00
Wincent Holm
9dc38e87cd Merge pull request #11 from yuwui/patch/default_net_version
change default network version to unmodded client
2021-12-06 14:53:23 +01:00
yuwui
932bf7ca60 update readme 2021-12-06 12:29:42 +01:00
yuwui
2dd96198af try original zone path before lowercasing 2021-12-06 10:31:09 +01:00
TheLongestRose
7dadc4ce77 Important note for WSL2 users
The server and client cannot connect when the server is running on a WSL2 distro and the server is set to localhost, due to differences between WSL1 and 2. This won't affect most people, but would have saved me a few hours.
2021-12-06 00:04:52 -08:00
Wincent Holm
34f1d4002b Merge pull request #38 from yuwui/patch/strip_cr 2021-12-06 07:46:14 +01:00
yuwui
3845dc77f9 strip carriage return from txt files 2021-12-06 07:07:17 +01:00
Wincent Holm
3163c91a4a Merge pull request #34 from aronwk-aaron/patch-1 2021-12-06 06:39:28 +01:00
7e4be6fdb6 Update README.md 2021-12-06 00:39:13 -05:00
4b8712b0f5 Update README.md 2021-12-06 00:37:30 -05:00
2f064f0145 change repo url in worldconfig.ini to be correct 2021-12-05 22:37:32 -06:00
0a9d4d0d66 Update 0_nt_footrace.sql 2021-12-05 19:28:06 -08:00
bcfa1fb906 Update 1_fix_overbuild_mission.sql 2021-12-05 19:27:45 -08:00
3c3a3dba8f Merge pull request #17 from m888r/clangfix
Small fixes for windows clang compile
2021-12-05 19:09:47 -05:00
Manas Shah
f760ef456c Small fixes for windows clang compile 2021-12-05 15:59:50 -08:00
Arkannex
1ba48ecd64 Update NPC.xml
Addition of an NPC to Gnarled Forest near Bucky Urchin.
2021-12-05 17:43:38 -06:00
Max
57ba0cde37 Tweaked markdown of README to reflected what was intended in previous commit. 2021-12-05 17:30:24 -06:00
Max
a409132f69 Marked build.sh as executable and updated README.md to note that build.sh exists and is useful 2021-12-05 17:28:27 -06:00
JoachimF
0c006b4007 Update README.md 2021-12-05 23:50:30 +01:00
Gie "Max" Vanommeslaeghe
498a9c0be4 Merge pull request #3 from luxaritas/patch-1
Note that the zlib -dev package is needed
2021-12-05 23:25:14 +01:00
yuwui
26dd78fff7 change default network version to 171022 2021-12-05 23:16:12 +01:00
Wincent Holm
54810fd5ef Added names to folder to copy over to build/res 2021-12-05 22:11:09 +01:00
Gie "Max" Vanommeslaeghe
27dace206b Merge pull request #6 from XenoTrixx/main
Corrected apt install command for ubuntu
2021-12-05 22:01:39 +01:00
XenoTrixx
a54687671a Correctet apt install command for ubuntu 2021-12-05 21:48:43 +01:00
Jonathan Romano
e0ef02bfdb Note that the zlib -dev package is needed 2021-12-05 15:31:42 -05:00
Stefan Heinz
18d33933d4 Add note to readme about cmake version to build 2021-12-05 21:26:58 +01:00
1848 changed files with 75389 additions and 59825 deletions

View File

@@ -1,37 +0,0 @@
---
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
BeforeLambdaBody: false
BeforeWhile: false
BreakBeforeBraces: Attach
ColumnLimit: 0
IndentWidth: 4
IndentCaseLabels: true
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '<[[:alnum:].]+\.h>'
Priority: 1
- Regex: '<[[:alnum:].]+>'
Priority: 2
- Regex: '.*/.*'
Priority: 3
- Regex: '.*'
Priority: 4
DerivePointerAlignment: false
PointerAlignment: Left
...

View File

@@ -1,17 +0,0 @@
Checks: '-*,readability-*,performance-*,modernize-*,-modernize-use-trailing-return-type,bugprone-*'
WarningsAsErrors: true
HeaderFilterRegex: ''
FormatStyle: none
CheckOptions:
- key: readability-identifier-naming.ClassCase
value: CamelCase
- key: readability-identifier-naming.ClassMethodCase
value: CamelCase
- key: readability-identifier-naming.ClassMemberPrefix
value: m_
- key: readability-identifier-naming.ClassMemberCase
value: CamelCase
- key: readability-identifier-naming.ClassConstantCase
value: UPPER_CASE
- key: readability-identifier-naming.FunctionCase
value: CamelCase

10
.dockerignore Normal file
View File

@@ -0,0 +1,10 @@
.git
Dockerfile
*.md
logo.png
versions.txt
docker-compose.yml
.env
docker/__pycache__
.env.example
build

76
.editorconfig Normal file
View File

@@ -0,0 +1,76 @@
# top-most EditorConfig file
root=true
# Unix-style newlines with a newline ending every file
[*]
indent_style=tab
tab_width=4
charset=utf-8
trim_trailing_whitespace=true
end_of_line=lf
insert_final_newline=true
[*.{c++,cc,cpp,cxx,h,h++,hh,hpp,hxx,inl,ipp,tlh,tli}]
vc_generate_documentation_comments=doxygen_slash_star
cpp_indent_braces=false
cpp_alignment_tab_fill_style=use_spaces
cpp_indent_multi_line_relative_to=innermost_parenthesis
cpp_indent_within_parentheses=indent
cpp_indent_preserve_within_parentheses=false
cpp_indent_case_labels=false
cpp_indent_case_contents=true
cpp_indent_case_contents_when_block=false
cpp_indent_lambda_braces_when_parameter=true
cpp_indent_goto_labels=one_left
cpp_indent_preprocessor=leftmost_column
cpp_indent_access_specifiers=false
cpp_indent_namespace_contents=true
cpp_indent_preserve_comments=false
cpp_new_line_before_open_brace_namespace=same_line
cpp_new_line_before_open_brace_type=same_line
cpp_new_line_before_open_brace_function=same_line
cpp_new_line_before_open_brace_block=same_line
cpp_new_line_before_open_brace_lambda=same_line
cpp_new_line_scope_braces_on_separate_lines=false
cpp_new_line_close_brace_same_line_empty_type=false
cpp_new_line_close_brace_same_line_empty_function=false
cpp_new_line_before_catch=false
cpp_new_line_before_else=false
cpp_new_line_before_while_in_do_while=false
cpp_space_before_function_open_parenthesis=remove
cpp_space_within_parameter_list_parentheses=false
cpp_space_between_empty_parameter_list_parentheses=false
cpp_space_after_keywords_in_control_flow_statements=true
cpp_space_within_control_flow_statement_parentheses=false
cpp_space_before_lambda_open_parenthesis=false
cpp_space_within_cast_parentheses=false
cpp_space_after_cast_close_parenthesis=false
cpp_space_within_expression_parentheses=false
cpp_space_before_block_open_brace=true
cpp_space_between_empty_braces=false
cpp_space_before_initializer_list_open_brace=false
cpp_space_within_initializer_list_braces=true
cpp_space_preserve_in_initializer_list=true
cpp_space_before_open_square_bracket=false
cpp_space_within_square_brackets=false
cpp_space_before_empty_square_brackets=false
cpp_space_between_empty_square_brackets=false
cpp_space_group_square_brackets=true
cpp_space_within_lambda_brackets=false
cpp_space_between_empty_lambda_brackets=false
cpp_space_before_comma=false
cpp_space_after_comma=true
cpp_space_remove_around_member_operators=true
cpp_space_before_inheritance_colon=true
cpp_space_before_constructor_colon=true
cpp_space_remove_before_semicolon=true
cpp_space_after_semicolon=false
cpp_space_remove_around_unary_operator=true
cpp_space_around_binary_operator=insert
cpp_space_around_assignment_operator=insert
cpp_space_pointer_reference_alignment=left
cpp_space_around_ternary_operator=insert
cpp_wrap_preserve_blocks=one_liners
cpp_indent_comment=fasle

14
.env.example Normal file
View File

@@ -0,0 +1,14 @@
# Full path to the LEGO Universe client
CLIENT_PATH=./client
# Updates NET_VERSION in CMakeVariables.txt
NET_VERSION=171022
# make sure this is a long random string
# grab a "SHA 256-bit Key" from here: https://keygen.io/
ACCOUNT_MANAGER_SECRET=
# Should be the externally facing IP of your server host
EXTERNAL_IP=localhost
# Database values
# Be careful with special characters here. It is more safe to use normal characters and/or numbers.
MARIADB_USER=darkflame
MARIADB_PASSWORD=
MARIADB_DATABASE=darkflame

11
.git-blame-ignore-revs Normal file
View File

@@ -0,0 +1,11 @@
# format codebase
19e77a38d837ce781ba0ca6ea8e78b67a6e3b5a5
# add semi-colons to macros consistently
9e4ce24fd2851e65df776dd9c57bcb0d45f4453a
# convert to unix line endings
72477e01e2711e0f61cdb192ee266e5e21b8846f
# enum cleanup
faf42d2f8cf432df2993b031f079b0b8c6d7dbe7

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
* text=auto eol=lf

60
.github/ISSUE_TEMPLATE/bug_report.yaml vendored Normal file
View File

@@ -0,0 +1,60 @@
name: Bug Report
description: Report incorrect behavior in DarkflameServer
title: "BUG: "
labels: ["bug", "triage"]
body:
- type: checkboxes
id: checks
attributes:
label: "Make sure you've done the following:"
options:
- label: >
I have checked that this issue has not already been reported.
required: true
- label: >
I have validated that this issue is not a syntax error of either MySQL or SQLite.
required: true
- label: >
I have pulled the latest version of the main branch of DarkflameServer and have confirmed that the issue exists there.
required: true
- type: input
id: server-version
attributes:
label: DarkflameServer Version
description: >
DarkflameServer version or commit SHA (can be obtained with `git rev-parse --short HEAD`)
validations:
required: true
- type: textarea
id: problem
attributes:
label: Issue Description
description: >
Please provide a description of the issue. If this is an in-game bug, please also include pictures that showcase the issue.
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: Reproduction Steps
description: >
Please provide a concise list of steps needed to reproduce this issue.
validations:
required: true
- type: textarea
id: expected-behavior
attributes:
label: Expected Behavior
description: >
Please describe what you expected to happen instead of the issue.
validations:
required: true
- type: textarea
id: environment
attributes:
label: Environment
description: >
Please include the environment you're running DarkflameServer on (for example: Windows, macOS, Ubuntu, WSL, etc).
validations:
required: true

View File

@@ -0,0 +1,44 @@
name: Documentation Improvement
description: Report wrong or missing documentation
title: "DOC: "
labels: ["docs", "triage"]
body:
- type: checkboxes
id: checks
attributes:
label: "Make sure you've done the following:"
options:
- label: >
I have checked that this issue has not already been reported.
required: true
- label: >
I have validated that the documentation is wrong or missing on the latest version of the main branch of DarkflameServer
required: true
- type: textarea
id: location
attributes:
label: Location of the documentation
description: >
Please provide the location of the documentation, e.g. "Entity.cpp" or the
URL of the documentation, e.g.
"https://github.com/DarkflameUniverse/DarkflameServer/blob/main/README.md"
placeholder: https://github.com/DarkflameUniverse/DarkflameServer/blob/main/README.md
validations:
required: true
- type: textarea
id: problem
attributes:
label: Documentation problem
description: >
Please provide a description of what documentation you believe needs to be fixed/improved
validations:
required: true
- type: textarea
id: suggested-fix
attributes:
label: Suggested fix for documentation
description: >
Please explain the suggested fix and **why** it's better than the existing documentation
validations:
required: true

View File

@@ -0,0 +1,40 @@
name: Feature Request
description: Suggest an idea for DarkflameServer
title: "ENH: "
labels: ["enhancement", "triage"]
body:
- type: textarea
id: problem
attributes:
label: Is your feature request related to a problem?
description: >
Please provide a description of what the problem is, e.g. "I wish I could use DarkflameServer to do [...]"
validations:
required: true
- type: textarea
id: solution
attributes:
label: Describe the solution you'd like
description: >
Please provide a description of the feature request, e.g. "`SlashCommandHandler.cpp` should get a new command `/unlimited-coins` that [...]", try to write a docstring for the desired feature
validations:
required: true
- type: textarea
id: implications
attributes:
label: Repository breaking implications
description: >
Please provide a description of how this feature will affect the DarkflameServer repository
- type: textarea
id: alternatives
attributes:
label: Describe alternatives you've considered
description: >
Please provide a description of any alternative solutions or features you've considered
- type: textarea
id: example
attributes:
label: Additional context
description: >
Please add any other context, code examples, or references to existing implementations about the feature request here

View File

@@ -0,0 +1,62 @@
name: Installation Issue
description: Report issues installing the DarkflameServer on your system
title: "BUILD: "
labels: ["build", "triage"]
body:
- type: checkboxes
id: checks
attributes:
label: "Make sure you've done the following:"
options:
- label: >
I have read the [installation guide](https://github.com/DarkflameUniverse/DarkflameServer/blob/main/README.md).
required: true
- type: input
id: server-version
attributes:
label: DarkflameServer Version
description: >
DarkflameServer version or commit SHA (can be obtained with `git rev-parse --short HEAD`)
validations:
required: true
- type: dropdown
id: platform
attributes:
label: Platform
description: >
Please provide on which platform you've tried to install DarkflameServer
options:
- Windows
- WSL1
- WSL2
- macOS
- Ubuntu
- Other
validations:
required: true
- type: dropdown
id: architecture
attributes:
label: Architecture
description: >
Please provide on which architecture you've tried to install DarkflameServer
options:
- x86
- ARM
validations:
required: true
- type: textarea
id: logs
attributes:
label: Error Logs
description: >
If possible, please copy and paste the error logs when attempting to install DarkflameServer.
value: >
<details>
Replace this line with the error logs.
</details>

View File

@@ -0,0 +1,50 @@
name: Performance Issue
description: Report slow performance or memory issues when running DarkflameServer
title: "PERF: "
labels: ["performance", "triage"]
body:
- type: checkboxes
id: checks
attributes:
label: "Make sure you've done the following:"
options:
- label: >
I have checked that this issue has not already been reported.
required: true
- label: >
I have pulled the latest version of the main branch of DarkflameServer and have confirmed that the issue exists there.
required: true
- type: input
id: server-version
attributes:
label: DarkflameServer Version
description: >
DarkflameServer version or commit SHA (can be obtained with `git rev-parse --short HEAD`)
validations:
required: true
- type: textarea
id: environment
attributes:
label: Environment
description: >
Please include the environment you're running DarkflameServer on (for example: Windows, macOS, Ubuntu, WSL, etc), available memory, number of CPU cores.
validations:
required: true
- type: textarea
id: example
attributes:
label: Reproducible Example
description: >
Please provide a minimal, example that quantifies slow runtime or memory issues.
Ideally include screenshots of CPU usage or memory usage. And if possible point
to the code that you may suspect to cause the issue.
validations:
required: true
- type: textarea
id: prior-performance
attributes:
label: Prior Performance
description: >
If applicable, please provide the prior version of DarkflameServer and output
of the same reproducible example where the performance issue did not exist.

View File

@@ -0,0 +1,56 @@
name: CI
on:
push:
branches:
- "main"
tags:
- "v*.*.*"
pull_request:
branches:
- "main"
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# generate Docker tags based on the following events/attributes
tags: |
type=ref,event=pr
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

51
.github/workflows/build-and-test.yml vendored Normal file
View File

@@ -0,0 +1,51 @@
name: CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build-and-test:
name: Build & Test (${{ matrix.os }})
runs-on: ${{ matrix.os }}
continue-on-error: true
strategy:
matrix:
os: [ windows-2022, ubuntu-20.04, macos-11 ]
steps:
- uses: actions/checkout@v3
with:
submodules: true
- name: Add msbuild to PATH (Windows only)
if: ${{ matrix.os == 'windows-2022' }}
uses: microsoft/setup-msbuild@v1.1
with:
vs-version: '[17,18)'
msbuild-architecture: x64
- name: Install libssl (Mac Only)
if: ${{ matrix.os == 'macos-11' }}
run: brew install openssl@3
- name: cmake
uses: lukka/run-cmake@v10
with:
configurePreset: "ci-${{matrix.os}}"
buildPreset: "ci-${{matrix.os}}"
testPreset: "ci-${{matrix.os}}"
- name: artifacts
uses: actions/upload-artifact@v3
with:
name: build-${{matrix.os}}
path: |
build/*Server*
build/*.ini
build/*.so
build/*.dll
build/vanity/
build/navmeshes/
build/migrations/
build/*.dcf
!build/*.pdb
!build/d*/

9
.gitignore vendored
View File

@@ -1,6 +1,7 @@
temp/
cmake-build-debug/
RelWithDebInfo/
docker/configs
# Third party libraries
thirdparty/mysql/
@@ -114,3 +115,11 @@ CMakeFiles/TargetDirectories.txt
# clangd
.cache
thirdparty/zlib-1.2.11/
.env
docker/__pycache__
docker-compose.override.yml
!*Test.bin
!cmake/*

7
.gitmodules vendored
View File

@@ -10,3 +10,10 @@
[submodule "thirdparty/libbcrypt"]
path = thirdparty/libbcrypt
url = https://github.com/trusch/libbcrypt.git
[submodule "thirdparty/mariadb-connector-cpp"]
path = thirdparty/mariadb-connector-cpp
url = https://github.com/mariadb-corporation/mariadb-connector-cpp.git
ignore = dirty
[submodule "thirdparty/magic_enum"]
path = thirdparty/magic_enum
url = https://github.com/Neargye/magic_enum.git

View File

@@ -1,5 +1,9 @@
cmake_minimum_required(VERSION 3.12)
cmake_minimum_required(VERSION 3.18)
project(Darkflame)
include(CTest)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
# Read variables from file
FILE(READ "${CMAKE_SOURCE_DIR}/CMakeVariables.txt" variables)
@@ -9,478 +13,348 @@ string(REPLACE "\n" ";" variables ${variables})
# Set the cmake variables, formatted as "VARIABLE #" in variables
foreach(variable ${variables})
# If the string contains a #, skip it
if("${variable}" MATCHES "#")
continue()
endif()
# If the string contains a #, skip it
if(NOT "${variable}" MATCHES "#")
# Split the variable into name and value
string(REPLACE "=" ";" variable ${variable})
# Split the variable into name and value
string(REPLACE "=" ";" variable ${variable})
# Check that the length of the variable is 2 (name and value)
list(LENGTH variable length)
# Check that the length of the variable is 2 (name and value)
list(LENGTH variable length)
if(NOT ${length} EQUAL 2)
continue()
endif()
if(${length} EQUAL 2)
list(GET variable 0 variable_name)
list(GET variable 1 variable_value)
list(GET variable 0 variable_name)
list(GET variable 1 variable_value)
# Set the variable
set(${variable_name} ${variable_value})
# Set the variable
set(${variable_name} ${variable_value})
# Add compiler definition
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D${variable_name}=${variable_value}")
message(STATUS "Variable: ${variable_name} = ${variable_value}")
message(STATUS "Variable: ${variable_name} = ${variable_value}")
endif()
endif()
endforeach()
# On windows it's better to build this from source, as there's no way FindZLIB is gonna find it
if(NOT WIN32)
find_package(ZLIB REQUIRED)
endif()
# Fetch External (Non-Submodule) Libraries
if(WIN32)
include(FetchContent)
FetchContent_Declare(
mysql
URL https://dev.mysql.com/get/Downloads/Connector-C++/mysql-connector-c++-8.0.27-winx64.zip
URL_HASH MD5=e3c53f6e4d0a72fde2713f7597bf9468
)
FetchContent_Declare(
zlib
URL http://github.com/madler/zlib/archive/refs/tags/v1.2.11.zip
URL_HASH MD5=9d6a627693163bbbf3f26403a3a0b0b1
)
FetchContent_MakeAvailable(zlib)
FetchContent_MakeAvailable(mysql)
set(ZLIB_INCLUDE_DIRS ${zlib_SOURCE_DIR} ${zlib_BINARY_DIR})
set_target_properties(zlib PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${ZLIB_INCLUDE_DIRS}") # Why?
add_library(ZLIB::ZLIB ALIAS zlib) # You're welcome
endif(WIN32)
if(UNIX)
if(APPLE)
else()
include(FetchContent)
FetchContent_Declare(
mysql
URL https://dev.mysql.com/get/Downloads/Connector-C++/mysql-connector-c++-8.0.27-linux-glibc2.12-x86-64bit.tar.gz
URL_HASH MD5=12f086b76c11022cc7139b41a36cdf9e
)
FetchContent_MakeAvailable(mysql)
if (__include_backtrace__ AND __compile_backtrace__)
FetchContent_Declare(
backtrace
GIT_REPOSITORY https://github.com/ianlancetaylor/libbacktrace.git
)
FetchContent_MakeAvailable(backtrace)
if (NOT EXISTS ${backtrace_SOURCE_DIR}/.libs)
set(backtrace_make_cmd "${backtrace_SOURCE_DIR}/configure --prefix=\"/usr\" --enable-shared --with-system-libunwind")
execute_process(
COMMAND bash -c "cd ${backtrace_SOURCE_DIR} && ${backtrace_make_cmd} && make && cd ${CMAKE_SOURCE_DIR}"
)
endif()
link_directories(${backtrace_SOURCE_DIR}/.libs/)
include_directories(${backtrace_SOURCE_DIR})
endif(__include_backtrace__)
endif()
endif(UNIX)
# Set the version
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPROJECT_VERSION=${PROJECT_VERSION}")
set(PROJECT_VERSION "\"${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}\"")
# Echo the version
message(STATUS "Version: ${PROJECT_VERSION}")
set(CMAKE_CXX_STANDARD 17)
if(WIN32)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
endif(WIN32)
# Our output dir
set(CMAKE_BINARY_DIR ${PROJECT_BINARY_DIR})
# Create a /res directory
make_directory(${CMAKE_BINARY_DIR}/res)
# Create a /locale directory
make_directory(${CMAKE_BINARY_DIR}/locale)
# Copy ini files on first build
if (NOT EXISTS ${PROJECT_BINARY_DIR}/authconfig.ini)
configure_file(
${CMAKE_SOURCE_DIR}/resources/authconfig.ini ${PROJECT_BINARY_DIR}/authconfig.ini
COPYONLY
)
endif()
if (NOT EXISTS ${PROJECT_BINARY_DIR}/chatconfig.ini)
configure_file(
${CMAKE_SOURCE_DIR}/resources/chatconfig.ini ${PROJECT_BINARY_DIR}/chatconfig.ini
COPYONLY
)
endif()
if (NOT EXISTS ${PROJECT_BINARY_DIR}/worldconfig.ini)
configure_file(
${CMAKE_SOURCE_DIR}/resources/worldconfig.ini ${PROJECT_BINARY_DIR}/worldconfig.ini
COPYONLY
)
endif()
if (NOT EXISTS ${PROJECT_BINARY_DIR}/masterconfig.ini)
configure_file(
${CMAKE_SOURCE_DIR}/resources/masterconfig.ini ${PROJECT_BINARY_DIR}/masterconfig.ini
COPYONLY
)
endif()
# Copy files to output
configure_file("${CMAKE_SOURCE_DIR}/vanity/CREDITS.md" "${CMAKE_BINARY_DIR}/vanity/CREDITS.md" COPYONLY)
configure_file("${CMAKE_SOURCE_DIR}/vanity/INFO.md" "${CMAKE_BINARY_DIR}/vanity/INFO.md" COPYONLY)
configure_file("${CMAKE_SOURCE_DIR}/vanity/TESTAMENT.md" "${CMAKE_BINARY_DIR}/vanity/TESTAMENT.md" COPYONLY)
configure_file("${CMAKE_SOURCE_DIR}/vanity/NPC.xml" "${CMAKE_BINARY_DIR}/vanity/NPC.xml" COPYONLY)
# 3rdparty includes
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/raknet/Source/)
if(UNIX)
if(APPLE)
include_directories(/usr/local/include/)
include_directories(/usr/local/mysql-connector-c++/include/jdbc/)
include_directories(/usr/local/mysql-connector-c++/include/jdbc/cppconn/)
else()
include_directories(${mysql_SOURCE_DIR}/include/jdbc/)
include_directories(${mysql_SOURCE_DIR}/include/jdbc/cppconn/)
endif(APPLE)
endif(UNIX)
if(WIN32)
include_directories(${mysql_SOURCE_DIR}/include/jdbc)
include_directories(${mysql_SOURCE_DIR}/include/jdbc/cppconn)
endif(WIN32)
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/tinyxml2/)
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/recastnavigation/Recast/Include)
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/recastnavigation/Detour/Include)
include_directories(${ZLIB_INCLUDE_DIRS})
# Bcrypt
if (NOT WIN32)
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/libbcrypt)
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/libbcrypt/include/bcrypt)
else ()
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/libbcrypt/include)
endif ()
# Our includes
include_directories(${PROJECT_BINARY_DIR})
include_directories(${PROJECT_SOURCE_DIR}/dChatFilter/)
include_directories(${PROJECT_SOURCE_DIR}/dCommon/)
include_directories(${PROJECT_SOURCE_DIR}/dGame/)
include_directories(${PROJECT_SOURCE_DIR}/dGame/dBehaviors)
include_directories(${PROJECT_SOURCE_DIR}/dGame/dComponents)
include_directories(${PROJECT_SOURCE_DIR}/dGame/dGameMessages)
include_directories(${PROJECT_SOURCE_DIR}/dGame/dInventory)
include_directories(${PROJECT_SOURCE_DIR}/dGame/dMission)
include_directories(${PROJECT_SOURCE_DIR}/dGame/dEntity)
include_directories(${PROJECT_SOURCE_DIR}/dGame/dUtilities)
include_directories(${PROJECT_SOURCE_DIR}/dPhysics/)
include_directories(${PROJECT_SOURCE_DIR}/dZoneManager/)
include_directories(${PROJECT_SOURCE_DIR}/dDatabase/)
include_directories(${PROJECT_SOURCE_DIR}/dDatabase/Tables/)
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/SQLite/)
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/cpplinq/)
include_directories(${PROJECT_SOURCE_DIR}/dNet/)
include_directories(${PROJECT_SOURCE_DIR}/dScripts/)
# Default to linking to libmysql
set(MYSQL_LIB mysql)
if(WIN32)
set(MYSQL_LIB mysqlcppconn)
endif(WIN32)
# Lib folders:
link_directories(${PROJECT_BINARY_DIR})
if(UNIX)
if(APPLE)
link_directories(/usr/local/mysql-connector-c++/lib64/)
else()
link_directories(${mysql_SOURCE_DIR}/lib64/)
# Link to libmysqlcppconn on Linux
set(MYSQL_LIB mysqlcppconn)
endif(APPLE)
endif(UNIX)
if(WIN32)
link_directories(${mysql_SOURCE_DIR}/lib64/vs14)
endif(WIN32)
# Source Code
file(
GLOB SOURCES
LIST_DIRECTORIES false
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
${PROJECT_SOURCE_DIR}/dWorldServer/*.cpp
)
# Source Code for AuthServer
file(
GLOB SOURCES_AUTH
LIST_DIRECTORIES false
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
${PROJECT_SOURCE_DIR}/dAuthServer/*.cpp
)
# Source Code for MasterServer
file(
GLOB SOURCES_MASTER
LIST_DIRECTORIES false
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
${PROJECT_SOURCE_DIR}/dMasterServer/*.cpp
)
# Source Code for ChatServer
file(
GLOB SOURCES_CHAT
LIST_DIRECTORIES false
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
${PROJECT_SOURCE_DIR}/dChatServer/*.cpp
)
# Source Code for raknet
file(
GLOB SOURCES_RAKNET
LIST_DIRECTORIES false
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
${PROJECT_SOURCE_DIR}/thirdparty/raknet/Source/*.cpp
)
# Source Code for recast
file(
GLOB SOURCES_RECAST
LIST_DIRECTORIES false
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
${PROJECT_SOURCE_DIR}/thirdparty/recastnavigation/Recast/Source/*.cpp
)
# Source Code for detour
file(
GLOB SOURCES_DETOUR
LIST_DIRECTORIES false
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
${PROJECT_SOURCE_DIR}/thirdparty/recastnavigation/Detour/Source/*.cpp
)
# Source Code for tinyxml2
file(
GLOB SOURCES_TINYXML2
LIST_DIRECTORIES false
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
${PROJECT_SOURCE_DIR}/thirdparty/tinyxml2/tinyxml2.cpp
)
# Source Code for libbcrypt
file(
GLOB SOURCES_LIBBCRYPT
LIST_DIRECTORIES false
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
${PROJECT_SOURCE_DIR}/thirdparty/libbcrypt/*.c
${PROJECT_SOURCE_DIR}/thirdparty/libbcrypt/src/*.c
)
# Source Code for dCommon
file(
GLOB SOURCES_DCOMMON
LIST_DIRECTORIES false
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
${PROJECT_SOURCE_DIR}/dCommon/*.cpp
)
# Source Code for dChatFilter
file(
GLOB SOURCES_DCHATFILTER
LIST_DIRECTORIES false
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
${PROJECT_SOURCE_DIR}/dChatFilter/*.cpp
)
# Source Code for dDatabase
file(
GLOB SOURCES_DDATABASE
LIST_DIRECTORIES false
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
${PROJECT_SOURCE_DIR}/dDatabase/*.cpp
${PROJECT_SOURCE_DIR}/dDatabase/Tables/*.cpp
${PROJECT_SOURCE_DIR}/thirdparty/SQLite/*.cpp
${PROJECT_SOURCE_DIR}/thirdparty/SQLite/*.c
)
# Source Code for dNet
file(
GLOB SOURCES_DNET
LIST_DIRECTORIES false
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
${PROJECT_SOURCE_DIR}/dNet/*.cpp
)
# Source Code for dGame
file(
GLOB SOURCES_DGAME
LIST_DIRECTORIES false
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
${PROJECT_SOURCE_DIR}/dGame/*.cpp
${PROJECT_SOURCE_DIR}/dGame/dBehaviors/*.cpp
${PROJECT_SOURCE_DIR}/dGame/dComponents/*.cpp
${PROJECT_SOURCE_DIR}/dGame/dGameMessages/*.cpp
${PROJECT_SOURCE_DIR}/dGame/dInventory/*.cpp
${PROJECT_SOURCE_DIR}/dGame/dMission/*.cpp
${PROJECT_SOURCE_DIR}/dGame/dEntity/*.cpp
${PROJECT_SOURCE_DIR}/dGame/dUtilities/*.cpp
${PROJECT_SOURCE_DIR}/dScripts/*.cpp
)
# Source Code for dZoneManager
file(
GLOB SOURCES_DZM
LIST_DIRECTORIES false
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
${PROJECT_SOURCE_DIR}/dZoneManager/*.cpp
)
# Source Code for dPhysics
file(
GLOB SOURCES_DPHYSICS
LIST_DIRECTORIES false
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
${PROJECT_SOURCE_DIR}/dPhysics/*.cpp
)
# 3rdparty static libraries:
#add_library(zlib ${SOURCES_ZLIB})
add_library(raknet ${SOURCES_RAKNET})
add_library(tinyxml2 ${SOURCES_TINYXML2})
add_library(detour ${SOURCES_DETOUR})
add_library(recast ${SOURCES_RECAST})
add_library(libbcrypt ${SOURCES_LIBBCRYPT})
# Our static libraries:
add_library(dCommon ${SOURCES_DCOMMON})
add_library(dChatFilter ${SOURCES_DCHATFILTER})
add_library(dDatabase ${SOURCES_DDATABASE})
add_library(dNet ${SOURCES_DNET})
add_library(dGame ${SOURCES_DGAME})
add_library(dZoneManager ${SOURCES_DZM})
add_library(dPhysics ${SOURCES_DPHYSICS})
target_link_libraries(dNet dCommon) #Needed because otherwise linker errors occur.
target_link_libraries(dCommon ZLIB::ZLIB)
target_link_libraries(dCommon libbcrypt)
# Our executables:
add_executable(WorldServer ${SOURCES})
add_executable(AuthServer ${SOURCES_AUTH})
add_executable(MasterServer ${SOURCES_MASTER})
add_executable(ChatServer ${SOURCES_CHAT})
# Target libraries to link to:
target_link_libraries(WorldServer dCommon)
target_link_libraries(WorldServer dChatFilter)
target_link_libraries(WorldServer dDatabase)
target_link_libraries(WorldServer dNet)
target_link_libraries(WorldServer dGame)
target_link_libraries(WorldServer dZoneManager)
target_link_libraries(WorldServer dPhysics)
target_link_libraries(WorldServer detour)
target_link_libraries(WorldServer recast)
target_link_libraries(WorldServer raknet)
target_link_libraries(WorldServer ${MYSQL_LIB})
if(UNIX)
target_link_libraries(WorldServer pthread)
target_link_libraries(WorldServer dl)
if(NOT APPLE AND __include_backtrace__)
target_link_libraries(WorldServer backtrace)
target_link_libraries(MasterServer backtrace)
target_link_libraries(AuthServer backtrace)
target_link_libraries(ChatServer backtrace)
endif()
endif(UNIX)
if(WIN32)
target_link_libraries(WorldServer ws2_32)
endif(WIN32)
target_link_libraries(WorldServer tinyxml2)
# Target libraries for Auth:
target_link_libraries(AuthServer dCommon)
target_link_libraries(AuthServer dDatabase)
target_link_libraries(AuthServer dNet)
target_link_libraries(AuthServer raknet)
target_link_libraries(AuthServer ${MYSQL_LIB})
if(UNIX)
target_link_libraries(AuthServer pthread)
target_link_libraries(AuthServer dl)
endif(UNIX)
if(WIN32)
target_link_libraries(AuthServer ws2_32)
endif(WIN32)
# Target libraries for Master:
target_link_libraries(MasterServer dCommon)
target_link_libraries(MasterServer dDatabase)
target_link_libraries(MasterServer dNet)
target_link_libraries(MasterServer raknet)
target_link_libraries(MasterServer ${MYSQL_LIB})
if(UNIX)
target_link_libraries(MasterServer pthread)
target_link_libraries(MasterServer dl)
endif(UNIX)
if(WIN32)
target_link_libraries(MasterServer ws2_32)
endif(WIN32)
# Target libraries for Chat:
target_link_libraries(ChatServer dCommon)
target_link_libraries(ChatServer dChatFilter)
target_link_libraries(ChatServer dDatabase)
target_link_libraries(ChatServer dNet)
target_link_libraries(ChatServer raknet)
target_link_libraries(ChatServer ${MYSQL_LIB})
if(UNIX)
target_link_libraries(ChatServer pthread)
target_link_libraries(ChatServer dl)
endif(UNIX)
if(WIN32)
target_link_libraries(ChatServer ws2_32)
endif(WIN32)
# Disable demo, tests and examples for recastNavigation. Turn these to ON if you want to use them
# This has to be done here to prevent a rare build error due to missing dependencies on the initial generations.
set(RECASTNAVIGATION_DEMO OFF CACHE BOOL "" FORCE)
set(RECASTNAVIGATION_TESTS OFF CACHE BOOL "" FORCE)
set(RECASTNAVIGATION_EXAMPLES OFF CACHE BOOL "" FORCE)
# Compiler flags:
# Disabled deprecated warnings as the MySQL includes have deprecated code in them.
# Disabled deprecated warnings as the MySQL includes have deprecated code in them.
# Disabled misleading indentation as DL_LinkedList from RakNet has a weird indent.
# Disabled no-register
# Disabled unknown pragmas because Linux doesn't understand Windows pragmas.
if(UNIX)
if(APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17 -O2 -Wuninitialized -Wno-unused-result -Wno-unknown-pragmas -fpermissive -D_GLIBCXX_USE_CXX11_ABI=0 -D_GLIBCXX_USE_CXX17_ABI=0 -fPIC")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17 -O2 -Wuninitialized -Wno-unused-result -Wno-unknown-pragmas -fpermissive -D_GLIBCXX_USE_CXX11_ABI=0 -D_GLIBCXX_USE_CXX17_ABI=0 -static-libgcc -fPIC")
endif()
if (__dynamic)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -rdynamic")
endif()
if (__ggdb)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ggdb")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -O2 -fPIC")
endif(UNIX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wuninitialized -fPIC")
add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0 _GLIBCXX_USE_CXX17_ABI=0)
if(NOT APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -lstdc++fs")
endif()
if(${DYNAMIC} AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -rdynamic")
endif()
if(${GGDB})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ggdb")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -O2 -fPIC")
elseif(MSVC)
# Skip warning for invalid conversion from size_t to uint32_t for all targets below for now
add_compile_options("/wd4267" "/utf-8")
elseif(WIN32)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
endif()
# Our output dir
set(CMAKE_BINARY_DIR ${PROJECT_BINARY_DIR})
# TODO make this not have to override the build type directories
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
# Create a /resServer directory
make_directory(${CMAKE_BINARY_DIR}/resServer)
# Create a /logs directory
make_directory(${CMAKE_BINARY_DIR}/logs)
# Copy resource files on first build
set(RESOURCE_FILES "sharedconfig.ini" "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini" "blacklist.dcf")
message(STATUS "Checking resource file integrity")
include(Utils)
UpdateConfigOption(${PROJECT_BINARY_DIR}/authconfig.ini "port" "auth_server_port")
UpdateConfigOption(${PROJECT_BINARY_DIR}/chatconfig.ini "port" "chat_server_port")
UpdateConfigOption(${PROJECT_BINARY_DIR}/masterconfig.ini "port" "master_server_port")
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(
${CMAKE_SOURCE_DIR}/resources/${resource_file} ${PROJECT_BINARY_DIR}/${resource_file}
COPYONLY
)
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()
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
configure_file(${CMAKE_SOURCE_DIR}/resources/navmeshes.zip ${PROJECT_BINARY_DIR}/navmeshes.zip COPYONLY)
file(ARCHIVE_EXTRACT INPUT ${PROJECT_BINARY_DIR}/navmeshes.zip DESTINATION ${PROJECT_BINARY_DIR}/navmeshes)
file(REMOVE ${PROJECT_BINARY_DIR}/navmeshes.zip)
# Copy vanity files on first build
set(VANITY_FILES "CREDITS.md" "INFO.md" "TESTAMENT.md" "NPC.xml")
foreach(file ${VANITY_FILES})
configure_file("${CMAKE_SOURCE_DIR}/vanity/${file}" "${CMAKE_BINARY_DIR}/vanity/${file}" COPYONLY)
endforeach()
# Move our migrations for MasterServer to run
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/migrations/dlu/)
file(GLOB SQL_FILES ${CMAKE_SOURCE_DIR}/migrations/dlu/*.sql)
foreach(file ${SQL_FILES})
get_filename_component(file ${file} NAME)
configure_file(${CMAKE_SOURCE_DIR}/migrations/dlu/${file} ${PROJECT_BINARY_DIR}/migrations/dlu/${file})
endforeach()
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/migrations/cdserver/)
file(GLOB SQL_FILES ${CMAKE_SOURCE_DIR}/migrations/cdserver/*.sql)
foreach(file ${SQL_FILES})
get_filename_component(file ${file} NAME)
configure_file(${CMAKE_SOURCE_DIR}/migrations/cdserver/${file} ${PROJECT_BINARY_DIR}/migrations/cdserver/${file})
endforeach()
# Create our list of include directories
set(INCLUDED_DIRECTORIES
"dCommon"
"dCommon/dClient"
"dCommon/dEnums"
"dChatFilter"
"dGame"
"dGame/dBehaviors"
"dGame/dComponents"
"dGame/dGameMessages"
"dGame/dInventory"
"dGame/dMission"
"dGame/dEntity"
"dGame/dPropertyBehaviors"
"dGame/dPropertyBehaviors/ControlBehaviorMessages"
"dGame/dUtilities"
"dPhysics"
"dNavigation"
"dNavigation/dTerrain"
"dZoneManager"
"dDatabase"
"dDatabase/CDClientDatabase"
"dDatabase/CDClientDatabase/CDClientTables"
"dDatabase/GameDatabase"
"dDatabase/GameDatabase/ITables"
"dDatabase/GameDatabase/MySQL"
"dDatabase/GameDatabase/MySQL/Tables"
"dNet"
"thirdparty/magic_enum/include/magic_enum"
"thirdparty/raknet/Source"
"thirdparty/tinyxml2"
"thirdparty/recastnavigation"
"thirdparty/SQLite"
"thirdparty/cpplinq"
"thirdparty/cpp-httplib"
"tests"
"tests/dCommonTests"
"tests/dGameTests"
"tests/dGameTests/dComponentsTests"
)
# Add system specfic includes for Apple, Windows and Other Unix OS' (including Linux)
if(APPLE)
include_directories("/usr/local/include/")
endif()
# Actually include the directories from our list
foreach(dir ${INCLUDED_DIRECTORIES})
include_directories(${PROJECT_SOURCE_DIR}/${dir})
endforeach()
if(NOT WIN32)
include_directories("${PROJECT_SOURCE_DIR}/thirdparty/libbcrypt/include/bcrypt")
endif()
include_directories("${PROJECT_SOURCE_DIR}/thirdparty/libbcrypt/include")
# Add linking directories:
link_directories(${PROJECT_BINARY_DIR})
# Load all of our third party directories
add_subdirectory(thirdparty)
# Glob together all headers that need to be precompiled
file(
GLOB HEADERS_DDATABASE
LIST_DIRECTORIES false
${PROJECT_SOURCE_DIR}/dDatabase/CDClientDatabase/*.h
${PROJECT_SOURCE_DIR}/dDatabase/CDClientDatabase/CDClientTables/*.h
${PROJECT_SOURCE_DIR}/dDatabase/GameDatabase/ITables/*.h
${PROJECT_SOURCE_DIR}/thirdparty/SQLite/*.h
)
file(
GLOB HEADERS_DZONEMANAGER
LIST_DIRECTORIES false
${PROJECT_SOURCE_DIR}/dZoneManager/*.h
)
file(
GLOB HEADERS_DCOMMON
LIST_DIRECTORIES false
${PROJECT_SOURCE_DIR}/dCommon/*.h
)
file(
GLOB HEADERS_DGAME
LIST_DIRECTORIES false
${PROJECT_SOURCE_DIR}/dGame/Entity.h
${PROJECT_SOURCE_DIR}/dGame/dGameMessages/GameMessages.h
${PROJECT_SOURCE_DIR}/dGame/EntityManager.h
${PROJECT_SOURCE_DIR}/dScripts/CppScripts.h
)
# Add our library subdirectories for creation of the library object
add_subdirectory(dCommon)
add_subdirectory(dDatabase)
add_subdirectory(dChatFilter)
add_subdirectory(dNet)
add_subdirectory(dScripts) # Add for dGame to use
add_subdirectory(dGame)
add_subdirectory(dZoneManager)
add_subdirectory(dNavigation)
add_subdirectory(dPhysics)
add_subdirectory(dServer)
# Create a list of common libraries shared between all binaries
set(COMMON_LIBRARIES "dCommon" "dDatabase" "dNet" "raknet" "mariadbConnCpp" "magic_enum")
# Add platform specific common libraries
if(UNIX)
set(COMMON_LIBRARIES ${COMMON_LIBRARIES} "dl" "pthread")
if(NOT APPLE AND ${INCLUDE_BACKTRACE})
set(COMMON_LIBRARIES ${COMMON_LIBRARIES} "backtrace")
endif()
endif()
# Include all of our binary directories
add_subdirectory(dWorldServer)
add_subdirectory(dAuthServer)
add_subdirectory(dChatServer)
add_subdirectory(dMasterServer) # Add MasterServer last so it can rely on the other binaries
target_precompile_headers(
dZoneManager PRIVATE
${HEADERS_DZONEMANAGER}
)
# Need to specify to use the CXX compiler language here or else we get errors including <string>.
target_precompile_headers(
dDatabase PRIVATE
"$<$<COMPILE_LANGUAGE:CXX>:${HEADERS_DDATABASE}>"
)
target_precompile_headers(
dCommon PRIVATE
${HEADERS_DCOMMON}
)
target_precompile_headers(
tinyxml2 PRIVATE
"$<$<COMPILE_LANGUAGE:CXX>:${PROJECT_SOURCE_DIR}/thirdparty/tinyxml2/tinyxml2.h>"
)
if(${ENABLE_TESTING})
add_subdirectory(tests)
endif()

128
CMakePresets.json Normal file
View File

@@ -0,0 +1,128 @@
{
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 14,
"patch": 0
},
"configurePresets": [
{
"name": "default",
"displayName": "Default configure step",
"description": "Use 'build' dir and Unix makefiles",
"binaryDir": "${sourceDir}/build",
"generator": "Unix Makefiles"
},
{
"name": "ci-ubuntu-20.04",
"displayName": "CI configure step for Ubuntu",
"description": "Same as default, Used in GitHub actions workflow",
"inherits": "default"
},
{
"name": "ci-macos-11",
"displayName": "CI configure step for MacOS",
"description": "Same as default, Used in GitHub actions workflow",
"inherits": "default"
},
{
"name": "ci-windows-2022",
"displayName": "CI configure step for Windows",
"description": "Set architecture to 64-bit (b/c RakNet)",
"inherits": "default",
"generator": "Visual Studio 17 2022",
"architecture": {
"value": "x64"
},
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
}
},
{
"name": "windows-default",
"inherits": "ci-windows-2022",
"displayName": "Windows only Configure Settings",
"description": "Sets build and install directories",
"generator": "Ninja",
"architecture": {
"value": "x64",
"strategy": "external"
}
}
],
"buildPresets": [
{
"name": "default",
"configurePreset": "default",
"displayName": "Default Build",
"description": "Default Build",
"jobs": 2
},
{
"name": "ci-windows-2022",
"configurePreset": "ci-windows-2022",
"displayName": "Windows CI Build",
"description": "This preset is used by the CI build on windows",
"configuration": "RelWithDebInfo",
"jobs": 2
},
{
"name": "ci-ubuntu-20.04",
"configurePreset": "ci-ubuntu-20.04",
"displayName": "Linux CI Build",
"description": "This preset is used by the CI build on linux",
"jobs": 2
},
{
"name": "ci-macos-11",
"configurePreset": "ci-macos-11",
"displayName": "MacOS CI Build",
"description": "This preset is used by the CI build on MacOS",
"jobs": 2
}
],
"testPresets": [
{
"name": "ci-ubuntu-20.04",
"configurePreset": "ci-ubuntu-20.04",
"displayName": "CI Tests on Linux",
"description": "Runs all tests on a linux configuration",
"execution": {
"jobs": 2
},
"output": {
"outputOnFailure": true
}
},
{
"name": "ci-macos-11",
"configurePreset": "ci-macos-11",
"displayName": "CI Tests on MacOS",
"description": "Runs all tests on a Mac configuration",
"execution": {
"jobs": 2
},
"output": {
"outputOnFailure": true
}
},
{
"name": "ci-windows-2022",
"configurePreset": "ci-windows-2022",
"displayName": "CI Tests on windows",
"description": "Runs all tests on a windows configuration",
"configuration": "RelWithDebInfo",
"execution": {
"jobs": 2
},
"output": {
"outputOnFailure": true
},
"filter": {
"exclude": {
"name": "((example)|(minigzip))+"
}
}
}
]
}

View File

@@ -1,18 +1,32 @@
PROJECT_VERSION_MAJOR=1
PROJECT_VERSION_MINOR=0
PROJECT_VERSION_PATCH=0
# LICENSE
LICENSE=AGPL-3.0
# The network version.
# 171023 - Darkflame Universe client
# 171022 - Unmodded client
NET_VERSION=171023
PROJECT_VERSION_MINOR=1
PROJECT_VERSION_PATCH=1
# Debugging
# __dynamic=1
# Set __dynamic to 1 to enable the -rdynamic flag for the linker, yielding some symbols in crashlogs.
# __ggdb=1
# Set __ggdb to 1 to enable the -ggdb flag for the linker, including more debug info.
# __include_backtrace__=1
# Set __include_backtrace__ to 1 to includes the backtrace library for better crashlogs.
# __compile_backtrace__=1
# Set __compile_backtrace__ to 1 to compile the backtrace library instead of using system libraries.
# Set DYNAMIC to 1 to enable the -rdynamic flag for the linker, yielding some symbols in crashlogs.
DYNAMIC=1
# Set GGDB to 1 to enable the -ggdb flag for the linker, including more debug info.
# Do note, changing this will re-build the whole server
GGDB=0
# Set INCLUDE_BACKTRACE to 1 to includes the backtrace library for better crashlogs.
# Do note, changing this will re-build the whole server
INCLUDE_BACKTRACE=0
# Set COMPILE_BACKTRACE to 1 to compile the backtrace library instead of using system libraries.
# Do note, changing this will re-build the whole server
COMPILE_BACKTRACE=0
# Set to the number of jobs (make -j equivalent) to compile the mariadbconn files with.
MARIADB_CONNECTOR_COMPILE_JOBS=1
# When set to 1 and uncommented, compiling and linking testing folders and libraries will be done.
ENABLE_TESTING=1
# The path to OpenSSL. Change this if your OpenSSL install path is different than the default.
OPENSSL_ROOT_DIR=/usr/local/opt/openssl@3/
# Whether or not to cache the entire CDClient Database into memory instead of lazy loading.
# 0 means to lazy load, all other values mean load the entire database.
CDCLIENT_CACHE_ALL=0

View File

@@ -36,23 +36,109 @@ In general, we follow the "fork-and-pull" Git workflow
- Open a PR in our repository.
PRs should include (when applicable):
- A descriptive title that covers the **entire** content of the pull request
- Description
- Motivation and Context
- Type of Changes
- How Has This Been Tested?
- Screenshots
## Commits
Commits to this project should be concise, descriptive and to the point. Writing proper commits helps define a clear project history and makes it easier to browse the source and pinpoint issues. Although this might seem trivial, a pull request with improperly formatted commits will not be accepted. An overview of good commit practices can be found in [this](https://cbea.ms/git-commit/) article. In a nutshell, a good commit has:
#### one conceptual change with a subject line that reflects it
The subject line of the commit is what you specify when doing `git commit -m "<subject-line>"`. When making commit, make sure that you create it for one conceptual change. E.g. do not use a commit to dump all the changes you have locally, but split your changes into commits that conceptually make sense and use the subject line to refelct that. Some examples:
**Bad:**
Commit message: `Document MovementAIComponent and add Avant Gardens Mech Scripts and fix Entity.cpp bug causing infinite loops`
Changed files:
- MovementAIComponent.cpp
- AgMechScript.cpp
- Entity.cpp
**Good:**
Commit message: `Document MovementAIComponent`
Changed files:
- MovementAIComponent.cpp
Commit message: `Add Avant Gardens Mech Scripts`
Changed files:
- AgMechScript.cpp
Commit message: `Fix Entity.cpp bug causing infinite loops`
Changed files:
- Entity.cpp
Not only does this logically make more sense, it'll make it easier to revert a conceptual change once something wrong with it. If you commit using the bad example but your bugfix turned out to introduce an even worse bug, all your changes have to be reverted, even though your other changes might not be broken. Splitting your commits into conceptually unique commits makes it easier to find and revert issues.
#### an imperative subject line
In the subject line it's also important to have an imperative writing style that covers the contents of your commit so that it easily reflects what it'll do when applied. We pick an imperative writing style so that all commits have equal tonality. An easy check for this is placing `When applied, this commit will ...` in front of your commit message and checking if that makes sense. Some examples:
**Bad:**
```
Nice commit :) -> "When applied, this commit will nice commit :)"
```
**Bad:**
```
fixed bug -> "When applied, this commit will fixed bug"
```
**Good:**
```
Fix Entity.cpp bug causing infinite loop -> "When applied, this commit will fix Entity.cpp bug causing infinite loop"
```
**Good:**
```
Add Avant Gardens mech scripts -> "When applied, this commit will add Avant Gardens mech scripts"
```
#### a subject line and a body
A good commit has a subject line that summarizes the change and a body that further describes the context required to understand the change. In this body you don't have to explain *what* the change was, as the code should reflect that, but *why* a change was made. Some examples:
**Bad:**
```
Add Avant Gardens mech scripts
Added the Avant Gardens mech scripts by creaing a new file called
AgMechScripts.cpp and then adding the proper event handlers to that
to send events to the client regarding changes of the mech.
```
**Good:**
```
Add Avant Gardens mech scripts
Added the Avant Gardens mech scripts as they were previously not
added, which produced InvalidScript errors.
```
## Development Resources
Check out a compiled list of development resources and tools [here](https://lu-dev.net/).
Please use [.editorconfig](https://editorconfig.org/#pre-installed) with your preferred IDE.
And run:
```bash
git config blame.ignoreRevsFile .git-blame-ignore-revs
```
to ignore the gitblame of mass formatting commits
## Coding Style
This project has gone through multiple iterations of coding style. In the code you'll find a number of different coding styles in use. What follows is the preferred style for this project.
### General
Use 4 spaces instead of the tab character.
**Never** use spaces instead of tabs. 1 Tab = 4 space character's width by default.
Use typically trailing braces everywhere (if, else, functions, structures, typedefs, class definitions, etc.)
@@ -77,7 +163,7 @@ if (x) {
}
```
Instead of
Instead of
```cpp
if ( x ) {

51
Dockerfile Normal file
View File

@@ -0,0 +1,51 @@
FROM gcc:12 as build
WORKDIR /app
RUN set -ex; \
apt-get update; \
apt-get install -y cmake
COPY . /app/
COPY --chmod=0500 ./build.sh /app/
RUN sed -i 's/MARIADB_CONNECTOR_COMPILE_JOBS__=.*/MARIADB_CONNECTOR_COMPILE_JOBS__=2/' /app/CMakeVariables.txt
RUN ./build.sh
FROM debian:12 as runtime
WORKDIR /app
RUN --mount=type=cache,id=build-apt-cache,target=/var/cache/apt \
apt update && \
apt install -y libssl3 libcurl4 && \
rm -rf /var/lib/apt/lists/*
# Grab libraries and load them
COPY --from=build /app/build/mariadbcpp/src/mariadb_connector_cpp-build/libmariadbcpp.so /usr/local/lib/
COPY --from=build /app/build/mariadbcpp/src/mariadb_connector_cpp-build/libmariadb/libmariadb/libmariadb.so.3 /usr/local/lib
RUN ldconfig
# Server bins
COPY --from=build /app/build/*Server /app/
# Necessary suplimentary files
COPY --from=build /app/build/*.ini /app/configs/
COPY --from=build /app/build/vanity/*.* /app/vanity/*
COPY --from=build /app/build/navmeshes /app/navmeshes
COPY --from=build /app/build/migrations /app/migrations
COPY --from=build /app/build/*.dcf /app/
# backup of config and vanity files to copy to the host incase
# of a mount clobbering the copy from above
COPY --from=build /app/build/*.ini /app/default-configs/
COPY --from=build /app/build/vanity/*.* /app/default-vanity/*
# needed as the container runs with the root user
# and therefore sudo doesn't exist
ENV USE_SUDO_AUTH=0
ENV DLU_CONFIG_DIR=/app/configs/
COPY --chmod=0500 ./entrypoint.sh /app/
ENTRYPOINT [ "/app/entrypoint.sh" ]

656
README.md
View File

@@ -18,162 +18,196 @@ Darkflame Universe is licensed under AGPLv3, please read [LICENSE](LICENSE). Som
Throughout the entire build and setup process a level of familiarity with the command line and preferably a Unix-like development environment is greatly advantageous.
### Hosting a server
We do not recommend hosting public servers. DLU is intended for small scale deployment, for example within a group of friends. It has not been tested for large scale deployment which comes with additional security risks.
We do not recommend hosting public servers. Darkflame Universe is intended for small scale deployment, for example within a group of friends. It has not been tested for large scale deployment which comes with additional security risks.
### Supply of resource files
Darkflame Universe is a server emulator and does not distribute any LEGO® Universe files. A separate game client is required to setup this server emulator and play the game, which we cannot supply. Users are strongly suggested to refer to the safe checksums listed in the resources tab below when checking if a client will work.
Darkflame Universe is a server emulator and does not distribute any LEGO® Universe files. A separate game client is required to setup this server emulator and play the game, which we cannot supply. Users are strongly suggested to refer to the safe checksums listed [here](#verifying-your-client-files) to see if a client will work.
## Build
Development of the latest iteration of Darkflame Universe has been done primarily in a Unix-like environment and is where it has been tested and designed for deployment. It is therefore highly recommended that Darkflame Universe be built and deployed using a Unix-like environment for the most streamlined experience.
## Step by step walkthrough for a single-player server
If you would like a setup for a single player server only on a Windows machine, use the [Native Windows Setup Guide by HailStorm](https://gist.github.com/HailStorm32/169df65a47a104199b5cc57d10fa57de) and skip this README.
### Prerequisites
**Clone the repository**
## Steps to setup server
* [Clone this repository](#clone-the-repository)
* [Install dependencies](#install-dependencies)
* [Database setup](#database-setup)
* [Build the server](#build-the-server)
* [Configuring your server](#configuring-your-server)
* [Required Configuration](#required-configuration)
* [Optional Configuration](#optional-configuration)
* [Verify your setup](#verify-your-setup)
* [Running the server](#running-the-server)
* [User Guide](#user-guide)
* [Docker](#docker)
## Clone the repository
If you are on Windows, you will need to download and install git from [here](https://git-scm.com/download/win)
Then run the following command
```bash
git clone --recursive https://github.com/DarkflameUniverse/DarkflameServer
```
**Python**
## Install dependencies
Some tools utilized to streamline the setup process require Python 3, make sure you have it installed.
### Windows packages
Ensure that you have either the [MSVC C++ compiler](https://visualstudio.microsoft.com/vs/features/cplusplus/) (recommended) or the [Clang compiler](https://github.com/llvm/llvm-project/releases/) installed.
You'll also need to download and install [CMake](https://cmake.org/download/) (version <font size="4">**CMake version 3.18**</font> or later!).
**Choosing the right version for your client**
DLU clients identify themselves using a higher version number than the regular live clients out there.
This was done make sure that older and incomplete clients wouldn't produce false positive bug reports for us, and because we made bug fixes and new content for the client.
If you're using a DLU client, then you don't need to change anything. But if you're using any other client, you'll have to go into the "CMakeVariables.txt" file and change it to match your client's version. (likely 171022)
### Linux builds
Make sure packages like `gcc`, `cmake`, and `zlib` are installed. Depending on the distribution, these packages might already be installed.
**Build the repository**
### MacOS packages
Ensure you have [brew](https://brew.sh) installed.
You will need to install the following packages
```bash
# Create the build directory, preserving it if it already exists
mkdir -p build
cd build
# Run CMake to generate make files
cmake ..
# Run make to build the project. To build utilizing multiple cores, append `-j` and the amount of cores to utilize, for example `make -j8`
make
brew install cmake gcc mariadb openssl zlib
```
### MacOS builds
### Linux packages
Make sure packages like `gcc`, and `zlib` are installed. Depending on the distribution, these packages might already be installed. Note that on systems like Ubuntu, you will need the `zlib1g-dev` package so that the header files are available. `libssl-dev` will also be required as well as `openssl`. You will also need a MySQL database solution to use. We recommend using `mariadb-server`.
**Download precompiled MySQL connector**
```bash
# Install required tools
brew install boost mysql-connector-c++
# Symlinks for finding the required modules
sudo ln -s /usr/local/mysql-connector-c++/lib64/libmysqlcppconn.dylib /usr/local/mysql-connector-c++/lib64/libmysql.dylib
sudo ln -s /usr/local/mysql-connector-c++/lib64/libcrypto.1.1.dylib /usr/local/mysql/lib/libcrypto.1.1.dylib
```
Then follow the Linux build steps (gcc is not required), but before running `make`, run the following to make sure all the libs are available in the build folder:
For Ubuntu, you would run the following commands. On other systems, the package install command will differ.
```bash
sudo ln -s /usr/local/mysql-connector-c++/lib64/libssl.1.1.dylib /path/to/build/folder/libssl.1.1.dylib
sudo ln -s /usr/local/mysql-connector-c++/lib64/libcrypto.1.1.dylib /path/to/build/folder/libcrypto.1.1.dylib
sudo apt update && sudo apt upgrade
# Install packages
sudo apt install build-essential gcc zlib1g-dev libssl-dev openssl mariadb-server cmake
```
### Windows builds (native)
Ensure that you have either the [MSVC](https://visualstudio.microsoft.com/vs/) or the [Clang](https://github.com/llvm/llvm-project/releases/) (recommended) compiler installed. You will also need to install [CMake](https://cmake.org/download/).
**Build the repository**
```batch
:: Create the build directory
mkdir build
cd build
:: Run CMake to generate make files
cmake ..
:: Run CMake with build flag to build
cmake --build .
```
### Windows builds (WSL)
This section will go through how to install [WSL](https://docs.microsoft.com/en-us/windows/wsl/install) and building in a Linux environment under Windows. WSL requires Windows 10 version 2004 and higher (Build 19041 and higher) or Windows 11.
**Open the Command Prompt application with Administrator permissions and run the following:**
#### Required CMake version
This project uses <font size="4">**CMake version 3.18**</font> or higher and as such you will need to ensure you have this version installed.
You can check your CMake version by using the following command in a terminal.
```bash
# Installing Windows Subsystem for Linux
wsl --install
cmake --version
```
**Open the Ubuntu application and run the following:**
```bash
# Make sure the install is up to date
apt update && apt upgrade
If you are going to be using an Ubuntu environment to run the server, you may need to get a more recent version of `cmake` than the packages available may provide.
# Make sure the gcc, cmake, and build-essentials are installed
sudo apt install gcc
The general approach to do so would be to obtain a copy of the signing key and then add the CMake repository to your apt.
You can do so with the following commands.
[Source of the below commands](https://askubuntu.com/questions/355565/how-do-i-install-the-latest-version-of-cmake-from-the-command-line)
```bash
# Remove the old version of CMake
sudo apt purge --auto-remove cmake
# Prepare for installation
sudo apt update && sudo apt install -y software-properties-common lsb-release && sudo apt clean all
# Obtain a copy of the signing key
wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | sudo tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null
# Add the repository to your sources list.
sudo apt-add-repository "deb https://apt.kitware.com/ubuntu/ $(lsb_release -cs) main"
# Next you'll want to ensure that Kitware's keyring stays up to date
sudo apt update
sudo apt install kitware-archive-keyring
sudo rm /etc/apt/trusted.gpg.d/kitware.gpg
# If sudo apt update above returned an error, copy the public key at the end of the error message and run the following command
# if the error message was "The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 6AF7F09730B3F0A4"
# then the below command would be "sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 6AF7F09730B3F0A4"
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys <TheCopiedPublicKey>
# Finally update and install
sudo apt update
sudo apt install cmake
sudo apt install build-essentials
```
[**Follow the Linux instructions**](#linux-builds)
## Database setup
First you'll need to start MariaDB.
## Setting up the environment
For Windows the service is always running by default.
### Database
Darkflame Universe utilizes a MySQL/MariaDB database for account and character information.
Initial setup can vary drastically based on which operating system or distribution you are running; there are instructions out there for most setups, follow those and come back here when you have a database up and running.
* Create a database for Darkflame Universe to use
* Run each SQL file in the order at which they appear [here](migrations/dlu/) on the database
### Resources
**LEGO® Universe 1.10.64**
This repository does not distribute any LEGO® Universe files. A full install of LEGO® Universe version 1.10.64 (latest) is required to finish setting up Darkflame Universe.
Known good SHA256 checksums of the client:
- `8f6c7e84eca3bab93232132a88c4ae6f8367227d7eafeaa0ef9c40e86c14edf5` (packed client, rar compressed)
- `c1531bf9401426042e8bab2de04ba1b723042dc01d9907c2635033d417de9e05` (packed client, includes extra locales, rar compressed)
- `0d862f71eedcadc4494c4358261669721b40b2131101cbd6ef476c5a6ec6775b` (unpacked client, includes extra locales, rar compressed)
Known good *SHA1* checksum of the DLU client:
- `91498e09b83ce69f46baf9e521d48f23fe502985` (packed client, zip compressed)
How to generate a SHA256 checksum:
For MacOS, run the following command
```bash
# Replace <file> with the file path to the client
# If on Linux or MacOS
shasum -a 256 <file>
# If on Windows
certutil -hashfile <file> SHA256
brew services start mariadb
```
**Unpacking the client**
* Clone lcdr's utilities repository [here](https://github.com/lcdr/utils)
* Use `pkextractor.pyw` to unpack the client files if they are not already unpacked
For Linux, run the following command
```bash
sudo systemctl start mysql
# If systemctl is not a known command on your distribution, try the following instead
sudo service mysql start
```
**Setup resource directory**
* In the `build` directory create a `res` directory if it does not already exist.
* Copy over or create symlinks from `macros`, `BrickModels`, `chatplus_en_us.txt`, and `maps` in your client `res` directory to the server `build/res` directory
* Unzip the navmeshes [here](./resources/navmeshes.zip) and place them in `build/res/maps/navmeshes`
<font size="4">**You will need to run this command every time you restart your environment**</font>
**Setup locale**
* In the `build` directory create a `locale` directory if it does not already exist
* Copy over or create symlinks from `locale.xml` in your client `locale` directory to the `build/locale` directory
If you are using Linux and `systemctl` and want the MariaDB instance to start on startup, run the following command
```bash
sudo systemctl enable --now mysql
```
**Client database**
* Use `fdb_to_sqlite.py` in lcdr's utilities on `res/cdclient.fdb` in the unpacked client to convert the client database to `cdclient.sqlite`
* Move and rename `cdclient.sqlite` into `build/res/CDServer.sqlite`
* Run each SQL file in the order at which they appear [here](migrations/cdserver/) on the SQLite database
Once MariaDB is started, you'll need to create a user and an empty database for Darkflame Universe to use.
**Configuration**
First, login to the MariaDB instance.
After the server has been built there should be four `ini` files in the build director: `authconfig.ini`, `chatconfig.ini`, `masterconfig.ini`, and `worldconfig.ini`. Go through them and fill in the database credentials and configure other settings if necessary.
To do this on Ubuntu/Linux, MacOS, or another Unix like operating system, run the following command in a terminal
```bash
# Logs you into the MariaDB instance as root
sudo mysql
```
**Verify**
For Windows, run the following command in the `Command Prompt (MariaDB xx.xx)` terminal
```bash
# Logs you into the mysql instance
mysql -u root -p
# You will then be prompted for the password you set for root during installation of MariaDB
```
Now that you are logged in, run the following commands.
```bash
# Creates a user for this computer which uses a password and grant said user all privileges.
# Change mydarkflameuser to a custom username and password to a custom password.
GRANT ALL ON *.* TO 'mydarkflameuser'@'localhost' IDENTIFIED BY 'password' WITH GRANT OPTION;
FLUSH PRIVILEGES;
# Then create a database for Darkflame Universe to use.
CREATE DATABASE darkflame;
```
## Build the server
You can either run `build.sh` when in the root folder of the repository:
```bash
./build.sh
```
Or manually run the commands used in [build.sh](build.sh).
If you would like to build the server faster, append `-j<number>` where number is the number of simultaneous compile jobs to run at once. It is recommended that you have this number always be 1 less than your core count to prevent slowdowns. The command would look like this if you would build with 4 jobs at once:
```bash
./build.sh -j4
```
### Notes
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 using a Darkflame Universe client, ensure `client_net_version` in `build/sharedconfig.ini` is changed to 171023.
## Configuring your server
This server has a few steps that need to be taken to configure the server for your use case.
### Required Configuration
Darkflame Universe can run with either a packed or an unpacked client.
Navigate to `build/sharedconfig.ini` and fill in the following fields:
* `mysql_host` (This is the IP address or hostname of your MariaDB server. This is highly likely `localhost`)
* If you setup your MariaDB instance on a port other than 3306, which can be done on a Windows install, you will need to make this value `tcp://localhost:portNum` where portNum is replaced with the port you chose to run MariaDB on.
* `mysql_database` (This is the database you created for the server)
* `mysql_username` (This is the user you created for the server)
* `mysql_password` (This is the password for the user you created for the server)
* `client_location` (This is the location of the client files. This should be the folder path of a packed or unpacked client)
* Ideally the path to the client should not contain any spaces.
### Optional Configuration
* After the server has been built there should be five `ini` files in the build directory: `sharedconfig.ini`, `authconfig.ini`, `chatconfig.ini`, `masterconfig.ini`, and `worldconfig.ini`.
* `authconfig.ini` contains an option to enable or disable play keys on your server. Do not change the default port for auth.
* `chatconfig.ini` contains a port option.
* `masterconfig.ini` contains options related to permissions you want to run your servers with.
* `sharedconfig.ini` contains several options that are shared across all servers
* `worldconfig.ini` contains several options to turn on QOL improvements should you want them. If you would like the most vanilla experience possible, you will need to turn some of these settings off.
## Verify your setup
Your build directory should now look like this:
* AuthServer
* ChatServer
@@ -182,228 +216,232 @@ Your build directory should now look like this:
* authconfig.ini
* chatconfig.ini
* masterconfig.ini
* sharedconfig.ini
* worldconfig.ini
* **locale/**
* locale.xml
* **res/**
* CDServer.sqlite
* chatplus_en_us.txt
* **macros/**
* ...
* **BrickModels/**
* ...
* **maps/**
* **navmeshes/**
* ...
* ...
* ...
## Running the server
If everything has been configured correctly you should now be able to run the `MasterServer` binary. Darkflame Universe utilizes port numbers under 1024, so under Linux you either have to give the binary network permissions or run it under sudo.
If everything has been configured correctly you should now be able to run the `MasterServer` binary which is located in the `build` directory. Darkflame Universe utilizes port numbers under 1024, so under Linux you either have to give the `AuthServer` binary network permissions or run it under sudo.
To give `AuthServer` network permissions and not require sudo, run the following command
```bash
sudo setcap 'cap_net_bind_service=+ep' AuthServer
```
and then go to `build/masterconfig.ini` and change `use_sudo_auth` to 0.
### Linux Service
If you are running this on a linux based system, it will use your terminal to run the program interactively, preventing you using it for other tasks and requiring it to be open to run the server.
_Note: You could use screen or tmux instead for virtual terminals_
To run the server non-interactively, we can use a systemctl service by copying the following file:
```shell
cp ./systemd.example /etc/systemd/system/darkflame.service
```
Make sure to edit the file in `/etc/systemd/system/darkflame.service` and change the:
- `User` and `Group` to the user that runs the darkflame server.
- `ExecPath` to the full file path of the server executable.
To register, enable and start the service use the following commands:
- Reload the systemd manager configuration to make it aware of the new service file:
```shell
systemctl daemon-reload
```
- Start the service:
```shell
systemctl start darkflame.service
```
- Enable OR disable the service to start on boot using:
```shell
systemctl enable darkflame.service
systemctl disable darkflame.service
```
- Verify that the service is running without errors:
```shell
systemctl status darkflame.service
```
- You can also restart, stop, or check the logs of the service using journalctl
```shell
systemctl restart darkflame.service
systemctl stop darkflame.service
journalctl -xeu darkflame.service
```
### First admin user
Run `MasterServer -a` to get prompted to create an admin account. This method is only intended for the system administrator as a means to get started, do NOT use this method to create accounts for other users!
### Account Manager
### Account management tool (Nexus Dashboard)
**If you are just using this server for yourself, you can skip setting up Nexus Dashboard**
Follow the instructions [here](https://github.com/DarkflameUniverse/AccountManager) to setup the DLU account management Python web application. This is the intended way for users to create accounts.
Follow the instructions [here](https://github.com/DarkflameUniverse/NexusDashboard) to setup the DLU Nexus Dashboard web application. This is the intended way for users to create accounts and the intended way for moderators to approve names/pets/properties and do other moderation actions.
### Admin levels
The admin level, or Game Master level (hereafter referred to as gmlevel), is specified in the `accounts.gm_level` column in the MySQL database. Normal players should have this set to `0`, which comes with no special privileges. The system administrator will have this set to `9`, which comes will all privileges. gmlevel `8` should be used to give a player a majority of privileges without the safety critical once.
The admin level, or game master level, is specified in the `accounts.gm_level` column in the MySQL database. Normal players should have this set to `0`, which comes with no special privileges. The system administrator will have this set to `9`, which comes will all privileges. Admin level `8` should be used to give a player a majority of privileges without the safety critical once.
While a character has a gmlevel of anything but `0`, some gameplay behavior will change. When testing gameplay, you should always use a character with a gmlevel of `0`.
While a character has a gmlevel of anything but 0, some gameplay behavior will change. When testing gameplay, you should always use a character with a gmlevel of 0.
# User guide
Some changes to the client `boot.cfg` file are needed to play on your server.
## User guide
A few modifications have to be made to the client.
### Client configuration
## Allowing a user to connect to your server
To connect to a server follow these steps:
* In the client directory, locate `boot.cfg`
* Open it in a text editor and locate where it says `AUTHSERVERIP=0:`
* Replace the contents after to `:` and the following `,` with what you configured as the server's public facing IP. For example `AUTHSERVERIP=0:localhost` for locally hosted servers
* Next locate the line `UGCUSE3DSERVICES=7:`
* Ensure the number after the 7 is a `0`
* Launch `legouniverse.exe`, through `wine` if on a Unix-like operating system
* Note that if you are on WSL2, you will need to configure the public IP in the server and client to be the IP of the WSL2 instance and not localhost, which can be found by running `ifconfig` in the terminal. Windows defaults to WSL1, so this will not apply to most users.
### Survival
## Updating your server
To update your server to the latest version navigate to your cloned directory
```bash
cd path/to/DarkflameServer
```
Run the following commands to update to the latest changes
```bash
git pull
git submodule update --init --recursive
```
Now follow the [build](#build-the-server) section for your system and your server is up to date.
The client script for the survival minigame has a bug in it which can cause the minigame to not load. To fix this, follow these instructions:
* Open `res/scripts/ai/minigame/survival/l_zone_survival_client.lua`
* Navigate to line `617`
* Change `PlayerReady(self)` to `onPlayerReady(self)`
* Save the file, overriding readonly mode if required
## In-game commands
* A list of all in-game commands can be found [here](./docs/Commands.md).
### Brick-By-Brick building
## Verifying your client files
Brick-By-Brick building requires `PATCHSERVERIP=0:` in the `boot.cfg` to point to a HTTP server which always returns `HTTP 404 - Not Found` for all requests. This can be achieved by pointing it to `localhost` while having `sudo python -m http.server 80` running in the background.
### LEGO® Universe 1.10.64
To verify that you are indeed using a LEGO® Universe 1.10.64 client, make sure you have the full client compressed **in a rar file** and run the following command.
```bash
# Replace <file> with the file path to the zipped client
### In-game commands
Here is a summary of the commands available in-game. All commands are prefixed by `/` and typed in the in-game chat window. Some commands requires admin privileges. Operands within `<>` are required, operands within `()` are not. For the full list of in-game commands, please checkout [the source file](./dGame/dUtilities/SlashCommandHandler.cpp).
# If on Linux or MacOS
shasum -a 256 <file>
<table>
<thead>
<th>
Command
</th>
<th>
Usage
</th>
<th>
Description
</th>
<th>
Admin Level Requirement
</th>
</thead>
<tbody>
<tr>
<td>
info
</td>
<td>
/info
</td>
<td>
Displays server info to the user, including where to find the server's source code.
</td>
<td>
</td>
</tr>
<tr>
<td>
credits
</td>
<td>
/credits
</td>
<td>
Displays the names of the people behind Darkflame Universe.
</td>
<td>
</td>
</tr>
<tr>
<td>
instance-info
</td>
<td>
/instance-info
</td>
<td>
Displays in the chat the current zone, clone, and instance id.
</td>
<td>
</td>
</tr>
<tr>
<td>
gmlevel
</td>
<td>
/gmlevel &#60;level&#62;
</td>
<td>
Within the authorized range of levels for the current account, changes the character's game master level to the specified value. This is required to use certain commands.
</td>
<td>
</td>
</tr>
<tr>
<td>
testmap
</td>
<td>
/testmap &#60;zone&#62; (clone-id)
</td>
<td>
Transfers you to the given zone by id and clone id.
</td>
<td>
1
</td>
</tr>
<tr>
<td>
ban
</td>
<td>
/ban &#60;username&#62;
</td>
<td>
Bans a user from the server.
</td>
<td>
4
</td>
</tr>
<tr>
<td>
gmadditem
</td>
<td>
/gmadditem &#60;id&#62; (count)
</td>
<td>
Adds the given item to your inventory by id.
</td>
<td>
8
</td>
</tr>
<tr>
<td>
spawn
</td>
<td>
/spawn &#60;id&#62;
</td>
<td>
Spawns an object at your location by id.
</td>
<td>
8
</td>
</tr>
<tr>
<td>
metrics
</td>
<td>
/metrics
</td>
<td>
Prints some information about the server's performance.
</td>
<td>
8
</td>
</tr>
</tbody>
</table>
# If on Windows using the Command Prompt
certutil -hashfile <file> SHA256
```
## Credits
### Contributors to DLUv3
* DarwinAnim8or
* Wincent01
* Mick
* averysumner
* Jon002
* Jonny
* Xiphoseer
Below are known good SHA256 checksums of the client:
* `8f6c7e84eca3bab93232132a88c4ae6f8367227d7eafeaa0ef9c40e86c14edf5` (packed client, rar compressed)
* `c1531bf9401426042e8bab2de04ba1b723042dc01d9907c2635033d417de9e05` (packed client, includes extra locales, rar compressed)
* `0d862f71eedcadc4494c4358261669721b40b2131101cbd6ef476c5a6ec6775b` (unpacked client, includes extra locales, rar compressed)
### Research and tools
* lcdr
If the returned hash matches one of the lines above then you can continue with setting up the server. If you are using a fully downloaded and complete client from live, then it will work, but the hash above may not match. Otherwise you must obtain a full install of LEGO® Universe 1.10.64.
You must also make absolutely sure your LEGO Universe client is not in a Windows OneDrive. DLU is not and will not support a client being stored in a OneDrive, so ensure you have moved the client outside of that location.
### Community management
* Neal
### Darkflame Universe Client
Darkflame Universe clients identify themselves using a higher version number than the regular live clients out there.
This was done make sure that older and incomplete clients wouldn't produce false positive bug reports for us, and because we made bug fixes and new content for the client.
### Former contributors
To verify that you are indeed using a Darkflame Universe client, make sure you have the full client compressed **in a zip file** and run the following command.
```bash
# Replace <file> with the file path to the zipped client
# If on Linux or MacOS
shasum -a 1 <file>
# If on Windows using the Command Prompt
certutil -hashfile <file> SHA1
```
Known good *SHA1* checksum of the Darkflame Universe client:
- `91498e09b83ce69f46baf9e521d48f23fe502985` (packed client, zip compressed)
# Docker
The Darkflame Server is automatically built and published as a Docker Container / [OCI](https://opencontainers.org/) Image to the GitHub Container Registry at:
[`ghcr.io/darkflameuniverse/darkflameserver`](https://github.com/DarkflameUniverse/DarkflameServer/pkgs/container/darkflameserver).
## Compose
You can use the `docker-compose` tool to [setup a MariaDB database](#database-setup), run the Darkflame Server and manage it with [Nexus Dashboard](https://github.com/DarkflameUniverse/NexusDashboard) all
at once. For that:
- [Install Docker Desktop](https://docs.docker.com/get-docker/)
- Open the directory that contains your LU Client
- If the `legouniverse.exe` is in a subfolder called `client`, you're good to go. There may also be a folder `versions`.
- Otherwise, create a new `client` folder and move the exe and everything else (e.g. `res` and `locale`) in there. This is necessary to work around a bug in the client that will prevent that you to log back in after getting disconnected.
- Download the [docker-compose.yml](docker-compose.yml) file and place it next to `client`.
- Download the [.env.example](.env.example) file and place it next to `client` with the file name `.env`
- You may get warnings that this name starts with a dot, acknowledge those, this is intentional. Depending on your operating system, you may need to activate showing hidden files (e.g. Ctrl-H in Gnome on Linux) and/or file extensions ("File name extensions" in the "View" tab on Windows).
- Update the `ACCOUNT_MANAGER_SECRET` and `MARIADB_PASSWORD` with strong random passwords.
- Use a password generator like <https://keygen.io>
- Avoid `:` and `@` characters
- Once the database user is created, changing the password will not update it, so the server will just fail to connect.
- Set `EXTERNAL_IP` to your LAN IP or public IP if you want to host the game for friends & family
- Open a terminal in the folder with the `docker-compose.yml` and `client`
- Run `docker compose up -d`
- This might require `sudo` on Linux, and a recent version of [docker compose](https://docs.docker.com/compose/install/)
- Run `docker exec -it dlu-darkflameserver-1 /app/MasterServer -a` and follow the instructions to create the initial admin account
- Open <http://localhost:8000> to access Nexus Dashboard with the admin account to create normal users
- Set `AUTHSERVERIP=0:localhost` in `client/boot.cfg`
- Replace `localhost` with the value of `EXTERNAL_IP` if you changed that earlier.
- Also make sure `UGCUSE3DSERVICES=7:` is set to `0`
- Launch `legouniverse.exe`
## Standalone
This assumes that you have a database deployed to your host or in another docker container.
A basic deployment of this contianer would look like:
```sh
# example docker contianer deployment
docker run -it \
-v /path/to/configs/:/app/configs \
-v /path/to/logs/:/app/logs \
-v /path/to/dumps/:/app/dumps \
-v /path/to/res:/app/res:ro \
-v /path/to/resServer:/app/resServer \
-e DUMP_FOLDER=/app/dumps \
-p 1001:1001/udp \
-p 2005:2005/udp \
-p 3000-3300:3000-3300/udp \
ghcr.io/darkflameuniverse/darkflameserver:latest
```
You will need to replace the `/path/to/`'s to reflect the paths on your host.
Any config option in the `.ini`'s can be overridden with environmental variables: Ex: `log_to_console=1` from `shared_config.ini` would be overidden like `-e LOG_TO_CONSOLE=0`
# Development Documentation
This is a Work in Progress, but below are some quick links to documentaion for systems and structs in the server
[Networked message structs](https://lcdruniverse.org/lu_packets/lu_packets/index.html)
[General system documentation](https://docs.lu-dev.net/en/latest/index.html)
# Credits
## DLU Team
* [DarwinAnim8or](https://github.com/DarwinAnim8or)
* [Wincent01](https://github.com/Wincent01)
* [Mick](https://github.com/MickVermeulen)
* [averysumner](https://github.com/codeshaunted)
* [Jon002](https://github.com/jaller200)
* [Jonny](https://github.com/cuzitsjonny)
* [Aaron K.](https://github.com/aronwk-aaron)
### Research and Tools
* [lcdr](https://github.com/lcdr)
* [Xiphoseer](https://github.com/Xiphoseer)
### Community Management
* [Neal](https://github.com/NealSpellman)
### Logo
* Cole Peterson (BlasterBuilder)
## Active Contributors
* [EmosewaMC](https://github.com/EmosewaMC)
* [Jettford](https://github.com/Jettford)
## Former Contributors
* TheMachine
* Matthew
* Raine
* [Raine](https://github.com/uwainium)
* Bricknave
### Special thanks
## Special Thanks
* humanoid24
* pwjones1969
* BlasterBuilder for the logo
* ALL OF THE NETDEVIL AND LEGO TEAMS!
* [Simon](https://github.com/SimonNitzsche)
* [ALL OF THE NETDEVIL AND LEGO TEAMS!](https://www.mobygames.com/game/macintosh/lego-universe/credits)

51
SECURITY.md Normal file
View File

@@ -0,0 +1,51 @@
# Security Policy
## Supported Versions
At the moment, only the latest commit on the `main` branch will be supported for security vulnerabilities. Private server operators
should keep their instances up to date and forks should regularily rebase on `main`.
| Branch | Supported |
| ------- | ------------------ |
| `main` | :white_check_mark: |
## Reporting a Vulnerability
If you found a security vulnerability in DLU, please send a message to [darkflame-security@googlegroups.com][darkflame-security]. You should get a
reply within *72 hours* that we have received your report and a tentative [CVSS score](https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator).
We will do a preliminary analysis to confirm that the vulnerability is a plausible claim and decline the report otherwise.
If possible, please include
1. reproducible steps on how to trigger the vulnerability
2. a description on why you are convinced that it exists.
3. any information you may have on active exploitation of the vulnerability (zero-day).
## Security Advisories
The project will release advisories on resolved vulnerabilities at <https://github.com/DarkflameUniverse/DarkflameServer/security/advisories>
## Receiving Security Updates
We set up [darkflame-security-announce@googlegroups.com][darkflame-security-announce] for private server operators to receive updates on vulnerabilities
such as the release of [Security Advisories](#security-advisories) or early workarounds and recommendations to mitigate ongoing
vulnerabilities.
Unfortunately, we cannot guarantee that announcements will be sent for every vulnerability.
## Embargo
We propose a 90 day (approx. 3 months) embargo on security vulnerabilities. That is, we ask everyone not to disclose the vulnerabilty
publicly until either:
1. 90 days have passed from the time the first related email is sent to `darkflame-security@`
2. a security advisory related to the vulnerability has been published by the project.
If you fail to comply with this embargo, you might be exluded from [receiving security updates](#receiving-security-updates).
## Bug Bounty
Unfortunately we cannot provide bug bounties at this time.
[darkflame-security]: mailto:darkflame-security@googlegroups.com
[darkflame-security-announce]: https://groups.google.com/g/darkflame-security-announce

8
build.sh Normal file → Executable file
View File

@@ -1,3 +1,6 @@
# Error if any command fails
set -e
# Create the build directory, preserving it if it already exists
mkdir -p build
cd build
@@ -5,5 +8,6 @@ cd build
# Run cmake to generate make files
cmake ..
# Run make to build the project. To build utilizing multiple cores, append `-j` and the amount of cores to utilize, for example `make -j8`
make
# To build utilizing multiple cores, append `-j` and the amount of cores to utilize, for example `cmake --build . --config Release -j8'
cmake --build . --config Release $1

51
cmake/Utils.cmake Normal file
View File

@@ -0,0 +1,51 @@
# Parses a config file for a specific option and appends the new option if it does not exist
# If the new option does exist, this function will do nothing.
# file_name: The name of the file to parse
# old_option_name: The name of the option to find
# new_option_name: The name of the option to add
function(UpdateConfigOption file_name old_option_name new_option_name)
string(APPEND old_option_name "=")
string(APPEND new_option_name "=")
message(STATUS "Checking " ${file_name} " for " ${old_option_name} " and adding " ${new_option_name} " if it does not exist")
if(NOT EXISTS ${file_name})
message(STATUS ${file_name} " does not exist. Doing nothing")
return()
endif()
file(READ ${file_name} 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()
set(found_new_option -1)
set(found_old_option -1)
set(current_value -1)
foreach(line ${current_file_contents})
string(FIND ${line} ${old_option_name} old_option_in_file)
if(${old_option_in_file} EQUAL 0)
set(found_old_option 1)
set(current_value ${line})
endif()
string(FIND ${line} ${new_option_name} found_new_option_in_file)
if(${found_new_option_in_file} EQUAL 0)
set(found_new_option 1)
endif()
endforeach(line ${current_file_contents})
if(${found_old_option} EQUAL 1 AND NOT ${found_new_option} EQUAL 1)
string(REPLACE ${old_option_name} ${new_option_name} current_value ${current_value})
file(APPEND ${file_name} "\n" ${current_value})
endif()
endfunction()

View File

@@ -1,104 +1,119 @@
#include <iostream>
#include <string>
#include <ctime>
#include <csignal>
#include <chrono>
#include <thread>
//DLU Includes:
#include "dCommonVars.h"
#include "dServer.h"
#include "dLogger.h"
#include "Logger.h"
#include "Database.h"
#include "dConfig.h"
#include "Diagnostics.h"
#include "BinaryPathFinder.h"
//RakNet includes:
#include "RakNetDefines.h"
#include "MessageIdentifiers.h"
//Auth includes:
#include "AuthPackets.h"
#include "dMessageIdentifiers.h"
#include "eConnectionType.h"
#include "eServerMessageType.h"
#include "eAuthMessageType.h"
#include "Game.h"
#include "Server.h"
namespace Game {
dLogger* logger;
dServer* server;
dConfig* config;
Logger* logger = nullptr;
dServer* server = nullptr;
dConfig* config = nullptr;
Game::signal_t lastSignal = 0;
std::mt19937 randomEngine;
}
dLogger* SetupLogger();
void HandlePacket(Packet* packet);
int main(int argc, char** argv) {
constexpr uint32_t authFramerate = mediumFramerate;
constexpr uint32_t authFrameDelta = mediumFrameDelta;
Diagnostics::SetProcessName("Auth");
Diagnostics::SetProcessFileName(argv[0]);
Diagnostics::Initialize();
std::signal(SIGINT, Game::OnSignal);
std::signal(SIGTERM, Game::OnSignal);
Game::config = new dConfig("authconfig.ini");
//Create all the objects we need to run our service:
Game::logger = SetupLogger();
if (!Game::logger) return 0;
Game::logger->Log("AuthServer", "Starting Auth server...\n");
Game::logger->Log("AuthServer", "Version: %i.%i\n", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
Game::logger->Log("AuthServer", "Compiled on: %s\n", __TIMESTAMP__);
Server::SetupLogger("AuthServer");
if (!Game::logger) return EXIT_FAILURE;
//Read our config:
dConfig config("authconfig.ini");
Game::config = &config;
Game::logger->SetLogToConsole(bool(std::stoi(config.GetValue("log_to_console"))));
LOG("Starting Auth server...");
LOG("Version: %s", PROJECT_VERSION);
LOG("Compiled on: %s", __TIMESTAMP__);
//Connect to the MySQL Database
std::string mysql_host = config.GetValue("mysql_host");
std::string mysql_database = config.GetValue("mysql_database");
std::string mysql_username = config.GetValue("mysql_username");
std::string mysql_password = config.GetValue("mysql_password");
try {
Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password);
} catch (sql::SQLException& ex) {
Game::logger->Log("AuthServer", "Got an error while connecting to the database: %s\n", ex.what());
Database::Destroy();
try {
Database::Connect();
} catch (sql::SQLException& ex) {
LOG("Got an error while connecting to the database: %s", ex.what());
Database::Destroy("AuthServer");
delete Game::server;
delete Game::logger;
return 0;
}
return EXIT_FAILURE;
}
//Find out the master's IP:
std::string masterIP;
int masterPort = 1500;
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT ip, port FROM servers WHERE name='master';");
auto res = stmt->executeQuery();
while (res->next()) {
masterIP = res->getString(1).c_str();
masterPort = res->getInt(2);
}
uint32_t masterPort = 1500;
delete res;
delete stmt;
auto masterInfo = Database::Get()->GetMasterInfo();
if (masterInfo) {
masterIP = masterInfo->ip;
masterPort = masterInfo->port;
}
LOG("Master is at %s:%d", masterIP.c_str(), masterPort);
Game::randomEngine = std::mt19937(time(0));
//It's safe to pass 'localhost' here, as the IP is only used as the external IP.
int maxClients = 50;
int ourPort = 1001; //LU client is hardcoded to use this for auth port, so I'm making it the default.
if (config.GetValue("max_clients") != "") maxClients = std::stoi(config.GetValue("max_clients"));
if (config.GetValue("port") != "") ourPort = std::atoi(config.GetValue("port").c_str());
Game::server = new dServer(config.GetValue("external_ip"), ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Auth);
uint32_t maxClients = 999;
uint32_t ourPort = 1001; //LU client is hardcoded to use this for auth port, so I'm making it the default.
std::string ourIP = "localhost";
GeneralUtils::TryParse(Game::config->GetValue("max_clients"), maxClients);
GeneralUtils::TryParse(Game::config->GetValue("auth_server_port"), ourPort);
const auto externalIPString = Game::config->GetValue("external_ip");
if (!externalIPString.empty()) ourIP = externalIPString;
Game::server = new dServer(ourIP, ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Auth, Game::config, &Game::lastSignal);
//Run it until server gets a kill message from Master:
auto t = std::chrono::high_resolution_clock::now();
Packet* packet = nullptr;
int framesSinceLastFlush = 0;
int framesSinceMasterDisconnect = 0;
int framesSinceLastSQLPing = 0;
constexpr uint32_t logFlushTime = 30 * authFramerate; // 30 seconds in frames
constexpr uint32_t sqlPingTime = 10 * 60 * authFramerate; // 10 minutes in frames
uint32_t framesSinceLastFlush = 0;
uint32_t framesSinceMasterDisconnect = 0;
uint32_t framesSinceLastSQLPing = 0;
while (true) {
AuthPackets::LoadClaimCodes();
Game::logger->Flush(); // once immediately before main loop
while (!Game::ShouldShutdown()) {
//Check if we're still connected to master:
if (!Game::server->GetIsConnectedToMaster()) {
framesSinceMasterDisconnect++;
if (framesSinceMasterDisconnect >= 30)
if (framesSinceMasterDisconnect >= authFramerate) {
LOG("No connection to master!");
break; //Exit our loop, shut down.
}
else framesSinceMasterDisconnect = 0;
}
} else framesSinceMasterDisconnect = 0;
//In world we'd update our other systems here.
@@ -112,61 +127,50 @@ int main(int argc, char** argv) {
}
//Push our log every 30s:
if (framesSinceLastFlush >= 900) {
if (framesSinceLastFlush >= logFlushTime) {
Game::logger->Flush();
framesSinceLastFlush = 0;
} else framesSinceLastFlush++;
//Every 10 min we ping our sql server to keep it alive hopefully:
if (framesSinceLastSQLPing >= 40000) {
if (framesSinceLastSQLPing >= sqlPingTime) {
//Find out the master's IP for absolutely no reason:
std::string masterIP;
int masterPort;
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT ip, port FROM servers WHERE name='master';");
auto res = stmt->executeQuery();
while (res->next()) {
masterIP = res->getString(1).c_str();
masterPort = res->getInt(2);
uint32_t masterPort;
auto masterInfo = Database::Get()->GetMasterInfo();
if (masterInfo) {
masterIP = masterInfo->ip;
masterPort = masterInfo->port;
}
delete res;
delete stmt;
framesSinceLastSQLPing = 0;
}
else framesSinceLastSQLPing++;
} else framesSinceLastSQLPing++;
//Sleep our thread since auth can afford to.
t += std::chrono::milliseconds(mediumFramerate); //Auth can run at a lower "fps"
t += std::chrono::milliseconds(authFrameDelta); //Auth can run at a lower "fps"
std::this_thread::sleep_until(t);
}
LOG("Exited Main Loop! (signal %d)", Game::lastSignal);
//Delete our objects here:
Database::Destroy();
Database::Destroy("AuthServer");
delete Game::server;
delete Game::logger;
delete Game::config;
return 0;
}
dLogger * SetupLogger() {
std::string logPath = "./logs/AuthServer_" + std::to_string(time(nullptr)) + ".log";
bool logToConsole = false;
#ifdef _DEBUG
logToConsole = true;
#endif
return new dLogger(logPath, logToConsole);
return EXIT_SUCCESS;
}
void HandlePacket(Packet* packet) {
if (packet->length < 4) return;
if (packet->data[0] == ID_USER_PACKET_ENUM) {
if (packet->data[1] == SERVER) {
if (packet->data[3] == MSG_SERVER_VERSION_CONFIRM) {
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::SERVER) {
if (static_cast<eServerMessageType>(packet->data[3]) == eServerMessageType::VERSION_CONFIRM) {
AuthPackets::HandleHandshake(Game::server, packet);
}
} else if (packet->data[1] == AUTH) {
if (packet->data[3] == MSG_AUTH_LOGIN_REQUEST) {
} else if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::AUTH) {
if (static_cast<eAuthMessageType>(packet->data[3]) == eAuthMessageType::LOGIN_REQUEST) {
AuthPackets::HandleLoginRequest(Game::server, packet);
}
}

View File

@@ -0,0 +1,7 @@
add_executable(AuthServer "AuthServer.cpp")
target_link_libraries(AuthServer ${COMMON_LIBRARIES} dServer)
target_include_directories(AuthServer PRIVATE ${PROJECT_SOURCE_DIR}/dServer)
add_compile_definitions(AuthServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"")

View File

@@ -0,0 +1,4 @@
set(DCHATFILTER_SOURCES "dChatFilter.cpp")
add_library(dChatFilter STATIC ${DCHATFILTER_SOURCES})
target_link_libraries(dChatFilter dDatabase)

View File

@@ -8,9 +8,11 @@
#include <regex>
#include "dCommonVars.h"
#include "Logger.h"
#include "dConfig.h"
#include "Database.h"
#include "dLogger.h"
#include "Game.h"
#include "eGameMasterLevel.h"
using namespace dChatFilterDCF;
@@ -18,78 +20,84 @@ dChatFilter::dChatFilter(const std::string& filepath, bool dontGenerateDCF) {
m_DontGenerateDCF = dontGenerateDCF;
if (!BinaryIO::DoesFileExist(filepath + ".dcf") || m_DontGenerateDCF) {
ReadWordlistPlaintext(filepath + ".txt");
if (!m_DontGenerateDCF) ExportWordlistToDCF(filepath + ".dcf");
ReadWordlistPlaintext(filepath + ".txt", true);
if (!m_DontGenerateDCF) ExportWordlistToDCF(filepath + ".dcf", true);
} else if (!ReadWordlistDCF(filepath + ".dcf", true)) {
ReadWordlistPlaintext(filepath + ".txt", true);
ExportWordlistToDCF(filepath + ".dcf", true);
}
else {
ReadWordlistDCF(filepath + ".dcf");
if (BinaryIO::DoesFileExist("blacklist.dcf")) {
ReadWordlistDCF("blacklist.dcf", false);
}
//Read player names that are ok as well:
auto stmt = Database::CreatePreppedStmt("select name from charinfo;");
auto res = stmt->executeQuery();
while (res->next()) {
std::string line = res->getString(1).c_str();
std::transform(line.begin(), line.end(), line.begin(), ::tolower); //Transform to lowercase
m_Words.push_back(CalculateHash(line));
auto approvedNames = Database::Get()->GetApprovedCharacterNames();
for (auto& name : approvedNames) {
std::transform(name.begin(), name.end(), name.begin(), ::tolower); //Transform to lowercase
m_ApprovedWords.push_back(CalculateHash(name));
}
delete res;
delete stmt;
}
dChatFilter::~dChatFilter() {
m_Words.clear();
m_ApprovedWords.clear();
m_DeniedWords.clear();
}
void dChatFilter::ReadWordlistPlaintext(const std::string& filepath) {
void dChatFilter::ReadWordlistPlaintext(const std::string& filepath, bool whiteList) {
std::ifstream file(filepath);
if (file) {
std::string line;
while (std::getline(file, line)) {
line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
std::transform(line.begin(), line.end(), line.begin(), ::tolower); //Transform to lowercase
m_Words.push_back(CalculateHash(line));
if (whiteList) m_ApprovedWords.push_back(CalculateHash(line));
else m_DeniedWords.push_back(CalculateHash(line));
}
}
}
void dChatFilter::ReadWordlistDCF(const std::string& filepath) {
bool dChatFilter::ReadWordlistDCF(const std::string& filepath, bool whiteList) {
std::ifstream file(filepath, std::ios::binary);
if (file) {
fileHeader hdr;
BinaryIO::BinaryRead(file, hdr);
if (hdr.header != header) {
std::cout << "Wrong file header!" << std::endl;
file.close();
return;
return false;
}
if (hdr.formatVersion <= formatVersion) {
if (hdr.formatVersion == formatVersion) {
size_t wordsToRead = 0;
BinaryIO::BinaryRead(file, wordsToRead);
m_Words.reserve(wordsToRead);
if (whiteList) m_ApprovedWords.reserve(wordsToRead);
else m_DeniedWords.reserve(wordsToRead);
size_t word = 0;
for (size_t i = 0; i < wordsToRead; ++i) {
BinaryIO::BinaryRead(file, word);
m_Words.push_back(word);
if (whiteList) m_ApprovedWords.push_back(word);
else m_DeniedWords.push_back(word);
}
}
else {
std::cout << "Newer file or corrupt" << std::endl;
return true;
} else {
file.close();
return;
return false;
}
}
return false;
}
void dChatFilter::ExportWordlistToDCF(const std::string& filepath) {
std::ofstream file(filepath, std::ios::binary);
void dChatFilter::ExportWordlistToDCF(const std::string& filepath, bool whiteList) {
std::ofstream file(filepath, std::ios::binary | std::ios_base::out);
if (file) {
BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::header));
BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::formatVersion));
BinaryIO::BinaryWrite(file, size_t(m_Words.size()));
BinaryIO::BinaryWrite(file, size_t(whiteList ? m_ApprovedWords.size() : m_DeniedWords.size()));
for (size_t word : m_Words) {
for (size_t word : whiteList ? m_ApprovedWords : m_DeniedWords) {
BinaryIO::BinaryWrite(file, word);
}
@@ -97,31 +105,45 @@ void dChatFilter::ExportWordlistToDCF(const std::string& filepath) {
}
}
bool dChatFilter::IsSentenceOkay(const std::string& message, int gmLevel) {
if (gmLevel > GAME_MASTER_LEVEL_FORUM_MODERATOR) return true; //If anything but a forum mod, return true.
if (message.empty()) return true;
std::vector<std::pair<uint8_t, uint8_t>> dChatFilter::IsSentenceOkay(const std::string& message, eGameMasterLevel gmLevel, bool whiteList) {
if (gmLevel > eGameMasterLevel::FORUM_MODERATOR) return { }; //If anything but a forum mod, return true.
if (message.empty()) return { };
if (!whiteList && m_DeniedWords.empty()) return { { 0, message.length() } };
std::stringstream sMessage(message);
std::string segment;
std::regex reg("(!*|\\?*|\\;*|\\.*|\\,*)");
std::vector<std::pair<uint8_t, uint8_t>> listOfBadSegments = std::vector<std::pair<uint8_t, uint8_t>>();
uint32_t position = 0;
while (std::getline(sMessage, segment, ' ')) {
std::string originalSegment = segment;
std::transform(segment.begin(), segment.end(), segment.begin(), ::tolower); //Transform to lowercase
segment = std::regex_replace(segment, reg, "");
size_t hash = CalculateHash(segment);
if (std::find(m_UserUnapprovedWordCache.begin(), m_UserUnapprovedWordCache.end(), hash) != m_UserUnapprovedWordCache.end()) {
return false;
if (std::find(m_UserUnapprovedWordCache.begin(), m_UserUnapprovedWordCache.end(), hash) != m_UserUnapprovedWordCache.end() && whiteList) {
listOfBadSegments.emplace_back(position, originalSegment.length());
}
if (!IsInWordlist(hash)) {
if (std::find(m_ApprovedWords.begin(), m_ApprovedWords.end(), hash) == m_ApprovedWords.end() && whiteList) {
m_UserUnapprovedWordCache.push_back(hash);
return false;
listOfBadSegments.emplace_back(position, originalSegment.length());
}
if (std::find(m_DeniedWords.begin(), m_DeniedWords.end(), hash) != m_DeniedWords.end() && !whiteList) {
m_UserUnapprovedWordCache.push_back(hash);
listOfBadSegments.emplace_back(position, originalSegment.length());
}
position += originalSegment.length() + 1;
}
return true;
return listOfBadSegments;
}
size_t dChatFilter::CalculateHash(const std::string& word) {
@@ -131,7 +153,3 @@ size_t dChatFilter::CalculateHash(const std::string& word) {
return value;
}
bool dChatFilter::IsInWordlist(size_t word) {
return std::find(m_Words.begin(), m_Words.end(), word) != m_Words.end();
}

View File

@@ -4,9 +4,10 @@
#include "dCommonVars.h"
enum class eGameMasterLevel : uint8_t;
namespace dChatFilterDCF {
static const uint32_t header = ('D' + ('C' << 8) + ('F' << 16) + ('B' << 24));
static const uint32_t formatVersion = 1;
static const uint32_t formatVersion = 2;
struct fileHeader {
uint32_t header;
@@ -20,17 +21,17 @@ public:
dChatFilter(const std::string& filepath, bool dontGenerateDCF);
~dChatFilter();
void ReadWordlistPlaintext(const std::string & filepath);
void ReadWordlistDCF(const std::string & filepath);
void ExportWordlistToDCF(const std::string & filepath);
bool IsSentenceOkay(const std::string& message, int gmLevel);
void ReadWordlistPlaintext(const std::string& filepath, bool whiteList);
bool ReadWordlistDCF(const std::string& filepath, bool whiteList);
void ExportWordlistToDCF(const std::string& filepath, bool whiteList);
std::vector<std::pair<uint8_t, uint8_t>> IsSentenceOkay(const std::string& message, eGameMasterLevel gmLevel, bool whiteList = true);
private:
bool m_DontGenerateDCF;
std::vector<size_t> m_Words;
std::vector<size_t> m_DeniedWords;
std::vector<size_t> m_ApprovedWords;
std::vector<size_t> m_UserUnapprovedWordCache;
//Private functions:
size_t CalculateHash(const std::string& word);
bool IsInWordlist(size_t word);
};

View File

@@ -0,0 +1,14 @@
set(DCHATSERVER_SOURCES
"ChatIgnoreList.cpp"
"ChatPacketHandler.cpp"
"PlayerContainer.cpp"
)
add_executable(ChatServer "ChatServer.cpp")
add_library(dChatServer ${DCHATSERVER_SOURCES})
target_include_directories(dChatServer PRIVATE ${PROJECT_SOURCE_DIR}/dServer)
add_compile_definitions(ChatServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"")
target_link_libraries(dChatServer ${COMMON_LIBRARIES} dChatFilter)
target_link_libraries(ChatServer ${COMMON_LIBRARIES} dChatFilter dChatServer dServer)

View File

@@ -0,0 +1,171 @@
#include "ChatIgnoreList.h"
#include "PlayerContainer.h"
#include "eChatInternalMessageType.h"
#include "BitStreamUtils.h"
#include "Game.h"
#include "Logger.h"
#include "eObjectBits.h"
#include "Database.h"
// A note to future readers, The client handles all the actual ignoring logic:
// not allowing teams, rejecting DMs, friends requets etc.
// The only thing not auto-handled is instance activities force joining the team on the server.
void WriteOutgoingReplyHeader(RakNet::BitStream& bitStream, const LWOOBJID& receivingPlayer, const ChatIgnoreList::Response type) {
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receivingPlayer);
//portion that will get routed:
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, type);
}
void ChatIgnoreList::GetIgnoreList(Packet* packet) {
CINSTREAM_SKIP_HEADER;
LWOOBJID playerId;
inStream.Read(playerId);
auto& receiver = Game::playerContainer.GetPlayerDataMutable(playerId);
if (!receiver) {
LOG("Tried to get ignore list, but player %llu not found in container", playerId);
return;
}
if (!receiver.ignoredPlayers.empty()) {
LOG_DEBUG("Player %llu already has an ignore list, but is requesting it again.", playerId);
} else {
auto ignoreList = Database::Get()->GetIgnoreList(static_cast<uint32_t>(playerId));
if (ignoreList.empty()) {
LOG_DEBUG("Player %llu has no ignores", playerId);
return;
}
for (auto& ignoredPlayer : ignoreList) {
receiver.ignoredPlayers.emplace_back(ignoredPlayer.name, ignoredPlayer.id);
GeneralUtils::SetBit(receiver.ignoredPlayers.back().playerId, eObjectBits::CHARACTER);
GeneralUtils::SetBit(receiver.ignoredPlayers.back().playerId, eObjectBits::PERSISTENT);
}
}
CBITSTREAM;
WriteOutgoingReplyHeader(bitStream, receiver.playerID, ChatIgnoreList::Response::GET_IGNORE);
bitStream.Write<uint8_t>(false); // Probably is Is Free Trial, but we don't care about that
bitStream.Write<uint16_t>(0); // literally spacing due to struct alignment
bitStream.Write<uint16_t>(receiver.ignoredPlayers.size());
for (const auto& ignoredPlayer : receiver.ignoredPlayers) {
bitStream.Write(ignoredPlayer.playerId);
bitStream.Write(LUWString(ignoredPlayer.playerName, 36));
}
Game::server->Send(&bitStream, packet->systemAddress, false);
}
void ChatIgnoreList::AddIgnore(Packet* packet) {
CINSTREAM_SKIP_HEADER;
LWOOBJID playerId;
inStream.Read(playerId);
auto& receiver = Game::playerContainer.GetPlayerDataMutable(playerId);
if (!receiver) {
LOG("Tried to get ignore list, but player %llu not found in container", playerId);
return;
}
constexpr int32_t MAX_IGNORES = 32;
if (receiver.ignoredPlayers.size() > MAX_IGNORES) {
LOG_DEBUG("Player %llu has too many ignores", playerId);
return;
}
inStream.IgnoreBytes(4); // ignore some garbage zeros idk
LUWString toIgnoreName;
inStream.Read(toIgnoreName);
std::string toIgnoreStr = toIgnoreName.GetAsString();
CBITSTREAM;
WriteOutgoingReplyHeader(bitStream, receiver.playerID, ChatIgnoreList::Response::ADD_IGNORE);
// Check if the player exists
LWOOBJID ignoredPlayerId = LWOOBJID_EMPTY;
if (toIgnoreStr == receiver.playerName || toIgnoreStr.find("[GM]") == 0) {
LOG_DEBUG("Player %llu tried to ignore themselves", playerId);
bitStream.Write(ChatIgnoreList::AddResponse::GENERAL_ERROR);
} else if (std::count(receiver.ignoredPlayers.begin(), receiver.ignoredPlayers.end(), toIgnoreStr) > 0) {
LOG_DEBUG("Player %llu is already ignoring %s", playerId, toIgnoreStr.c_str());
bitStream.Write(ChatIgnoreList::AddResponse::ALREADY_IGNORED);
} else {
// Get the playerId falling back to query if not online
const auto& playerData = Game::playerContainer.GetPlayerData(toIgnoreStr);
if (!playerData) {
// Fall back to query
auto player = Database::Get()->GetCharacterInfo(toIgnoreStr);
if (!player || player->name != toIgnoreStr) {
LOG_DEBUG("Player %s not found", toIgnoreStr.c_str());
} else {
ignoredPlayerId = player->id;
}
} else {
ignoredPlayerId = playerData.playerID;
}
if (ignoredPlayerId != LWOOBJID_EMPTY) {
Database::Get()->AddIgnore(static_cast<uint32_t>(playerId), static_cast<uint32_t>(ignoredPlayerId));
GeneralUtils::SetBit(ignoredPlayerId, eObjectBits::CHARACTER);
GeneralUtils::SetBit(ignoredPlayerId, eObjectBits::PERSISTENT);
receiver.ignoredPlayers.emplace_back(toIgnoreStr, ignoredPlayerId);
LOG_DEBUG("Player %llu is ignoring %s", playerId, toIgnoreStr.c_str());
bitStream.Write(ChatIgnoreList::AddResponse::SUCCESS);
} else {
bitStream.Write(ChatIgnoreList::AddResponse::PLAYER_NOT_FOUND);
}
}
LUWString playerNameSend(toIgnoreStr, 33);
bitStream.Write(playerNameSend);
bitStream.Write(ignoredPlayerId);
Game::server->Send(&bitStream, packet->systemAddress, false);
}
void ChatIgnoreList::RemoveIgnore(Packet* packet) {
CINSTREAM_SKIP_HEADER;
LWOOBJID playerId;
inStream.Read(playerId);
auto& receiver = Game::playerContainer.GetPlayerDataMutable(playerId);
if (!receiver) {
LOG("Tried to get ignore list, but player %llu not found in container", playerId);
return;
}
inStream.IgnoreBytes(4); // ignore some garbage zeros idk
LUWString removedIgnoreName;
inStream.Read(removedIgnoreName);
std::string removedIgnoreStr = removedIgnoreName.GetAsString();
auto toRemove = std::remove(receiver.ignoredPlayers.begin(), receiver.ignoredPlayers.end(), removedIgnoreStr);
if (toRemove == receiver.ignoredPlayers.end()) {
LOG_DEBUG("Player %llu is not ignoring %s", playerId, removedIgnoreStr.c_str());
return;
}
Database::Get()->RemoveIgnore(static_cast<uint32_t>(playerId), static_cast<uint32_t>(toRemove->playerId));
receiver.ignoredPlayers.erase(toRemove, receiver.ignoredPlayers.end());
CBITSTREAM;
WriteOutgoingReplyHeader(bitStream, receiver.playerID, ChatIgnoreList::Response::REMOVE_IGNORE);
bitStream.Write<int8_t>(0);
LUWString playerNameSend(removedIgnoreStr, 33);
bitStream.Write(playerNameSend);
Game::server->Send(&bitStream, packet->systemAddress, false);
}

View File

@@ -0,0 +1,27 @@
#ifndef __CHATIGNORELIST__H__
#define __CHATIGNORELIST__H__
struct Packet;
#include <cstdint>
namespace ChatIgnoreList {
void GetIgnoreList(Packet* packet);
void AddIgnore(Packet* packet);
void RemoveIgnore(Packet* packet);
enum class Response : uint8_t {
ADD_IGNORE = 32,
REMOVE_IGNORE = 33,
GET_IGNORE = 34,
};
enum class AddResponse : uint8_t {
SUCCESS,
ALREADY_IGNORED,
PLAYER_NOT_FOUND,
GENERAL_ERROR,
};
};
#endif //!__CHATIGNORELIST__H__

File diff suppressed because it is too large Load Diff

View File

@@ -5,6 +5,8 @@
struct PlayerData;
enum class eAddFriendResponseType : uint8_t;
namespace ChatPacketHandler {
void HandleFriendlistRequest(Packet* packet);
void HandleFriendRequest(Packet* packet);
@@ -22,19 +24,18 @@ namespace ChatPacketHandler {
void HandleTeamLootOption(Packet* packet);
void HandleTeamStatusRequest(Packet* packet);
void SendTeamInvite(PlayerData* receiver, PlayerData* sender);
void SendTeamInviteConfirm(PlayerData* receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName);
void SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName);
void SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64PlayerID);
void SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID);
void SendTeamRemovePlayer(PlayerData* receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName);
void SendTeamSetOffWorldFlag(PlayerData* receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID);
void SendTeamInvite(const PlayerData& receiver, const PlayerData& sender);
void SendTeamInviteConfirm(const PlayerData& receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName);
void SendTeamStatus(const PlayerData& receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName);
void SendTeamSetLeader(const PlayerData& receiver, LWOOBJID i64PlayerID);
void SendTeamAddPlayer(const PlayerData& receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID);
void SendTeamRemovePlayer(const PlayerData& receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName);
void SendTeamSetOffWorldFlag(const PlayerData& receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID);
//FriendData is the player we're SENDING this stuff to. Player is the friend that changed state.
void SendFriendUpdate(PlayerData* friendData, PlayerData* playerData, uint8_t notifyType);
void SendFriendUpdate(const PlayerData& friendData, const PlayerData& playerData, uint8_t notifyType, uint8_t isBestFriend);
void SendFriendRequest(PlayerData* receiver, PlayerData* sender, bool isBFFReq = false);
void SendFriendResponse(PlayerData* receiver, PlayerData* sender, uint8_t responseCode = 3);
void SendRemoveFriend(PlayerData* receiver, std::string& personToRemove, bool isSuccessful);
void SendFriendRequest(const PlayerData& receiver, const PlayerData& sender);
void SendFriendResponse(const PlayerData& receiver, const PlayerData& sender, eAddFriendResponseType responseCode, uint8_t isBestFriendsAlready = 0U, uint8_t isBestFriendRequest = 0U);
void SendRemoveFriend(const PlayerData& receiver, std::string& personToRemove, bool isSuccessful);
};

View File

@@ -6,105 +6,134 @@
//DLU Includes:
#include "dCommonVars.h"
#include "dServer.h"
#include "dLogger.h"
#include "Logger.h"
#include "Database.h"
#include "dConfig.h"
#include "dMessageIdentifiers.h"
#include "dChatFilter.h"
#include "Diagnostics.h"
#include "AssetManager.h"
#include "BinaryPathFinder.h"
#include "eConnectionType.h"
#include "PlayerContainer.h"
#include "ChatPacketHandler.h"
#include "eChatMessageType.h"
#include "eChatInternalMessageType.h"
#include "eWorldMessageType.h"
#include "ChatIgnoreList.h"
#include "Game.h"
namespace Game {
dLogger* logger;
dServer* server;
dConfig* config;
dChatFilter* chatFilter;
}
#include "Server.h"
//RakNet includes:
#include "RakNetDefines.h"
#include "MessageIdentifiers.h"
namespace Game {
Logger* logger = nullptr;
dServer* server = nullptr;
dConfig* config = nullptr;
dChatFilter* chatFilter = nullptr;
AssetManager* assetManager = nullptr;
Game::signal_t lastSignal = 0;
std::mt19937 randomEngine;
PlayerContainer playerContainer;
}
dLogger* SetupLogger();
void HandlePacket(Packet* packet);
PlayerContainer playerContainer;
int main(int argc, char** argv) {
constexpr uint32_t chatFramerate = mediumFramerate;
constexpr uint32_t chatFrameDelta = mediumFrameDelta;
Diagnostics::SetProcessName("Chat");
Diagnostics::SetProcessFileName(argv[0]);
Diagnostics::Initialize();
std::signal(SIGINT, Game::OnSignal);
std::signal(SIGTERM, Game::OnSignal);
Game::config = new dConfig("chatconfig.ini");
//Create all the objects we need to run our service:
Game::logger = SetupLogger();
if (!Game::logger) return 0;
Game::logger->Log("ChatServer", "Starting Chat server...\n");
Game::logger->Log("ChatServer", "Version: %i.%i\n", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
Game::logger->Log("ChatServer", "Compiled on: %s\n", __TIMESTAMP__);
Server::SetupLogger("ChatServer");
if (!Game::logger) return EXIT_FAILURE;
//Read our config:
dConfig config("chatconfig.ini");
Game::config = &config;
Game::logger->SetLogToConsole(bool(std::stoi(config.GetValue("log_to_console"))));
//Connect to the MySQL Database
std::string mysql_host = config.GetValue("mysql_host");
std::string mysql_database = config.GetValue("mysql_database");
std::string mysql_username = config.GetValue("mysql_username");
std::string mysql_password = config.GetValue("mysql_password");
LOG("Starting Chat server...");
LOG("Version: %s", PROJECT_VERSION);
LOG("Compiled on: %s", __TIMESTAMP__);
try {
Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password);
std::string clientPathStr = Game::config->GetValue("client_location");
if (clientPathStr.empty()) clientPathStr = "./res";
std::filesystem::path clientPath = std::filesystem::path(clientPathStr);
if (clientPath.is_relative()) {
clientPath = BinaryPathFinder::GetBinaryDir() / clientPath;
}
Game::assetManager = new AssetManager(clientPath);
} catch (std::runtime_error& ex) {
LOG("Got an error while setting up assets: %s", ex.what());
return EXIT_FAILURE;
}
catch (sql::SQLException& ex) {
Game::logger->Log("ChatServer", "Got an error while connecting to the database: %s\n", ex.what());
Database::Destroy();
//Connect to the MySQL Database
try {
Database::Connect();
} catch (sql::SQLException& ex) {
LOG("Got an error while connecting to the database: %s", ex.what());
Database::Destroy("ChatServer");
delete Game::server;
delete Game::logger;
return 0;
return EXIT_FAILURE;
}
//Find out the master's IP:
std::string masterIP;
int masterPort = 1000;
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT ip, port FROM servers WHERE name='master';");
auto res = stmt->executeQuery();
while (res->next()) {
masterIP = res->getString(1).c_str();
masterPort = res->getInt(2);
uint32_t masterPort = 1000;
auto masterInfo = Database::Get()->GetMasterInfo();
if (masterInfo) {
masterIP = masterInfo->ip;
masterPort = masterInfo->port;
}
delete res;
delete stmt;
//It's safe to pass 'localhost' here, as the IP is only used as the external IP.
int maxClients = 50;
int ourPort = 1501;
if (config.GetValue("max_clients") != "") maxClients = std::stoi(config.GetValue("max_clients"));
if (config.GetValue("port") != "") ourPort = std::atoi(config.GetValue("port").c_str());
uint32_t maxClients = 999;
uint32_t ourPort = 1501;
std::string ourIP = "localhost";
GeneralUtils::TryParse(Game::config->GetValue("max_clients"), maxClients);
GeneralUtils::TryParse(Game::config->GetValue("chat_server_port"), ourPort);
const auto externalIPString = Game::config->GetValue("external_ip");
if (!externalIPString.empty()) ourIP = externalIPString;
Game::server = new dServer(config.GetValue("external_ip"), ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Chat);
Game::server = new dServer(ourIP, ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Chat, Game::config, &Game::lastSignal);
Game::chatFilter = new dChatFilter("./res/chatplus_en_us", bool(std::stoi(config.GetValue("dont_generate_dcf"))));
bool dontGenerateDCF = false;
GeneralUtils::TryParse(Game::config->GetValue("dont_generate_dcf"), dontGenerateDCF);
Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", dontGenerateDCF);
Game::randomEngine = std::mt19937(time(0));
Game::playerContainer.Initialize();
//Run it until server gets a kill message from Master:
auto t = std::chrono::high_resolution_clock::now();
Packet* packet = nullptr;
int framesSinceLastFlush = 0;
int framesSinceMasterDisconnect = 0;
int framesSinceLastSQLPing = 0;
constexpr uint32_t logFlushTime = 30 * chatFramerate; // 30 seconds in frames
constexpr uint32_t sqlPingTime = 10 * 60 * chatFramerate; // 10 minutes in frames
uint32_t framesSinceLastFlush = 0;
uint32_t framesSinceMasterDisconnect = 0;
uint32_t framesSinceLastSQLPing = 0;
while (true) {
Game::logger->Flush(); // once immediately before main loop
while (!Game::ShouldShutdown()) {
//Check if we're still connected to master:
if (!Game::server->GetIsConnectedToMaster()) {
framesSinceMasterDisconnect++;
if (framesSinceMasterDisconnect >= 30)
if (framesSinceMasterDisconnect >= chatFramerate)
break; //Exit our loop, shut down.
}
else framesSinceMasterDisconnect = 0;
} else framesSinceMasterDisconnect = 0;
//In world we'd update our other systems here.
@@ -118,82 +147,70 @@ int main(int argc, char** argv) {
}
//Push our log every 30s:
if (framesSinceLastFlush >= 900) {
if (framesSinceLastFlush >= logFlushTime) {
Game::logger->Flush();
framesSinceLastFlush = 0;
}
else framesSinceLastFlush++;
} else framesSinceLastFlush++;
//Every 10 min we ping our sql server to keep it alive hopefully:
if (framesSinceLastSQLPing >= 40000) {
if (framesSinceLastSQLPing >= sqlPingTime) {
//Find out the master's IP for absolutely no reason:
std::string masterIP;
int masterPort;
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT ip, port FROM servers WHERE name='master';");
auto res = stmt->executeQuery();
while (res->next()) {
masterIP = res->getString(1).c_str();
masterPort = res->getInt(2);
uint32_t masterPort;
auto masterInfo = Database::Get()->GetMasterInfo();
if (masterInfo) {
masterIP = masterInfo->ip;
masterPort = masterInfo->port;
}
delete res;
delete stmt;
framesSinceLastSQLPing = 0;
}
else framesSinceLastSQLPing++;
} else framesSinceLastSQLPing++;
//Sleep our thread since auth can afford to.
t += std::chrono::milliseconds(mediumFramerate); //Chat can run at a lower "fps"
t += std::chrono::milliseconds(chatFrameDelta); //Chat can run at a lower "fps"
std::this_thread::sleep_until(t);
}
//Delete our objects here:
Database::Destroy();
Database::Destroy("ChatServer");
delete Game::server;
delete Game::logger;
delete Game::config;
return 0;
}
dLogger* SetupLogger() {
std::string logPath = "./logs/ChatServer_" + std::to_string(time(nullptr)) + ".log";
bool logToConsole = false;
#ifdef _DEBUG
logToConsole = true;
#endif
return new dLogger(logPath, logToConsole);
return EXIT_SUCCESS;
}
void HandlePacket(Packet* packet) {
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.\n");
LOG("A server has disconnected, erasing their connected players from the list.");
}
if (packet->data[0] == ID_NEW_INCOMING_CONNECTION) {
Game::logger->Log("ChatServer", "A server is connecting, awaiting user list.\n");
LOG("A server is connecting, awaiting user list.");
}
if (packet->data[1] == CHAT_INTERNAL) {
switch (packet->data[3]) {
case MSG_CHAT_INTERNAL_PLAYER_ADDED_NOTIFICATION:
playerContainer.InsertPlayer(packet);
if (packet->length < 4) return; // Nothing left to process. Need 4 bytes to continue.
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::CHAT_INTERNAL) {
switch (static_cast<eChatInternalMessageType>(packet->data[3])) {
case eChatInternalMessageType::PLAYER_ADDED_NOTIFICATION:
Game::playerContainer.InsertPlayer(packet);
break;
case MSG_CHAT_INTERNAL_PLAYER_REMOVED_NOTIFICATION:
playerContainer.RemovePlayer(packet);
case eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION:
Game::playerContainer.RemovePlayer(packet);
break;
case MSG_CHAT_INTERNAL_MUTE_UPDATE:
playerContainer.MuteUpdate(packet);
case eChatInternalMessageType::MUTE_UPDATE:
Game::playerContainer.MuteUpdate(packet);
break;
case MSG_CHAT_INTERNAL_CREATE_TEAM:
playerContainer.CreateTeamServer(packet);
case eChatInternalMessageType::CREATE_TEAM:
Game::playerContainer.CreateTeamServer(packet);
break;
case MSG_CHAT_INTERNAL_ANNOUNCEMENT: {
case eChatInternalMessageType::ANNOUNCEMENT: {
//we just forward this packet to every connected server
CINSTREAM;
Game::server->Send(&inStream, packet->systemAddress, true); //send to everyone except origin
@@ -201,88 +218,96 @@ void HandlePacket(Packet* packet) {
}
default:
Game::logger->Log("ChatServer", "Unknown CHAT_INTERNAL id: %i\n", int(packet->data[3]));
LOG("Unknown CHAT_INTERNAL id: %i", int(packet->data[3]));
}
}
if (packet->data[1] == CHAT) {
switch (packet->data[3]) {
case MSG_CHAT_GET_FRIENDS_LIST:
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::CHAT) {
switch (static_cast<eChatMessageType>(packet->data[3])) {
case eChatMessageType::GET_FRIENDS_LIST:
ChatPacketHandler::HandleFriendlistRequest(packet);
break;
case MSG_CHAT_GET_IGNORE_LIST:
Game::logger->Log("ChatServer", "Asked for ignore list, but is unimplemented right now.\n");
case eChatMessageType::GET_IGNORE_LIST:
ChatIgnoreList::GetIgnoreList(packet);
break;
case MSG_CHAT_TEAM_GET_STATUS:
case eChatMessageType::ADD_IGNORE:
ChatIgnoreList::AddIgnore(packet);
break;
case eChatMessageType::REMOVE_IGNORE:
ChatIgnoreList::RemoveIgnore(packet);
break;
case eChatMessageType::TEAM_GET_STATUS:
ChatPacketHandler::HandleTeamStatusRequest(packet);
break;
case MSG_CHAT_ADD_FRIEND_REQUEST:
case eChatMessageType::ADD_FRIEND_REQUEST:
//this involves someone sending the initial request, the response is below, response as in from the other player.
//We basically just check to see if this player is online or not and route the packet.
ChatPacketHandler::HandleFriendRequest(packet);
break;
case MSG_CHAT_ADD_FRIEND_RESPONSE:
case eChatMessageType::ADD_FRIEND_RESPONSE:
//This isn't the response a server sent, rather it is a player's response to a received request.
//Here, we'll actually have to add them to eachother's friend lists depending on the response code.
ChatPacketHandler::HandleFriendResponse(packet);
break;
case MSG_CHAT_REMOVE_FRIEND:
case eChatMessageType::REMOVE_FRIEND:
ChatPacketHandler::HandleRemoveFriend(packet);
break;
case MSG_CHAT_GENERAL_CHAT_MESSAGE:
case eChatMessageType::GENERAL_CHAT_MESSAGE:
ChatPacketHandler::HandleChatMessage(packet);
break;
case MSG_CHAT_PRIVATE_CHAT_MESSAGE:
case eChatMessageType::PRIVATE_CHAT_MESSAGE:
//This message is supposed to be echo'd to both the sender and the receiver
//BUT: they have to have different responseCodes, so we'll do some of the ol hacky wacky to fix that right up.
ChatPacketHandler::HandlePrivateChatMessage(packet);
break;
case MSG_CHAT_TEAM_INVITE:
case eChatMessageType::TEAM_INVITE:
ChatPacketHandler::HandleTeamInvite(packet);
break;
case MSG_CHAT_TEAM_INVITE_RESPONSE:
case eChatMessageType::TEAM_INVITE_RESPONSE:
ChatPacketHandler::HandleTeamInviteResponse(packet);
break;
case MSG_CHAT_TEAM_LEAVE:
case eChatMessageType::TEAM_LEAVE:
ChatPacketHandler::HandleTeamLeave(packet);
break;
case MSG_CHAT_TEAM_SET_LEADER:
case eChatMessageType::TEAM_SET_LEADER:
ChatPacketHandler::HandleTeamPromote(packet);
break;
case MSG_CHAT_TEAM_KICK:
case eChatMessageType::TEAM_KICK:
ChatPacketHandler::HandleTeamKick(packet);
break;
case MSG_CHAT_TEAM_SET_LOOT:
case eChatMessageType::TEAM_SET_LOOT:
ChatPacketHandler::HandleTeamLootOption(packet);
break;
default:
Game::logger->Log("ChatServer", "Unknown CHAT id: %i\n", int(packet->data[3]));
LOG("Unknown CHAT id: %i", int(packet->data[3]));
}
}
if (packet->data[1] == WORLD) {
switch (packet->data[3]) {
case MSG_WORLD_CLIENT_ROUTE_PACKET: {
printf("routing packet from world\n");
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::WORLD) {
switch (static_cast<eWorldMessageType>(packet->data[3])) {
case eWorldMessageType::ROUTE_PACKET: {
LOG("Routing packet from world");
break;
}
default:
Game::logger->Log("ChatServer", "Unknown World id: %i\n", int(packet->data[3]));
LOG("Unknown World id: %i", int(packet->data[3]));
}
}
}

View File

@@ -3,125 +3,120 @@
#include <iostream>
#include <algorithm>
#include "Game.h"
#include "dLogger.h"
#include "Logger.h"
#include "ChatPacketHandler.h"
#include "GeneralUtils.h"
#include "dMessageIdentifiers.h"
#include "PacketUtils.h"
#include "BitStreamUtils.h"
#include "Database.h"
#include "eConnectionType.h"
#include "eChatInternalMessageType.h"
#include "ChatPackets.h"
#include "dConfig.h"
PlayerContainer::PlayerContainer() {
void PlayerContainer::Initialize() {
GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("max_number_of_best_friends"), m_MaxNumberOfBestFriends);
GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("max_number_of_friends"), m_MaxNumberOfFriends);
}
PlayerContainer::~PlayerContainer() {
mPlayers.clear();
m_Players.clear();
}
TeamData::TeamData() {
lootFlag = Game::config->GetValue("default_team_loot") == "0" ? 0 : 1;
}
void PlayerContainer::InsertPlayer(Packet* packet) {
CINSTREAM;
PlayerData* data = new PlayerData();
inStream.Read(data->playerID);
inStream.Read(data->playerID);
inStream.Read(data->playerName);
inStream.Read(data->zoneID);
inStream.Read(data->muteExpire);
data->sysAddr = packet->systemAddress;
mNames[data->playerID] = GeneralUtils::ASCIIToUTF16(std::string(data->playerName.C_String()));
mPlayers.insert(std::make_pair(data->playerID, data));
Game::logger->Log("PlayerContainer", "Added user: %s (%llu), zone: %i\n", data->playerName.C_String(), data->playerID, data->zoneID.GetMapID());
auto* insertLog = Database::CreatePreppedStmt("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);");
insertLog->setInt(1, data->playerID);
insertLog->setInt(2, 0);
insertLog->setUInt64(3, time(nullptr));
insertLog->setInt(4, data->zoneID.GetMapID());
insertLog->executeUpdate();
}
void PlayerContainer::RemovePlayer(Packet* packet) {
CINSTREAM;
LWOOBJID playerID;
inStream.Read(playerID); //skip header
inStream.Read(playerID);
//Before they get kicked, we need to also send a message to their friends saying that they disconnected.
auto player = this->GetPlayerData(playerID);
if (player == nullptr) {
CINSTREAM_SKIP_HEADER;
LWOOBJID playerId;
if (!inStream.Read(playerId)) {
LOG("Failed to read player ID");
return;
}
for (auto& fr : player->friends) {
//if (!fr.isOnline) continue;
auto& data = m_Players[playerId];
data.playerID = playerId;
auto fd = this->GetPlayerData(fr.friendID);
if (fd) ChatPacketHandler::SendFriendUpdate(fd, player, 0);
uint32_t len;
inStream.Read<uint32_t>(len);
for (int i = 0; i < len; i++) {
char character; inStream.Read<char>(character);
data.playerName += character;
}
inStream.Read(data.zoneID);
inStream.Read(data.muteExpire);
data.sysAddr = packet->systemAddress;
m_Names[data.playerID] = GeneralUtils::UTF8ToUTF16(data.playerName);
LOG("Added user: %s (%llu), zone: %i", data.playerName.c_str(), data.playerID, data.zoneID.GetMapID());
Database::Get()->UpdateActivityLog(data.playerID, eActivityType::PlayerLoggedIn, data.zoneID.GetMapID());
}
void PlayerContainer::RemovePlayer(Packet* packet) {
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID;
inStream.Read(playerID);
//Before they get kicked, we need to also send a message to their friends saying that they disconnected.
const auto& player = GetPlayerData(playerID);
if (!player) {
LOG("Failed to find user: %llu", playerID);
return;
}
for (const auto& fr : player.friends) {
const auto& fd = this->GetPlayerData(fr.friendID);
if (fd) ChatPacketHandler::SendFriendUpdate(fd, player, 0, fr.isBestFriend);
}
auto* team = GetTeam(playerID);
if (team != nullptr)
{
//TeamStatusUpdate(team);
if (team != nullptr) {
const auto memberName = GeneralUtils::UTF8ToUTF16(player.playerName);
const auto memberName = GeneralUtils::ASCIIToUTF16(std::string(player->playerName.C_String()));
for (const auto memberId : team->memberIDs)
{
auto* otherMember = GetPlayerData(memberId);
for (const auto memberId : team->memberIDs) {
const auto& otherMember = GetPlayerData(memberId);
if (otherMember == nullptr) continue;
if (!otherMember) continue;
ChatPacketHandler::SendTeamSetOffWorldFlag(otherMember, playerID, {0, 0, 0});
//ChatPacketHandler::SendTeamRemovePlayer(otherMember, false, false, true, false, team->leaderID, player->playerID, memberName);
ChatPacketHandler::SendTeamSetOffWorldFlag(otherMember, playerID, { 0, 0, 0 });
}
}
Game::logger->Log("PlayerContainer", "Removed user: %llu\n", playerID);
mPlayers.erase(playerID);
LOG("Removed user: %llu", playerID);
m_Players.erase(playerID);
auto* insertLog = Database::CreatePreppedStmt("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);");
insertLog->setInt(1, playerID);
insertLog->setInt(2, 1);
insertLog->setUInt64(3, time(nullptr));
insertLog->setInt(4, player->zoneID.GetMapID());
insertLog->executeUpdate();
Database::Get()->UpdateActivityLog(playerID, eActivityType::PlayerLoggedOut, player.zoneID.GetMapID());
}
void PlayerContainer::MuteUpdate(Packet* packet)
{
CINSTREAM;
void PlayerContainer::MuteUpdate(Packet* packet) {
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID;
inStream.Read(playerID); //skip header
inStream.Read(playerID);
time_t expire = 0;
inStream.Read(expire);
auto* player = this->GetPlayerData(playerID);
auto& player = this->GetPlayerDataMutable(playerID);
if (player == nullptr)
{
Game::logger->Log("PlayerContainer", "Failed to find user: %llu\n", playerID);
if (!player) {
LOG("Failed to find user: %llu", playerID);
return;
}
player->muteExpire = expire;
player.muteExpire = expire;
BroadcastMuteUpdate(playerID, expire);
}
void PlayerContainer::CreateTeamServer(Packet* packet)
{
CINSTREAM;
void PlayerContainer::CreateTeamServer(Packet* packet) {
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID;
inStream.Read(playerID); //skip header
inStream.Read(playerID);
size_t membersSize = 0;
inStream.Read(membersSize);
@@ -130,8 +125,7 @@ void PlayerContainer::CreateTeamServer(Packet* packet)
members.reserve(membersSize);
for (size_t i = 0; i < membersSize; i++)
{
for (size_t i = 0; i < membersSize; i++) {
LWOOBJID member;
inStream.Read(member);
members.push_back(member);
@@ -140,21 +134,19 @@ void PlayerContainer::CreateTeamServer(Packet* packet)
LWOZONEID zoneId;
inStream.Read(zoneId);
auto* team = CreateLocalTeam(members);
if (team != nullptr)
{
if (team != nullptr) {
team->zoneId = zoneId;
}
UpdateTeamsOnWorld(team, false);
}
void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time)
{
void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time) {
CBITSTREAM;
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_MUTE_UPDATE);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::MUTE_UPDATE);
bitStream.Write(player);
bitStream.Write(time);
@@ -162,30 +154,23 @@ void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time)
Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
}
TeamData* PlayerContainer::CreateLocalTeam(std::vector<LWOOBJID> members)
{
if (members.empty())
{
TeamData* PlayerContainer::CreateLocalTeam(std::vector<LWOOBJID> members) {
if (members.empty()) {
return nullptr;
}
TeamData* newTeam = nullptr;
for (const auto member : members)
{
for (const auto member : members) {
auto* team = GetTeam(member);
if (team != nullptr)
{
if (team != nullptr) {
RemoveMember(team, member, false, false, true);
}
if (newTeam == nullptr)
{
if (newTeam == nullptr) {
newTeam = CreateTeam(member, true);
}
else
{
} else {
AddMember(newTeam, member);
}
}
@@ -197,14 +182,13 @@ TeamData* PlayerContainer::CreateLocalTeam(std::vector<LWOOBJID> members)
return newTeam;
}
TeamData* PlayerContainer::CreateTeam(LWOOBJID leader, bool local)
{
TeamData* PlayerContainer::CreateTeam(LWOOBJID leader, bool local) {
auto* team = new TeamData();
team->teamID = ++mTeamIDCounter;
team->teamID = ++m_TeamIDCounter;
team->leaderID = leader;
team->local = local;
mTeams.push_back(team);
AddMember(team, leader);
@@ -212,95 +196,85 @@ TeamData* PlayerContainer::CreateTeam(LWOOBJID leader, bool local)
return team;
}
TeamData* PlayerContainer::GetTeam(LWOOBJID playerID)
{
for (auto* team : mTeams)
{
TeamData* PlayerContainer::GetTeam(LWOOBJID playerID) {
for (auto* team : mTeams) {
if (std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID) == team->memberIDs.end()) continue;
return team;
}
return nullptr;
}
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");
const 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);
if (index != team->memberIDs.end()) return;
team->memberIDs.push_back(playerID);
auto* leader = GetPlayerData(team->leaderID);
auto* member = GetPlayerData(playerID);
const auto& leader = GetPlayerData(team->leaderID);
const auto& member = GetPlayerData(playerID);
if (leader == nullptr || member == nullptr) return;
if (!leader || !member) return;
const auto leaderName = GeneralUtils::ASCIIToUTF16(std::string(leader->playerName.C_String()));
const auto memberName = GeneralUtils::ASCIIToUTF16(std::string(member->playerName.C_String()));
const auto leaderName = GeneralUtils::UTF8ToUTF16(leader.playerName);
const auto memberName = GeneralUtils::UTF8ToUTF16(member.playerName);
ChatPacketHandler::SendTeamInviteConfirm(member, false, leader->playerID, leader->zoneID, team->lootFlag, 0, 0, leaderName);
/*
ChatPacketHandler::SendTeamAddPlayer(member, false, false, false, leader->playerID, leaderName, leader->zoneID);
ChatPacketHandler::SendTeamInviteConfirm(member, false, leader.playerID, leader.zoneID, team->lootFlag, 0, 0, leaderName);
Game::logger->Log("PlayerContainer", "Team invite successfully accepted, leader: %s, member: %s\n", leader->playerName.C_String(), member->playerName.C_String());
*/
if (!team->local)
{
ChatPacketHandler::SendTeamSetLeader(member, leader->playerID);
}
else
{
if (!team->local) {
ChatPacketHandler::SendTeamSetLeader(member, leader.playerID);
} else {
ChatPacketHandler::SendTeamSetLeader(member, LWOOBJID_EMPTY);
}
UpdateTeamsOnWorld(team, false);
for (const auto memberId : team->memberIDs)
{
auto* otherMember = GetPlayerData(memberId);
for (const auto memberId : team->memberIDs) {
const auto& otherMember = GetPlayerData(memberId);
if (otherMember == member) continue;
const auto otherMemberName = GetName(memberId);
ChatPacketHandler::SendTeamAddPlayer(member, false, team->local, false, memberId, otherMemberName, otherMember != nullptr ? otherMember->zoneID : LWOZONEID(0, 0, 0));
if (otherMember != nullptr)
{
ChatPacketHandler::SendTeamAddPlayer(otherMember, false, team->local, false, member->playerID, memberName, member->zoneID);
ChatPacketHandler::SendTeamAddPlayer(member, false, team->local, false, memberId, otherMemberName, otherMember ? otherMember.zoneID : LWOZONEID(0, 0, 0));
if (otherMember) {
ChatPacketHandler::SendTeamAddPlayer(otherMember, false, team->local, false, member.playerID, memberName, member.zoneID);
}
}
}
void PlayerContainer::RemoveMember(TeamData* team, LWOOBJID playerID, bool disband, bool kicked, bool leaving, bool silent)
{
void PlayerContainer::RemoveMember(TeamData* team, LWOOBJID playerID, bool disband, bool kicked, bool leaving, bool silent) {
const auto index = std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID);
if (index == team->memberIDs.end()) return;
auto* member = GetPlayerData(playerID);
if (member != nullptr && !silent)
{
const auto& member = GetPlayerData(playerID);
if (member && !silent) {
ChatPacketHandler::SendTeamSetLeader(member, LWOOBJID_EMPTY);
}
const auto memberName = GetName(playerID);
for (const auto memberId : team->memberIDs)
{
if (silent && memberId == playerID)
{
for (const auto memberId : team->memberIDs) {
if (silent && memberId == playerID) {
continue;
}
auto* otherMember = GetPlayerData(memberId);
const auto& otherMember = GetPlayerData(memberId);
if (otherMember == nullptr) continue;
if (!otherMember) continue;
ChatPacketHandler::SendTeamRemovePlayer(otherMember, disband, kicked, leaving, false, team->leaderID, playerID, memberName);
}
@@ -309,51 +283,43 @@ void PlayerContainer::RemoveMember(TeamData* team, LWOOBJID playerID, bool disba
UpdateTeamsOnWorld(team, false);
if (team->memberIDs.size() <= 1)
{
if (team->memberIDs.size() <= 1) {
DisbandTeam(team);
}
else
{
if (playerID == team->leaderID)
{
} else {
if (playerID == team->leaderID) {
PromoteMember(team, team->memberIDs[0]);
}
}
}
void PlayerContainer::PromoteMember(TeamData* team, LWOOBJID newLeader)
{
void PlayerContainer::PromoteMember(TeamData* team, LWOOBJID newLeader) {
team->leaderID = newLeader;
for (const auto memberId : team->memberIDs)
{
auto* otherMember = GetPlayerData(memberId);
for (const auto memberId : team->memberIDs) {
const auto& otherMember = GetPlayerData(memberId);
if (otherMember == nullptr) continue;
if (!otherMember) continue;
ChatPacketHandler::SendTeamSetLeader(otherMember, newLeader);
}
}
void PlayerContainer::DisbandTeam(TeamData* team)
{
void PlayerContainer::DisbandTeam(TeamData* team) {
const auto index = std::find(mTeams.begin(), mTeams.end(), team);
if (index == mTeams.end()) return;
for (const auto memberId : team->memberIDs)
{
auto* otherMember = GetPlayerData(memberId);
for (const auto memberId : team->memberIDs) {
const auto& otherMember = GetPlayerData(memberId);
if (otherMember == nullptr) continue;
if (!otherMember) continue;
const auto memberName = GeneralUtils::ASCIIToUTF16(std::string(otherMember->playerName.C_String()));
const auto memberName = GeneralUtils::UTF8ToUTF16(otherMember.playerName);
ChatPacketHandler::SendTeamSetLeader(otherMember, LWOOBJID_EMPTY);
ChatPacketHandler::SendTeamRemovePlayer(otherMember, true, false, false, team->local, team->leaderID, otherMember->playerID, memberName);
ChatPacketHandler::SendTeamRemovePlayer(otherMember, true, false, false, team->local, team->leaderID, otherMember.playerID, memberName);
}
UpdateTeamsOnWorld(team, true);
mTeams.erase(index);
@@ -361,51 +327,41 @@ void PlayerContainer::DisbandTeam(TeamData* team)
delete team;
}
void PlayerContainer::TeamStatusUpdate(TeamData* team)
{
void PlayerContainer::TeamStatusUpdate(TeamData* team) {
const auto index = std::find(mTeams.begin(), mTeams.end(), team);
if (index == mTeams.end()) return;
auto* leader = GetPlayerData(team->leaderID);
const auto& leader = GetPlayerData(team->leaderID);
if (leader == nullptr) return;
if (!leader) return;
const auto leaderName = GeneralUtils::ASCIIToUTF16(std::string(leader->playerName.C_String()));
const auto leaderName = GeneralUtils::UTF8ToUTF16(leader.playerName);
for (const auto memberId : team->memberIDs)
{
auto* otherMember = GetPlayerData(memberId);
for (const auto memberId : team->memberIDs) {
const auto& otherMember = GetPlayerData(memberId);
if (otherMember == nullptr) continue;
if (!otherMember) continue;
if (!team->local)
{
ChatPacketHandler::SendTeamStatus(otherMember, team->leaderID, leader->zoneID, team->lootFlag, 0, leaderName);
}
else
{
//ChatPacketHandler::SendTeamStatus(otherMember, LWOOBJID_EMPTY, LWOZONEID(0, 0, 0), 1, 0, u"");
if (!team->local) {
ChatPacketHandler::SendTeamStatus(otherMember, team->leaderID, leader.zoneID, team->lootFlag, 0, leaderName);
}
}
UpdateTeamsOnWorld(team, false);
}
void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam)
{
void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) {
CBITSTREAM;
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_TEAM_UPDATE);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::TEAM_UPDATE);
bitStream.Write(team->teamID);
bitStream.Write(deleteTeam);
if (!deleteTeam)
{
if (!deleteTeam) {
bitStream.Write(team->lootFlag);
bitStream.Write(static_cast<char>(team->memberIDs.size()));
for (const auto memberID : team->memberIDs)
{
bitStream.Write<char>(team->memberIDs.size());
for (const auto memberID : team->memberIDs) {
bitStream.Write(memberID);
}
}
@@ -413,29 +369,43 @@ void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam)
Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
}
std::u16string PlayerContainer::GetName(LWOOBJID playerID)
{
const auto& pair = mNames.find(playerID);
std::u16string PlayerContainer::GetName(LWOOBJID playerID) {
const auto iter = m_Names.find(playerID);
if (pair == mNames.end()) return u"";
if (iter == m_Names.end()) return u"";
return pair->second;
return iter->second;
}
LWOOBJID PlayerContainer::GetId(const std::u16string& playerName)
{
for (const auto& pair : mNames)
{
if (pair.second == playerName)
{
return pair.first;
LWOOBJID PlayerContainer::GetId(const std::u16string& playerName) {
LWOOBJID toReturn = LWOOBJID_EMPTY;
for (const auto& [id, name] : m_Names) {
if (name == playerName) {
toReturn = id;
break;
}
}
return LWOOBJID_EMPTY;
return toReturn;
}
bool PlayerContainer::GetIsMuted(PlayerData* data)
{
return data->muteExpire == 1 || data->muteExpire > time(NULL);
PlayerData& PlayerContainer::GetPlayerDataMutable(const LWOOBJID& playerID) {
return m_Players[playerID];
}
PlayerData& PlayerContainer::GetPlayerDataMutable(const std::string& playerName) {
for (auto& [id, player] : m_Players) {
if (!player) continue;
if (player.playerName == playerName) return player;
}
return m_Players[LWOOBJID_EMPTY];
}
const PlayerData& PlayerContainer::GetPlayerData(const LWOOBJID& playerID) {
return GetPlayerDataMutable(playerID);
}
const PlayerData& PlayerContainer::GetPlayerData(const std::string& playerName) {
return GetPlayerDataMutable(playerName);
}

View File

@@ -7,19 +7,48 @@
#include "dServer.h"
#include <unordered_map>
struct IgnoreData {
IgnoreData(const std::string& name, const LWOOBJID& id) : playerName(name), playerId(id) {}
inline bool operator==(const std::string& other) const noexcept {
return playerName == other;
}
inline bool operator==(const LWOOBJID& other) const noexcept {
return playerId == other;
}
LWOOBJID playerId = LWOOBJID_EMPTY;
std::string playerName;
};
struct PlayerData {
LWOOBJID playerID;
RakNet::RakString playerName;
SystemAddress sysAddr;
LWOZONEID zoneID;
operator bool() const noexcept {
return playerID != LWOOBJID_EMPTY;
}
bool operator==(const PlayerData& other) const noexcept {
return playerID == other.playerID;
}
bool GetIsMuted() const {
return muteExpire == 1 || muteExpire > time(NULL);
}
SystemAddress sysAddr{};
LWOZONEID zoneID{};
LWOOBJID playerID = LWOOBJID_EMPTY;
time_t muteExpire = 0;
uint8_t countOfBestFriends = 0;
std::string playerName;
std::vector<FriendData> friends;
time_t muteExpire;
std::vector<IgnoreData> ignoredPlayers;
};
struct TeamData {
TeamData();
LWOOBJID teamID = LWOOBJID_EMPTY; // Internal use
LWOOBJID leaderID = LWOOBJID_EMPTY;
std::vector<LWOOBJID> memberIDs {};
std::vector<LWOOBJID> memberIDs{};
uint8_t lootFlag = 0;
bool local = false;
LWOZONEID zoneId = {};
@@ -27,31 +56,19 @@ struct TeamData {
class PlayerContainer {
public:
PlayerContainer();
~PlayerContainer();
void Initialize();
void InsertPlayer(Packet* packet);
void RemovePlayer(Packet* packet);
void MuteUpdate(Packet* packet);
void CreateTeamServer(Packet* packet);
void BroadcastMuteUpdate(LWOOBJID player, time_t time);
PlayerData* GetPlayerData(const LWOOBJID& playerID) {
auto it = mPlayers.find(playerID);
if (it != mPlayers.end()) return it->second;
return nullptr;
}
PlayerData* GetPlayerData(const std::string& playerName) {
for (auto player : mPlayers) {
if (player.second) {
std::string pn = player.second->playerName.C_String();
if (pn == playerName) return player.second;
}
}
return nullptr;
}
const PlayerData& GetPlayerData(const LWOOBJID& playerID);
const PlayerData& GetPlayerData(const std::string& playerName);
PlayerData& GetPlayerDataMutable(const LWOOBJID& playerID);
PlayerData& GetPlayerDataMutable(const std::string& playerName);
TeamData* CreateLocalTeam(std::vector<LWOOBJID> members);
TeamData* CreateTeam(LWOOBJID leader, bool local = false);
@@ -64,14 +81,15 @@ public:
void UpdateTeamsOnWorld(TeamData* team, bool deleteTeam);
std::u16string GetName(LWOOBJID playerID);
LWOOBJID GetId(const std::u16string& playerName);
bool GetIsMuted(PlayerData* data);
std::map<LWOOBJID, PlayerData*>& GetAllPlayerData() { return mPlayers; }
uint32_t GetMaxNumberOfBestFriends() { return m_MaxNumberOfBestFriends; }
uint32_t GetMaxNumberOfFriends() { return m_MaxNumberOfFriends; }
private:
LWOOBJID mTeamIDCounter = 0;
std::map<LWOOBJID, PlayerData*> mPlayers;
LWOOBJID m_TeamIDCounter = 0;
std::map<LWOOBJID, PlayerData> m_Players;
std::vector<TeamData*> mTeams;
std::unordered_map<LWOOBJID, std::u16string> mNames;
std::unordered_map<LWOOBJID, std::u16string> m_Names;
uint32_t m_MaxNumberOfBestFriends = 5;
uint32_t m_MaxNumberOfFriends = 50;
};

153
dCommon/AMFDeserialize.cpp Normal file
View File

@@ -0,0 +1,153 @@
#include "AMFDeserialize.h"
#include <stdexcept>
#include "Amf3.h"
/**
* AMF3 Reference document https://rtmp.veriskope.com/pdf/amf3-file-format-spec.pdf
* AMF3 Deserializer written by EmosewaMC
*/
AMFBaseValue* AMFDeserialize::Read(RakNet::BitStream* inStream) {
if (!inStream) return nullptr;
AMFBaseValue* returnValue = nullptr;
// Read in the value type from the bitStream
eAmf marker;
inStream->Read(marker);
// Based on the typing, create the value associated with that and return the base value class
switch (marker) {
case eAmf::Undefined: {
returnValue = new AMFBaseValue();
break;
}
case eAmf::Null: {
returnValue = new AMFNullValue();
break;
}
case eAmf::False: {
returnValue = new AMFBoolValue(false);
break;
}
case eAmf::True: {
returnValue = new AMFBoolValue(true);
break;
}
case eAmf::Integer: {
returnValue = ReadAmfInteger(inStream);
break;
}
case eAmf::Double: {
returnValue = ReadAmfDouble(inStream);
break;
}
case eAmf::String: {
returnValue = ReadAmfString(inStream);
break;
}
case eAmf::Array: {
returnValue = ReadAmfArray(inStream);
break;
}
// These values are unimplemented in the live client and will remain unimplemented
// unless someone modifies the client to allow serializing of these values.
case eAmf::XMLDoc:
case eAmf::Date:
case eAmf::Object:
case eAmf::XML:
case eAmf::ByteArray:
case eAmf::VectorInt:
case eAmf::VectorUInt:
case eAmf::VectorDouble:
case eAmf::VectorObject:
case eAmf::Dictionary: {
throw marker;
break;
}
default:
throw std::invalid_argument("Invalid AMF3 marker" + std::to_string(static_cast<int32_t>(marker)));
break;
}
return returnValue;
}
uint32_t AMFDeserialize::ReadU29(RakNet::BitStream* inStream) {
bool byteFlag = true;
uint32_t actualNumber{};
uint8_t numberOfBytesRead{};
while (byteFlag && numberOfBytesRead < 4) {
uint8_t byte{};
inStream->Read(byte);
// Parse the byte
if (numberOfBytesRead < 3) {
byteFlag = byte & static_cast<uint8_t>(1 << 7);
byte = byte << 1UL;
}
// Combine the read byte with our current read in number
actualNumber <<= 8UL;
actualNumber |= static_cast<uint32_t>(byte);
// If we are not done reading in bytes, shift right 1 bit
if (numberOfBytesRead < 3) actualNumber = actualNumber >> 1UL;
numberOfBytesRead++;
}
return actualNumber;
}
const std::string AMFDeserialize::ReadString(RakNet::BitStream* inStream) {
auto length = ReadU29(inStream);
// Check if this is a reference
bool isReference = length % 2 == 1;
// Right shift by 1 bit to get index if reference or size of next string if value
length = length >> 1;
if (isReference) {
std::string value(length, 0);
inStream->Read(&value[0], length);
// Empty strings are never sent by reference
if (!value.empty()) accessedElements.push_back(value);
return value;
} else {
// Length is a reference to a previous index - use that as the read in value
return accessedElements.at(length);
}
}
AMFBaseValue* AMFDeserialize::ReadAmfDouble(RakNet::BitStream* inStream) {
double value;
inStream->Read<double>(value);
return new AMFDoubleValue(value);
}
AMFBaseValue* AMFDeserialize::ReadAmfArray(RakNet::BitStream* inStream) {
auto arrayValue = new AMFArrayValue();
// Read size of dense array
auto sizeOfDenseArray = (ReadU29(inStream) >> 1);
// Then read associative portion
while (true) {
auto key = ReadString(inStream);
// No more associative values when we encounter an empty string key
if (key.size() == 0) break;
arrayValue->Insert(key, Read(inStream));
}
// Finally read dense portion
for (uint32_t i = 0; i < sizeOfDenseArray; i++) {
arrayValue->Insert(i, Read(inStream));
}
return arrayValue;
}
AMFBaseValue* AMFDeserialize::ReadAmfString(RakNet::BitStream* inStream) {
return new AMFStringValue(ReadString(inStream));
}
AMFBaseValue* AMFDeserialize::ReadAmfInteger(RakNet::BitStream* inStream) {
return new AMFIntValue(ReadU29(inStream));
}

72
dCommon/AMFDeserialize.h Normal file
View File

@@ -0,0 +1,72 @@
#pragma once
#include "BitStream.h"
#include <vector>
#include <string>
class AMFBaseValue;
class AMFDeserialize {
public:
/**
* Read an AMF3 value from a bitstream.
*
* @param inStream inStream to read value from.
* @return Returns an AMFValue with all the information from the bitStream in it.
*/
AMFBaseValue* Read(RakNet::BitStream* inStream);
private:
/**
* @brief Private method to read a U29 integer from a bitstream
*
* @param inStream bitstream to read data from
* @return The number as an unsigned 29 bit integer
*/
uint32_t ReadU29(RakNet::BitStream* inStream);
/**
* @brief Reads a string from a bitstream
*
* @param inStream bitStream to read data from
* @return The read string
*/
const std::string ReadString(RakNet::BitStream* inStream);
/**
* @brief Read an AMFDouble value from a bitStream
*
* @param inStream bitStream to read data from
* @return Double value represented as an AMFValue
*/
AMFBaseValue* ReadAmfDouble(RakNet::BitStream* inStream);
/**
* @brief Read an AMFArray from a bitStream
*
* @param inStream bitStream to read data from
* @return Array value represented as an AMFValue
*/
AMFBaseValue* ReadAmfArray(RakNet::BitStream* inStream);
/**
* @brief Read an AMFString from a bitStream
*
* @param inStream bitStream to read data from
* @return String value represented as an AMFValue
*/
AMFBaseValue* ReadAmfString(RakNet::BitStream* inStream);
/**
* @brief Read an AMFInteger from a bitStream
*
* @param inStream bitStream to read data from
* @return Integer value represented as an AMFValue
*/
AMFBaseValue* ReadAmfInteger(RakNet::BitStream* inStream);
/**
* List of strings read so far saved to be read by reference.
*/
std::vector<std::string> accessedElements;
};

View File

@@ -1,157 +0,0 @@
#include "AMFFormat.h"
// AMFInteger
void AMFIntegerValue::SetIntegerValue(uint32_t value) {
this->value = value;
}
uint32_t AMFIntegerValue::GetIntegerValue() {
return this->value;
}
// AMFDouble
void AMFDoubleValue::SetDoubleValue(double value) {
this->value = value;
}
double AMFDoubleValue::GetDoubleValue() {
return this->value;
}
// AMFString
void AMFStringValue::SetStringValue(const std::string& value) {
this->value = value;
}
std::string AMFStringValue::GetStringValue() {
return this->value;
}
// AMFXMLDoc
void AMFXMLDocValue::SetXMLDocValue(const std::string& value) {
this->xmlData = value;
}
std::string AMFXMLDocValue::GetXMLDocValue() {
return this->xmlData;
}
// AMFDate
void AMFDateValue::SetDateValue(uint64_t value) {
this->millisecondTimestamp = value;
}
uint64_t AMFDateValue::GetDateValue() {
return this->millisecondTimestamp;
}
// AMFArray Insert Value
void AMFArrayValue::InsertValue(const std::string& key, AMFValue* value) {
this->associative.insert(std::make_pair(key, value));
}
// AMFArray Remove Value
void AMFArrayValue::RemoveValue(const std::string& key) {
_AMFArrayMap_::iterator it = this->associative.find(key);
if (it != this->associative.end()) {
this->associative.erase(it);
}
}
// AMFArray Find Value
AMFValue* AMFArrayValue::FindValue(const std::string& key) {
_AMFArrayMap_::iterator it = this->associative.find(key);
if (it != this->associative.end()) {
return it->second;
}
return nullptr;
}
// AMFArray Get Associative Iterator Begin
_AMFArrayMap_::iterator AMFArrayValue::GetAssociativeIteratorValueBegin() {
return this->associative.begin();
}
// AMFArray Get Associative Iterator End
_AMFArrayMap_::iterator AMFArrayValue::GetAssociativeIteratorValueEnd() {
return this->associative.end();
}
// AMFArray Push Back Value
void AMFArrayValue::PushBackValue(AMFValue* value) {
this->dense.push_back(value);
}
// AMFArray Pop Back Value
void AMFArrayValue::PopBackValue() {
this->dense.pop_back();
}
// AMFArray Get Dense List Size
uint32_t AMFArrayValue::GetDenseValueSize() {
return (uint32_t)this->dense.size();
}
// AMFArray Get value at index in Dense List
AMFValue* AMFArrayValue::GetValueAt(uint32_t index) {
return this->dense.at(index);
}
// AMFArray Get Dense Iterator Begin
_AMFArrayList_::iterator AMFArrayValue::GetDenseIteratorBegin() {
return this->dense.begin();
}
// AMFArray Get Dense Iterator End
_AMFArrayList_::iterator AMFArrayValue::GetDenseIteratorEnd() {
return this->dense.end();
}
// AMFObject Constructor
AMFObjectValue::AMFObjectValue(std::vector<std::pair<std::string, AMFValueType>> traits) {
this->traits.reserve(traits.size());
std::vector<std::pair<std::string, AMFValueType>>::iterator it = traits.begin();
while (it != traits.end()) {
this->traits.insert(std::make_pair(it->first, std::make_pair(it->second, new AMFNullValue())));
it++;
}
}
// AMFObject Set Value
void AMFObjectValue::SetTraitValue(const std::string& trait, AMFValue* value) {
if (value) {
_AMFObjectTraits_::iterator it = this->traits.find(trait);
if (it != this->traits.end()) {
if (it->second.first == value->GetValueType()) {
it->second.second = value;
}
}
}
}
// AMFObject Get Value
AMFValue* AMFObjectValue::GetTraitValue(const std::string& trait) {
_AMFObjectTraits_::iterator it = this->traits.find(trait);
if (it != this->traits.end()) {
return it->second.second;
}
return nullptr;
}
// AMFObject Get Trait Iterator Begin
_AMFObjectTraits_::iterator AMFObjectValue::GetTraitsIteratorBegin() {
return this->traits.begin();
}
// AMFObject Get Trait Iterator End
_AMFObjectTraits_::iterator AMFObjectValue::GetTraitsIteratorEnd() {
return this->traits.end();
}
// AMFObject Get Trait Size
uint32_t AMFObjectValue::GetTraitArrayCount() {
return (uint32_t)this->traits.size();
}

View File

@@ -1,368 +0,0 @@
#pragma once
// Custom Classes
#include "dCommonVars.h"
// C++
#include <unordered_map>
#include <vector>
/*!
\file AMFFormat.hpp
\brief A class for managing AMF values
*/
class AMFValue; // Forward declaration
// Definitions
#define _AMFArrayMap_ std::unordered_map<std::string, AMFValue*>
#define _AMFArrayList_ std::vector<AMFValue*>
#define _AMFObjectTraits_ std::unordered_map<std::string, std::pair<AMFValueType, AMFValue*>>
#define _AMFObjectDynamicTraits_ std::unordered_map<std::string, AMFValue*>
//! An enum for each AMF value type
enum AMFValueType : unsigned char {
AMFUndefined = 0x00, //!< An undefined AMF Value
AMFNull = 0x01, //!< A null AMF value
AMFFalse = 0x02, //!< A false AMF value
AMFTrue = 0x03, //!< A true AMF value
AMFInteger = 0x04, //!< An integer AMF value
AMFDouble = 0x05, //!< A double AMF value
AMFString = 0x06, //!< A string AMF value
AMFXMLDoc = 0x07, //!< An XML Doc AMF value
AMFDate = 0x08, //!< A date AMF value
AMFArray = 0x09, //!< An array AMF value
AMFObject = 0x0A, //!< An object AMF value
AMFXML = 0x0B, //!< An XML AMF value
AMFByteArray = 0x0C, //!< A byte array AMF value
AMFVectorInt = 0x0D, //!< An integer vector AMF value
AMFVectorUInt = 0x0E, //!< An unsigned integer AMF value
AMFVectorDouble = 0x0F, //!< A double vector AMF value
AMFVectorObject = 0x10, //!< An object vector AMF value
AMFDictionary = 0x11 //!< A dictionary AMF value
};
//! An enum for the object value types
enum AMFObjectValueType : unsigned char {
AMFObjectAnonymous = 0x01,
AMFObjectTyped = 0x02,
AMFObjectDynamic = 0x03,
AMFObjectExternalizable = 0x04
};
//! The base AMF value class
class AMFValue {
public:
//! Returns the AMF value type
/*!
\return The AMF value type
*/
virtual AMFValueType GetValueType() = 0;
};
//! A typedef for a pointer to an AMF value
typedef AMFValue* NDGFxValue;
// The various AMF value types
//! The undefined value AMF type
class AMFUndefinedValue : public AMFValue {
private:
//! Returns the AMF value type
/*!
\return The AMF value type
*/
AMFValueType GetValueType() { return AMFUndefined; }
};
//! The null value AMF type
class AMFNullValue : public AMFValue {
private:
//! Returns the AMF value type
/*!
\return The AMF value type
*/
AMFValueType GetValueType() { return AMFNull; }
};
//! The false value AMF type
class AMFFalseValue : public AMFValue {
private:
//! Returns the AMF value type
/*!
\return The AMF value type
*/
AMFValueType GetValueType() { return AMFFalse; }
};
//! The true value AMF type
class AMFTrueValue : public AMFValue {
private:
//! Returns the AMF value type
/*!
\return The AMF value type
*/
AMFValueType GetValueType() { return AMFTrue; }
};
//! The integer value AMF type
class AMFIntegerValue : public AMFValue {
private:
uint32_t value; //!< The value of the AMF type
//! Returns the AMF value type
/*!
\return The AMF value type
*/
AMFValueType GetValueType() { return AMFInteger; }
public:
//! Sets the integer value
/*!
\param value The value to set
*/
void SetIntegerValue(uint32_t value);
//! Gets the integer value
/*!
\return The integer value
*/
uint32_t GetIntegerValue();
};
//! The double value AMF type
class AMFDoubleValue : public AMFValue {
private:
double value; //!< The value of the AMF type
//! Returns the AMF value type
/*!
\return The AMF value type
*/
AMFValueType GetValueType() { return AMFDouble; }
public:
//! Sets the double value
/*!
\param value The value to set to
*/
void SetDoubleValue(double value);
//! Gets the double value
/*!
\return The double value
*/
double GetDoubleValue();
};
//! The string value AMF type
class AMFStringValue : public AMFValue {
private:
std::string value; //!< The value of the AMF type
//! Returns the AMF value type
/*!
\return The AMF value type
*/
AMFValueType GetValueType() { return AMFString; }
public:
//! Sets the string value
/*!
\param value The string value to set to
*/
void SetStringValue(const std::string& value);
//! Gets the string value
/*!
\return The string value
*/
std::string GetStringValue();
};
//! The XML doc value AMF type
class AMFXMLDocValue : public AMFValue {
private:
std::string xmlData; //!< The value of the AMF type
//! Returns the AMF value type
/*!
\return The AMF value type
*/
AMFValueType GetValueType() { return AMFXMLDoc; }
public:
//! Sets the XML Doc value
/*!
\param value The value to set to
*/
void SetXMLDocValue(const std::string& value);
//! Gets the XML Doc value
/*!
\return The XML Doc value
*/
std::string GetXMLDocValue();
};
//! The date value AMF type
class AMFDateValue : public AMFValue {
private:
uint64_t millisecondTimestamp; //!< The time in milliseconds since the ephoch
//! Returns the AMF value type
/*!
\return The AMF value type
*/
AMFValueType GetValueType() { return AMFDate; }
public:
//! Sets the date time
/*!
\param value The value to set to
*/
void SetDateValue(uint64_t value);
//! Gets the date value
/*!
\return The date value in milliseconds since the epoch
*/
uint64_t GetDateValue();
};
//! The array value AMF type
class AMFArrayValue : public AMFValue {
private:
_AMFArrayMap_ associative; //!< The array map (associative part)
_AMFArrayList_ dense; //!< The array list (dense part)
//! Returns the AMF value type
/*!
\return The AMF value type
*/
AMFValueType GetValueType() { return AMFArray; }
public:
//! Inserts an item into the array map for a specific key
/*!
\param key The key to set
\param value The value to add
*/
void InsertValue(const std::string& key, AMFValue* value);
//! Removes an item for a specific key
/*!
\param key The key to remove
*/
void RemoveValue(const std::string& key);
//! Finds an AMF value
/*!
\return The AMF value if found, nullptr otherwise
*/
AMFValue* FindValue(const std::string& key);
//! Returns where the associative iterator begins
/*!
\return Where the array map iterator begins
*/
_AMFArrayMap_::iterator GetAssociativeIteratorValueBegin();
//! Returns where the associative iterator ends
/*!
\return Where the array map iterator ends
*/
_AMFArrayMap_::iterator GetAssociativeIteratorValueEnd();
//! Pushes back a value into the array list
/*!
\param value The value to push back
*/
void PushBackValue(AMFValue* value);
//! Pops back the last value in the array list
void PopBackValue();
//! Gets the count of the dense list
/*!
\return The dense list size
*/
uint32_t GetDenseValueSize();
//! Gets a specific value from the list for the specified index
/*!
\param index The index to get
*/
AMFValue* GetValueAt(uint32_t index);
//! Returns where the dense iterator begins
/*!
\return Where the iterator begins
*/
_AMFArrayList_::iterator GetDenseIteratorBegin();
//! Returns where the dense iterator ends
/*!
\return Where the iterator ends
*/
_AMFArrayList_::iterator GetDenseIteratorEnd();
};
//! The anonymous object value AMF type
class AMFObjectValue : public AMFValue {
private:
_AMFObjectTraits_ traits; //!< The object traits
//! Returns the AMF value type
/*!
\return The AMF value type
*/
AMFValueType GetValueType() { return AMFObject; }
public:
//! Constructor
/*!
\param traits The traits to set
*/
AMFObjectValue(std::vector<std::pair<std::string, AMFValueType>> traits);
//! Gets the object value type
/*!
\return The object value type
*/
virtual AMFObjectValueType GetObjectValueType() { return AMFObjectAnonymous; }
//! Sets the value of a trait
/*!
\param trait The trait to set the value for
\param value The AMF value to set
*/
void SetTraitValue(const std::string& trait, AMFValue* value);
//! Gets a trait value
/*!
\param trait The trait to get the value for
\return The trait value
*/
AMFValue* GetTraitValue(const std::string& trait);
//! Gets the beginning of the object traits iterator
/*!
\return The AMF trait array iterator begin
*/
_AMFObjectTraits_::iterator GetTraitsIteratorBegin();
//! Gets the end of the object traits iterator
/*!
\return The AMF trait array iterator begin
*/
_AMFObjectTraits_::iterator GetTraitsIteratorEnd();
//! Gets the amount of traits
/*!
\return The amount of traits
*/
uint32_t GetTraitArrayCount();
};

View File

@@ -1,271 +0,0 @@
#include "AMFFormat_BitStream.h"
// Writes an AMFValue pointer to a RakNet::BitStream
template<>
void RakNet::BitStream::Write<AMFValue*>(AMFValue* value) {
if (value != nullptr) {
AMFValueType type = value->GetValueType();
switch (type) {
case AMFUndefined: {
AMFUndefinedValue* v = (AMFUndefinedValue*)value;
this->Write(*v);
break;
}
case AMFNull: {
AMFNullValue* v = (AMFNullValue*)value;
this->Write(*v);
break;
}
case AMFFalse: {
AMFFalseValue* v = (AMFFalseValue*)value;
this->Write(*v);
break;
}
case AMFTrue: {
AMFTrueValue* v = (AMFTrueValue*)value;
this->Write(*v);
break;
}
case AMFInteger: {
AMFIntegerValue* v = (AMFIntegerValue*)value;
this->Write(*v);
break;
}
case AMFString: {
AMFStringValue* v = (AMFStringValue*)value;
this->Write(*v);
break;
}
case AMFXMLDoc: {
AMFXMLDocValue* v = (AMFXMLDocValue*)value;
this->Write(*v);
break;
}
case AMFDate: {
AMFDateValue* v = (AMFDateValue*)value;
this->Write(*v);
break;
}
case AMFArray: {
AMFArrayValue* v = (AMFArrayValue*)value;
this->Write(*v);
break;
}
}
}
}
// A private function to write an value to a RakNet::BitStream
void WriteUInt29(RakNet::BitStream* bs, uint32_t v) {
unsigned char b4 = (unsigned char)v;
if (v < 0x00200000) {
b4 = b4 & 0x7F;
if (v > 0x7F) {
unsigned char b3;
v = v >> 7;
b3 = ((unsigned char)(v)) | 0x80;
if (v > 0x7F) {
unsigned char b2;
v = v >> 7;
b2 = ((unsigned char)(v)) | 0x80;
bs->Write(b2);
}
bs->Write(b3);
}
} else {
unsigned char b1;
unsigned char b2;
unsigned char b3;
v = v >> 8;
b3 = ((unsigned char)(v)) | 0x80;
v = v >> 7;
b2 = ((unsigned char)(v)) | 0x80;
v = v >> 7;
b1 = ((unsigned char)(v)) | 0x80;
bs->Write(b1);
bs->Write(b2);
bs->Write(b3);
}
bs->Write(b4);
}
// Writes a flag number to a RakNet::BitStream
void WriteFlagNumber(RakNet::BitStream* bs, uint32_t v) {
v = (v << 1) | 0x01;
WriteUInt29(bs, v);
}
// Writes an AMFString to a RakNet::BitStream
void WriteAMFString(RakNet::BitStream* bs, const std::string& str) {
WriteFlagNumber(bs, (uint32_t)str.size());
bs->Write(str.c_str(), (uint32_t)str.size());
}
// Writes an AMF U16 to a RakNet::BitStream
void WriteAMFU16(RakNet::BitStream* bs, uint16_t value) {
unsigned char b2;
b2 = (unsigned char)value;
value = value >> 8;
bs->Write((unsigned char)value);
bs->Write(b2);
}
// Writes an AMF U32 to RakNet::BitStream
void WriteAMFU32(RakNet::BitStream* bs, uint32_t value) {
unsigned char b2;
unsigned char b3;
unsigned char b4;
b4 = (unsigned char)value;
value = value >> 8;
b3 = (unsigned char)value;
value = value >> 8;
b2 = (unsigned char)value;
value = value >> 8;
bs->Write((unsigned char)value);
bs->Write(b2);
bs->Write(b3);
bs->Write(b4);
}
// Writes an AMF U64 to RakNet::BitStream
void WriteAMFU64(RakNet::BitStream* bs, uint64_t value) {
unsigned char b2;
unsigned char b3;
unsigned char b4;
unsigned char b5;
unsigned char b6;
unsigned char b7;
unsigned char b8;
b8 = (unsigned char)value;
value = value >> 8;
b7 = (unsigned char)value;
value = value >> 8;
b6 = (unsigned char)value;
value = value >> 8;
b5 = (unsigned char)value;
value = value >> 8;
b4 = (unsigned char)value;
value = value >> 8;
b3 = (unsigned char)value;
value = value >> 8;
b2 = (unsigned char)value;
value = value >> 8;
bs->Write((unsigned char)value);
bs->Write(b2);
bs->Write(b3);
bs->Write(b4);
bs->Write(b5);
bs->Write(b6);
bs->Write(b7);
bs->Write(b8);
}
// Writes an AMFUndefinedValue to BitStream
template<>
void RakNet::BitStream::Write<AMFUndefinedValue>(AMFUndefinedValue value) {
this->Write(AMFUndefined);
}
// Writes an AMFNullValue to BitStream
template<>
void RakNet::BitStream::Write<AMFNullValue>(AMFNullValue value) {
this->Write(AMFNull);
}
// Writes an AMFFalseValue to BitStream
template<>
void RakNet::BitStream::Write<AMFFalseValue>(AMFFalseValue value) {
this->Write(AMFFalse);
}
// Writes an AMFTrueValue to BitStream
template<>
void RakNet::BitStream::Write<AMFTrueValue>(AMFTrueValue value) {
this->Write(AMFTrue);
}
// Writes an AMFIntegerValue to BitStream
template<>
void RakNet::BitStream::Write<AMFIntegerValue>(AMFIntegerValue value) {
this->Write(AMFInteger);
WriteUInt29(this, value.GetIntegerValue());
}
// Writes an AMFDoubleValue to BitStream
template<>
void RakNet::BitStream::Write<AMFDoubleValue>(AMFDoubleValue value) {
this->Write(AMFDouble);
double d = value.GetDoubleValue();
WriteAMFU64(this, *((unsigned long long*)&d));
}
// Writes an AMFStringValue to BitStream
template<>
void RakNet::BitStream::Write<AMFStringValue>(AMFStringValue value) {
this->Write(AMFString);
std::string v = value.GetStringValue();
WriteAMFString(this, v);
}
// Writes an AMFXMLDocValue to BitStream
template<>
void RakNet::BitStream::Write<AMFXMLDocValue>(AMFXMLDocValue value) {
this->Write(AMFXMLDoc);
std::string v = value.GetXMLDocValue();
WriteAMFString(this, v);
}
// Writes an AMFDateValue to BitStream
template<>
void RakNet::BitStream::Write<AMFDateValue>(AMFDateValue value) {
this->Write(AMFDate);
uint64_t date = value.GetDateValue();
WriteAMFU64(this, date);
}
// Writes an AMFArrayValue to BitStream
template<>
void RakNet::BitStream::Write<AMFArrayValue>(AMFArrayValue value) {
this->Write(AMFArray);
uint32_t denseSize = value.GetDenseValueSize();
WriteFlagNumber(this, denseSize);
_AMFArrayMap_::iterator it = value.GetAssociativeIteratorValueBegin();
_AMFArrayMap_::iterator end = value.GetAssociativeIteratorValueEnd();
while (it != end) {
WriteAMFString(this, it->first);
this->Write(it->second);
it++;
}
this->Write(AMFNull);
if (denseSize > 0) {
_AMFArrayList_::iterator it2 = value.GetDenseIteratorBegin();
_AMFArrayList_::iterator end2 = value.GetDenseIteratorEnd();
while (it2 != end2) {
this->Write(*it2);
it2++;
}
}
}

View File

@@ -1,92 +0,0 @@
#pragma once
// Custom Classes
#include "AMFFormat.h"
// RakNet
#include <BitStream.h>
/*!
\file AMFBitStream.hpp
\brief A class that implements native writing of AMF values to RakNet::BitStream
*/
// We are using the RakNet namespace
namespace RakNet {
//! Writes an AMFValue pointer to a RakNet::BitStream
/*!
\param value The value to write
*/
template<>
void RakNet::BitStream::Write<AMFValue*>(AMFValue* value);
//! Writes an AMFUndefinedValue to a RakNet::BitStream
/*!
\param value The value to write
*/
template<>
void RakNet::BitStream::Write<AMFUndefinedValue>(AMFUndefinedValue value);
//! Writes an AMFNullValue to a RakNet::BitStream
/*!
\param value The value to write
*/
template<>
void RakNet::BitStream::Write<AMFNullValue>(AMFNullValue value);
//! Writes an AMFFalseValue to a RakNet::BitStream
/*!
\param value The value to write
*/
template<>
void RakNet::BitStream::Write<AMFFalseValue>(AMFFalseValue value);
//! Writes an AMFTrueValue to a RakNet::BitStream
/*!
\param value The value to write
*/
template<>
void RakNet::BitStream::Write<AMFTrueValue>(AMFTrueValue value);
//! Writes an AMFIntegerValue to a RakNet::BitStream
/*!
\param value The value to write
*/
template<>
void RakNet::BitStream::Write<AMFIntegerValue>(AMFIntegerValue value);
//! Writes an AMFDoubleValue to a RakNet::BitStream
/*!
\param value The value to write
*/
template<>
void RakNet::BitStream::Write<AMFDoubleValue>(AMFDoubleValue value);
//! Writes an AMFStringValue to a RakNet::BitStream
/*!
\param value The value to write
*/
template<>
void RakNet::BitStream::Write<AMFStringValue>(AMFStringValue value);
//! Writes an AMFXMLDocValue to a RakNet::BitStream
/*!
\param value The value to write
*/
template<>
void RakNet::BitStream::Write<AMFXMLDocValue>(AMFXMLDocValue value);
//! Writes an AMFDateValue to a RakNet::BitStream
/*!
\param value The value to write
*/
template<>
void RakNet::BitStream::Write<AMFDateValue>(AMFDateValue value);
//! Writes an AMFArrayValue to a RakNet::BitStream
/*!
\param value The value to write
*/
template<>
void RakNet::BitStream::Write<AMFArrayValue>(AMFArrayValue value);
}

367
dCommon/Amf3.h Normal file
View File

@@ -0,0 +1,367 @@
#ifndef __AMF3__H__
#define __AMF3__H__
#include "dCommonVars.h"
#include "Logger.h"
#include "Game.h"
#include <unordered_map>
#include <vector>
enum class eAmf : uint8_t {
Undefined = 0x00, // An undefined AMF Value
Null = 0x01, // A null AMF value
False = 0x02, // A false AMF value
True = 0x03, // A true AMF value
Integer = 0x04, // An integer AMF value
Double = 0x05, // A double AMF value
String = 0x06, // A string AMF value
XMLDoc = 0x07, // Unused in the live client and cannot be serialized without modification. An XML Doc AMF value
Date = 0x08, // Unused in the live client and cannot be serialized without modification. A date AMF value
Array = 0x09, // An array AMF value
Object = 0x0A, // Unused in the live client and cannot be serialized without modification. An object AMF value
XML = 0x0B, // Unused in the live client and cannot be serialized without modification. An XML AMF value
ByteArray = 0x0C, // Unused in the live client and cannot be serialized without modification. A byte array AMF value
VectorInt = 0x0D, // Unused in the live client and cannot be serialized without modification. An integer vector AMF value
VectorUInt = 0x0E, // Unused in the live client and cannot be serialized without modification. An unsigned integer AMF value
VectorDouble = 0x0F, // Unused in the live client and cannot be serialized without modification. A double vector AMF value
VectorObject = 0x10, // Unused in the live client and cannot be serialized without modification. An object vector AMF value
Dictionary = 0x11 // Unused in the live client and cannot be serialized without modification. A dictionary AMF value
};
class AMFBaseValue {
public:
virtual eAmf GetValueType() { return eAmf::Undefined; };
AMFBaseValue() {};
virtual ~AMFBaseValue() {};
};
template<typename ValueType>
class AMFValue : public AMFBaseValue {
public:
AMFValue() {};
AMFValue(ValueType value) { SetValue(value); };
virtual ~AMFValue() override {};
eAmf GetValueType() override { return eAmf::Undefined; };
const ValueType& GetValue() { return data; };
void SetValue(ValueType value) { data = value; };
protected:
ValueType data;
};
// As a string this is much easier to write and read from a BitStream.
template<>
class AMFValue<const char*> : public AMFBaseValue {
public:
AMFValue() {};
AMFValue(const char* value) { SetValue(std::string(value)); };
virtual ~AMFValue() override {};
eAmf GetValueType() override { return eAmf::String; };
const std::string& GetValue() { return data; };
void SetValue(std::string value) { data = value; };
protected:
std::string data;
};
typedef AMFValue<std::nullptr_t> AMFNullValue;
typedef AMFValue<bool> AMFBoolValue;
typedef AMFValue<int32_t> AMFIntValue;
typedef AMFValue<std::string> AMFStringValue;
typedef AMFValue<double> AMFDoubleValue;
template<> inline eAmf AMFValue<std::nullptr_t>::GetValueType() { return eAmf::Null; };
template<> inline eAmf AMFValue<bool>::GetValueType() { return this->data ? eAmf::True : eAmf::False; };
template<> inline eAmf AMFValue<int32_t>::GetValueType() { return eAmf::Integer; };
template<> inline eAmf AMFValue<uint32_t>::GetValueType() { return eAmf::Integer; };
template<> inline eAmf AMFValue<std::string>::GetValueType() { return eAmf::String; };
template<> inline eAmf AMFValue<double>::GetValueType() { return eAmf::Double; };
/**
* The AMFArrayValue object holds 2 types of lists:
* An associative list where a key maps to a value
* A Dense list where elements are stored back to back
*
* Objects that are Registered are owned by this object
* and are not to be deleted by a caller.
*/
class AMFArrayValue : public AMFBaseValue {
typedef std::unordered_map<std::string, AMFBaseValue*> AMFAssociative;
typedef std::vector<AMFBaseValue*> AMFDense;
public:
eAmf GetValueType() override { return eAmf::Array; };
~AMFArrayValue() override {
for (auto valueToDelete : GetDense()) {
if (valueToDelete) {
delete valueToDelete;
valueToDelete = nullptr;
}
}
for (auto valueToDelete : GetAssociative()) {
if (valueToDelete.second) {
delete valueToDelete.second;
valueToDelete.second = nullptr;
}
}
};
/**
* Returns the Associative portion of the object
*/
inline AMFAssociative& GetAssociative() { return this->associative; };
/**
* Returns the dense portion of the object
*/
inline AMFDense& GetDense() { return this->dense; };
/**
* Inserts an AMFValue into the associative portion with the given key.
* If a duplicate is attempted to be inserted, it is ignored and the
* first value with that key is kept in the map.
*
* These objects are not to be deleted by the caller as they are owned by
* the AMFArray object which manages its own memory.
*
* @param key The key to associate with the value
* @param value The value to insert
*
* @return The inserted element if the type matched,
* or nullptr if a key existed and was not the same type
*/
template<typename ValueType>
std::pair<AMFValue<ValueType>*, bool> Insert(const std::string& key, ValueType value) {
auto element = associative.find(key);
AMFValue<ValueType>* val = nullptr;
bool found = true;
if (element == associative.end()) {
val = new AMFValue<ValueType>(value);
associative.insert(std::make_pair(key, val));
} else {
val = dynamic_cast<AMFValue<ValueType>*>(element->second);
found = false;
}
return std::make_pair(val, found);
};
// Associates an array with a string key
std::pair<AMFBaseValue*, bool> Insert(const std::string& key) {
auto element = associative.find(key);
AMFArrayValue* val = nullptr;
bool found = true;
if (element == associative.end()) {
val = new AMFArrayValue();
associative.insert(std::make_pair(key, val));
} else {
val = dynamic_cast<AMFArrayValue*>(element->second);
found = false;
}
return std::make_pair(val, found);
};
// Associates an array with an integer key
std::pair<AMFBaseValue*, bool> Insert(const uint32_t& index) {
AMFArrayValue* val = nullptr;
bool inserted = false;
if (index >= dense.size()) {
dense.resize(index + 1);
val = new AMFArrayValue();
dense.at(index) = val;
inserted = true;
}
return std::make_pair(dynamic_cast<AMFArrayValue*>(dense.at(index)), inserted);
};
/**
* @brief Inserts an AMFValue into the AMFArray key'd by index.
* Attempting to insert the same key to the same value twice overwrites
* the previous value with the new one.
*
* @param index The index to associate with the value
* @param value The value to insert
* @return The inserted element, or nullptr if the type did not match
* what was at the index.
*/
template<typename ValueType>
std::pair<AMFValue<ValueType>*, bool> Insert(const uint32_t& index, ValueType value) {
AMFValue<ValueType>* val = nullptr;
bool inserted = false;
if (index >= this->dense.size()) {
this->dense.resize(index + 1);
val = new AMFValue<ValueType>(value);
this->dense.at(index) = val;
inserted = true;
}
return std::make_pair(dynamic_cast<AMFValue<ValueType>*>(this->dense.at(index)), inserted);
};
/**
* Inserts an AMFValue into the associative portion with the given key.
* If a duplicate is attempted to be inserted, it replaces the original
*
* The inserted element is now owned by this object and is not to be deleted
*
* @param key The key to associate with the value
* @param value The value to insert
*/
void Insert(const std::string& key, AMFBaseValue* value) {
auto element = associative.find(key);
if (element != associative.end() && element->second) {
delete element->second;
element->second = value;
} else {
associative.insert(std::make_pair(key, value));
}
};
/**
* Inserts an AMFValue into the associative portion with the given index.
* If a duplicate is attempted to be inserted, it replaces the original
*
* The inserted element is now owned by this object and is not to be deleted
*
* @param key The key to associate with the value
* @param value The value to insert
*/
void Insert(const uint32_t index, AMFBaseValue* value) {
if (index < dense.size()) {
AMFDense::iterator itr = dense.begin() + index;
if (*itr) delete dense.at(index);
} else {
dense.resize(index + 1);
}
dense.at(index) = value;
};
/**
* Pushes an AMFValue into the back of the dense portion.
*
* These objects are not to be deleted by the caller as they are owned by
* the AMFArray object which manages its own memory.
*
* @param value The value to insert
*
* @return The inserted pointer, or nullptr should the key already be in use.
*/
template<typename ValueType>
inline AMFValue<ValueType>* Push(ValueType value) {
return Insert(this->dense.size(), value).first;
};
/**
* Removes the key from the associative portion
*
* The pointer removed is now no longer managed by this container
*
* @param key The key to remove from the associative portion
*/
void Remove(const std::string& key, bool deleteValue = true) {
AMFAssociative::iterator it = this->associative.find(key);
if (it != this->associative.end()) {
if (deleteValue) delete it->second;
this->associative.erase(it);
}
}
/**
* Pops the last element in the dense portion, deleting it in the process.
*/
void Remove(const uint32_t index) {
if (!this->dense.empty() && index < this->dense.size()) {
auto itr = this->dense.begin() + index;
if (*itr) delete (*itr);
this->dense.erase(itr);
}
}
void Pop() {
if (!this->dense.empty()) Remove(this->dense.size() - 1);
}
AMFArrayValue* GetArray(const std::string& key) {
AMFAssociative::const_iterator it = this->associative.find(key);
if (it != this->associative.end()) {
return dynamic_cast<AMFArrayValue*>(it->second);
}
return nullptr;
};
AMFArrayValue* GetArray(const uint32_t index) {
return index >= this->dense.size() ? nullptr : dynamic_cast<AMFArrayValue*>(this->dense.at(index));
};
inline AMFArrayValue* InsertArray(const std::string& key) {
return static_cast<AMFArrayValue*>(Insert(key).first);
};
inline AMFArrayValue* InsertArray(const uint32_t index) {
return static_cast<AMFArrayValue*>(Insert(index).first);
};
inline AMFArrayValue* PushArray() {
return static_cast<AMFArrayValue*>(Insert(this->dense.size()).first);
};
/**
* Gets an AMFValue by the key from the associative portion and converts it
* to the AmfValue template type. If the key did not exist, it is inserted.
*
* @tparam The target object type
* @param key The key to lookup
*
* @return The AMFValue
*/
template <typename AmfType>
AMFValue<AmfType>* Get(const std::string& key) const {
AMFAssociative::const_iterator it = this->associative.find(key);
return it != this->associative.end() ?
dynamic_cast<AMFValue<AmfType>*>(it->second) :
nullptr;
};
// Get from the array but dont cast it
AMFBaseValue* Get(const std::string& key) const {
AMFAssociative::const_iterator it = this->associative.find(key);
return it != this->associative.end() ? it->second : nullptr;
};
/**
* @brief Get an AMFValue object at a position in the dense portion.
* Gets an AMFValue by the index from the dense portion and converts it
* to the AmfValue template type. If the index did not exist, it is inserted.
*
* @tparam The target object type
* @param index The index to get
* @return The casted object, or nullptr.
*/
template <typename AmfType>
AMFValue<AmfType>* Get(uint32_t index) const {
return index < this->dense.size() ?
dynamic_cast<AMFValue<AmfType>*>(this->dense.at(index)) :
nullptr;
};
// Get from the dense but dont cast it
AMFBaseValue* Get(const uint32_t index) const {
return index < this->dense.size() ? this->dense.at(index) : nullptr;
};
private:
/**
* The associative portion. These values are key'd with strings to an AMFValue.
*/
AMFAssociative associative;
/**
* The dense portion. These AMFValue's are stored one after
* another with the most recent addition being at the back.
*/
AMFDense dense;
};
#endif //!__AMF3__H__

184
dCommon/AmfSerialize.cpp Normal file
View File

@@ -0,0 +1,184 @@
#include "AmfSerialize.h"
#include "Game.h"
#include "Logger.h"
// Writes an AMFValue pointer to a RakNet::BitStream
template<>
void RakNet::BitStream::Write<AMFBaseValue&>(AMFBaseValue& value) {
eAmf type = value.GetValueType();
this->Write(type);
switch (type) {
case eAmf::Integer: {
this->Write<AMFIntValue&>(*static_cast<AMFIntValue*>(&value));
break;
}
case eAmf::Double: {
this->Write<AMFDoubleValue&>(*static_cast<AMFDoubleValue*>(&value));
break;
}
case eAmf::String: {
this->Write<AMFStringValue&>(*static_cast<AMFStringValue*>(&value));
break;
}
case eAmf::Array: {
this->Write<AMFArrayValue&>(*static_cast<AMFArrayValue*>(&value));
break;
}
default: {
LOG("Encountered unwritable AMFType %i!", type);
}
case eAmf::Undefined:
case eAmf::Null:
case eAmf::False:
case eAmf::True:
case eAmf::Date:
case eAmf::Object:
case eAmf::XML:
case eAmf::XMLDoc:
case eAmf::ByteArray:
case eAmf::VectorInt:
case eAmf::VectorUInt:
case eAmf::VectorDouble:
case eAmf::VectorObject:
case eAmf::Dictionary:
break;
}
}
/**
* A private function to write an value to a RakNet::BitStream
* RakNet writes in the correct byte order - do not reverse this.
*/
void WriteUInt29(RakNet::BitStream* bs, uint32_t v) {
unsigned char b4 = static_cast<unsigned char>(v);
if (v < 0x00200000) {
b4 = b4 & 0x7F;
if (v > 0x7F) {
unsigned char b3;
v = v >> 7;
b3 = static_cast<unsigned char>(v) | 0x80;
if (v > 0x7F) {
unsigned char b2;
v = v >> 7;
b2 = static_cast<unsigned char>(v) | 0x80;
bs->Write(b2);
}
bs->Write(b3);
}
} else {
unsigned char b1;
unsigned char b2;
unsigned char b3;
v = v >> 8;
b3 = static_cast<unsigned char>(v) | 0x80;
v = v >> 7;
b2 = static_cast<unsigned char>(v) | 0x80;
v = v >> 7;
b1 = static_cast<unsigned char>(v) | 0x80;
bs->Write(b1);
bs->Write(b2);
bs->Write(b3);
}
bs->Write(b4);
}
/**
* Writes a flag number to a RakNet::BitStream
* RakNet writes in the correct byte order - do not reverse this.
*/
void WriteFlagNumber(RakNet::BitStream* bs, uint32_t v) {
v = (v << 1) | 0x01;
WriteUInt29(bs, v);
}
/**
* Writes an AMFString to a RakNet::BitStream
*
* RakNet writes in the correct byte order - do not reverse this.
*/
void WriteAMFString(RakNet::BitStream* bs, const std::string& str) {
WriteFlagNumber(bs, static_cast<uint32_t>(str.size()));
bs->Write(str.c_str(), static_cast<uint32_t>(str.size()));
}
/**
* Writes an U16 to a bitstream
*
* RakNet writes in the correct byte order - do not reverse this.
*/
void WriteAMFU16(RakNet::BitStream* bs, uint16_t value) {
bs->Write(value);
}
/**
* Writes an U32 to a bitstream
*
* RakNet writes in the correct byte order - do not reverse this.
*/
void WriteAMFU32(RakNet::BitStream* bs, uint32_t value) {
bs->Write(value);
}
/**
* Writes an U64 to a bitstream
*
* RakNet writes in the correct byte order - do not reverse this.
*/
void WriteAMFU64(RakNet::BitStream* bs, uint64_t value) {
bs->Write(value);
}
// Writes an AMFIntegerValue to BitStream
template<>
void RakNet::BitStream::Write<AMFIntValue&>(AMFIntValue& value) {
WriteUInt29(this, value.GetValue());
}
// Writes an AMFDoubleValue to BitStream
template<>
void RakNet::BitStream::Write<AMFDoubleValue&>(AMFDoubleValue& value) {
double d = value.GetValue();
WriteAMFU64(this, *reinterpret_cast<uint64_t*>(&d));
}
// Writes an AMFStringValue to BitStream
template<>
void RakNet::BitStream::Write<AMFStringValue&>(AMFStringValue& value) {
WriteAMFString(this, value.GetValue());
}
// Writes an AMFArrayValue to BitStream
template<>
void RakNet::BitStream::Write<AMFArrayValue&>(AMFArrayValue& value) {
uint32_t denseSize = value.GetDense().size();
WriteFlagNumber(this, denseSize);
auto it = value.GetAssociative().begin();
auto end = value.GetAssociative().end();
while (it != end) {
WriteAMFString(this, it->first);
this->Write<AMFBaseValue&>(*it->second);
it++;
}
this->Write(eAmf::Null);
if (denseSize > 0) {
auto it2 = value.GetDense().begin();
auto end2 = value.GetDense().end();
while (it2 != end2) {
this->Write<AMFBaseValue&>(**it2);
it2++;
}
}
}

50
dCommon/AmfSerialize.h Normal file
View File

@@ -0,0 +1,50 @@
#pragma once
// Custom Classes
#include "Amf3.h"
// RakNet
#include "BitStream.h"
/*!
\file AmfSerialize.h
\brief A class that implements native writing of AMF values to RakNet::BitStream
*/
// We are using the RakNet namespace
namespace RakNet {
//! Writes an AMFValue pointer to a RakNet::BitStream
/*!
\param value The value to write
*/
template <>
void RakNet::BitStream::Write<AMFBaseValue&>(AMFBaseValue& value);
//! Writes an AMFIntegerValue to a RakNet::BitStream
/*!
\param value The value to write
*/
template <>
void RakNet::BitStream::Write<AMFIntValue&>(AMFIntValue& value);
//! Writes an AMFDoubleValue to a RakNet::BitStream
/*!
\param value The value to write
*/
template <>
void RakNet::BitStream::Write<AMFDoubleValue&>(AMFDoubleValue& value);
//! Writes an AMFStringValue to a RakNet::BitStream
/*!
\param value The value to write
*/
template <>
void RakNet::BitStream::Write<AMFStringValue&>(AMFStringValue& value);
//! Writes an AMFArrayValue to a RakNet::BitStream
/*!
\param value The value to write
*/
template <>
void RakNet::BitStream::Write<AMFArrayValue&>(AMFArrayValue& value);
} // namespace RakNet

View File

@@ -1,16 +1,8 @@
#include "BinaryIO.h"
#include <string>
void BinaryIO::WriteString(const std::string& stringToWrite, std::ofstream& outstream) {
//BinaryWrite(outstream, uint32_t(stringToWrite.length()));
for (size_t i = 0; i < size_t(stringToWrite.length()); ++i) {
BinaryIO::BinaryWrite(outstream, stringToWrite[i]);
}
}
//For reading null-terminated strings
std::string BinaryIO::ReadString(std::ifstream & instream) {
std::string BinaryIO::ReadString(std::istream& instream) {
std::string toReturn;
char buffer;
@@ -23,36 +15,3 @@ std::string BinaryIO::ReadString(std::ifstream & instream) {
return toReturn;
}
//For reading strings of a specific size
std::string BinaryIO::ReadString(std::ifstream& instream, size_t size) {
std::string toReturn;
char buffer;
for (size_t i = 0; i < size; ++i) {
BinaryIO::BinaryRead(instream, buffer);
toReturn += buffer;
}
return toReturn;
}
std::string BinaryIO::ReadWString(std::ifstream & instream) {
size_t size;
BinaryRead(instream, size);
//toReturn.resize(size);
std::string test;
unsigned char buf;
for (size_t i = 0; i < size; ++i) {
//instream.ignore(1);
BinaryRead(instream, buf);
test += buf;
}
//printf("%s\n", test.c_str());
//instream.read((char*)&toReturn[0], size * 2);
//std::string str(toReturn.begin(), toReturn.end());
return test;
}

View File

@@ -1,28 +1,74 @@
#pragma once
#ifndef __BINARYIO__H__
#define __BINARYIO__H__
#include <iostream>
#include <fstream>
#include <string>
#include "Game.h"
#include "Logger.h"
namespace BinaryIO {
template<typename T>
std::ostream& BinaryWrite(std::ostream& stream, const T& value) {
return stream.write(reinterpret_cast<const char*>(&value), sizeof(T));
}
template<typename T>
std::istream & BinaryRead(std::istream& stream, T& value) {
if (!stream.good())
printf("bla");
std::istream& BinaryRead(std::istream& stream, T& value) {
if (!stream.good()) throw std::runtime_error("Failed to read from istream.");
return stream.read(reinterpret_cast<char*>(&value), sizeof(T));
}
void WriteString(const std::string& stringToWrite, std::ofstream& outstream);
std::string ReadString(std::ifstream & instream);
std::string ReadString(std::ifstream& instream, size_t size);
std::string ReadWString(std::ifstream& instream);
enum class ReadType : int8_t {
WideString = 0,
String = 1,
};
template<typename SizeType>
inline void ReadString(std::istream& stream, std::u16string& value) {
static_assert(std::is_integral<SizeType>::value, "SizeType must be an integral type.");
SizeType size;
BinaryRead(stream, size);
if (!stream.good()) throw std::runtime_error("Failed to read from istream.");
value.resize(size);
stream.read(reinterpret_cast<char*>(value.data()), size * sizeof(uint16_t));
}
template<typename SizeType>
inline void ReadString(std::istream& stream, std::string& value, ReadType readType) {
static_assert(std::is_integral<SizeType>::value, "SizeType must be an integral type.");
SizeType size;
BinaryRead(stream, size);
if (!stream.good()) throw std::runtime_error("Failed to read from istream.");
value.resize(size);
if (readType == ReadType::WideString) {
uint16_t wideChar;
// Faster to do this than to read a u16string and convert it to a string since we only go through allocator once
for (SizeType i = 0; i < size; ++i) {
BinaryRead(stream, wideChar);
value[i] = static_cast<char>(wideChar);
}
} else {
stream.read(value.data(), size);
}
}
std::string ReadString(std::istream& instream);
inline bool DoesFileExist(const std::string& name) {
std::ifstream f(name.c_str());
return f.good();
}
}
#endif //!__BINARYIO__H__

View File

@@ -0,0 +1,71 @@
#include <filesystem>
#include <string>
#include "BinaryPathFinder.h"
#include "dPlatforms.h"
#if defined(DARKFLAME_PLATFORM_WIN32)
#include <Windows.h>
#elif defined(DARKFLAME_PLATFORM_MACOS) || defined(DARKFLAME_PLATFORM_IOS)
#include <mach-o/dyld.h>
#elif defined(DARKFLAME_PLATFORM_FREEBSD)
#include <sys/types.h>
#include <sys/sysctl.h>
#include <stdlib.h>
#endif
std::filesystem::path BinaryPathFinder::binaryDir;
std::filesystem::path BinaryPathFinder::GetBinaryDir() {
if (!binaryDir.empty()) {
return binaryDir;
}
std::string pathStr;
// Derived from boost::dll::program_location, licensed under the Boost Software License: http://www.boost.org/LICENSE_1_0.txt
#if defined(DARKFLAME_PLATFORM_WIN32)
char path[MAX_PATH];
GetModuleFileName(NULL, path, MAX_PATH);
pathStr = std::string(path);
#elif defined(DARKFLAME_PLATFORM_MACOS) || defined(DARKFLAME_PLATFORM_IOS)
char path[1024];
uint32_t size = sizeof(path);
if (_NSGetExecutablePath(path, &size) == 0) {
pathStr = std::string(path);
} else {
// The filepath size is greater than our initial buffer size, so try again with the size
// that _NSGetExecutablePath told us it actually is
char *p = new char[size];
if (_NSGetExecutablePath(p, &size) != 0) {
throw std::runtime_error("Failed to get binary path from _NSGetExecutablePath");
}
pathStr = std::string(p);
delete[] p;
}
#elif defined(DARKFLAME_PLATFORM_FREEBSD)
int mib[4];
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PATHNAME;
mib[3] = -1;
char buf[10240];
size_t cb = sizeof(buf);
sysctl(mib, 4, buf, &cb, NULL, 0);
pathStr = std::string(buf);
#else // DARKFLAME_PLATFORM_LINUX || DARKFLAME_PLATFORM_UNIX || DARKFLAME_PLATFORM_ANDROID
pathStr = std::filesystem::read_symlink("/proc/self/exe");
#endif
// Some methods like _NSGetExecutablePath could return a symlink
// Either way, we need to get the parent path because we want the directory, not the binary itself
// We also ensure that it is an absolute path so that it is valid if we need to construct a path
// to exucute on unix systems (eg sudo BinaryPathFinder::GetBinaryDir() / WorldServer)
if (std::filesystem::is_symlink(pathStr)) {
binaryDir = std::filesystem::absolute(std::filesystem::read_symlink(pathStr).parent_path());
} else {
binaryDir = std::filesystem::absolute(std::filesystem::path(pathStr).parent_path());
}
return binaryDir;
}

View File

@@ -0,0 +1,15 @@
#pragma once
#ifndef __BINARYPATHFINDER__H__
#define __BINARYPATHFINDER__H__
#include <filesystem>
class BinaryPathFinder {
private:
static std::filesystem::path binaryDir;
public:
static std::filesystem::path GetBinaryDir();
};
#endif //!__BINARYPATHFINDER__H__

11
dCommon/Brick.h Normal file
View File

@@ -0,0 +1,11 @@
#ifndef __BRICK__H__
#define __BRICK__H__
#include <cstdint>
struct Brick {
uint32_t designerID;
uint32_t materialID;
};
#endif //!__BRICK__H__

154
dCommon/BrickByBrickFix.cpp Normal file
View File

@@ -0,0 +1,154 @@
#include "BrickByBrickFix.h"
#include <memory>
#include <iostream>
#include <sstream>
#include "tinyxml2.h"
#include "Database.h"
#include "Game.h"
#include "ZCompression.h"
#include "Logger.h"
//! Forward declarations
void WriteSd0Magic(char* input, uint32_t chunkSize);
bool CheckSd0Magic(std::istream& streamToCheck);
/**
* @brief Truncates all models with broken data from the database.
*
* @return The number of models deleted
*/
uint32_t BrickByBrickFix::TruncateBrokenBrickByBrickXml() {
uint32_t modelsTruncated{};
auto modelsToTruncate = Database::Get()->GetAllUgcModels();
bool previousCommitValue = Database::Get()->GetAutoCommit();
Database::Get()->SetAutoCommit(false);
for (auto& model : modelsToTruncate) {
std::string completeUncompressedModel{};
uint32_t chunkCount{};
// Check that header is sd0 by checking for the sd0 magic.
if (CheckSd0Magic(model.lxfmlData)) {
while (true) {
uint32_t chunkSize{};
model.lxfmlData.read(reinterpret_cast<char*>(&chunkSize), sizeof(uint32_t)); // Extract chunk size from istream
// Check if good here since if at the end of an sd0 file, this will have eof flagged.
if (!model.lxfmlData.good()) break;
std::unique_ptr<uint8_t[]> compressedChunk(new uint8_t[chunkSize]);
for (uint32_t i = 0; i < chunkSize; i++) {
compressedChunk[i] = model.lxfmlData.get();
}
// Ignore the valgrind warning about uninitialized values. These are discarded later when we know the actual uncompressed size.
std::unique_ptr<uint8_t[]> uncompressedChunk(new uint8_t[ZCompression::MAX_SD0_CHUNK_SIZE]);
int32_t err{};
int32_t actualUncompressedSize = ZCompression::Decompress(
compressedChunk.get(), chunkSize, uncompressedChunk.get(), ZCompression::MAX_SD0_CHUNK_SIZE, err);
if (actualUncompressedSize != -1) {
uint32_t previousSize = completeUncompressedModel.size();
completeUncompressedModel.append(reinterpret_cast<char*>(uncompressedChunk.get()));
completeUncompressedModel.resize(previousSize + actualUncompressedSize);
} else {
LOG("Failed to inflate chunk %i for model %llu. Error: %i", chunkCount, model.id, err);
break;
}
chunkCount++;
}
std::unique_ptr<tinyxml2::XMLDocument> document = std::make_unique<tinyxml2::XMLDocument>();
if (!document) {
LOG("Failed to initialize tinyxml document. Aborting.");
return 0;
}
if (!(document->Parse(completeUncompressedModel.c_str(), completeUncompressedModel.size()) == tinyxml2::XML_SUCCESS)) {
if (completeUncompressedModel.find(
"</LXFML>",
completeUncompressedModel.length() >= 15 ? completeUncompressedModel.length() - 15 : 0) == std::string::npos
) {
LOG("Brick-by-brick model %llu will be deleted!", model.id);
Database::Get()->DeleteUgcModelData(model.id);
modelsTruncated++;
}
}
} else {
LOG("Brick-by-brick model %llu will be deleted!", model.id);
Database::Get()->DeleteUgcModelData(model.id);
modelsTruncated++;
}
}
Database::Get()->Commit();
Database::Get()->SetAutoCommit(previousCommitValue);
return modelsTruncated;
}
/**
* @brief Updates all current models in the database to have the Segmented Data 0 (SD0) format.
* Any models that do not start with zlib and best compression magic will not be updated.
*
* @return The number of models updated to SD0
*/
uint32_t BrickByBrickFix::UpdateBrickByBrickModelsToSd0() {
uint32_t updatedModels = 0;
auto modelsToUpdate = Database::Get()->GetAllUgcModels();
auto previousAutoCommitState = Database::Get()->GetAutoCommit();
Database::Get()->SetAutoCommit(false);
for (auto& model : modelsToUpdate) {
// Check if the stored blob starts with zlib magic (0x78 0xDA - best compression of zlib)
// If it does, convert it to sd0.
if (model.lxfmlData.get() == 0x78 && model.lxfmlData.get() == 0xDA) {
// Get and save size of zlib compressed chunk.
model.lxfmlData.seekg(0, std::ios::end);
uint32_t oldLxfmlSize = static_cast<uint32_t>(model.lxfmlData.tellg());
model.lxfmlData.seekg(0);
// Allocate 9 extra bytes. 5 for sd0 magic, 4 for the only zlib compressed size.
uint32_t oldLxfmlSizeWithHeader = oldLxfmlSize + 9;
std::unique_ptr<char[]> sd0ConvertedModel(new char[oldLxfmlSizeWithHeader]);
WriteSd0Magic(sd0ConvertedModel.get(), oldLxfmlSize);
for (uint32_t i = 9; i < oldLxfmlSizeWithHeader; i++) {
sd0ConvertedModel.get()[i] = model.lxfmlData.get();
}
std::string outputString(sd0ConvertedModel.get(), oldLxfmlSizeWithHeader);
std::istringstream outputStringStream(outputString);
try {
Database::Get()->UpdateUgcModelData(model.id, outputStringStream);
LOG("Updated model %i to sd0", model.id);
updatedModels++;
} catch (sql::SQLException exception) {
LOG("Failed to update model %i. This model should be inspected manually to see why."
"The database error is %s", model.id, exception.what());
}
}
}
Database::Get()->Commit();
Database::Get()->SetAutoCommit(previousAutoCommitState);
return updatedModels;
}
/**
* @brief Writes sd0 magic at the front of a char*
*
* @param input the char* to write at the front of
* @param chunkSize The size of the first chunk to write the size of
*/
void WriteSd0Magic(char* input, uint32_t chunkSize) {
input[0] = 's';
input[1] = 'd';
input[2] = '0';
input[3] = 0x01;
input[4] = 0xFF;
*reinterpret_cast<uint32_t*>(input + 5) = chunkSize; // Write the integer to the character array
}
bool CheckSd0Magic(std::istream& streamToCheck) {
return streamToCheck.get() == 's' && streamToCheck.get() == 'd' && streamToCheck.get() == '0' && streamToCheck.get() == 0x01 && streamToCheck.get() == 0xFF;
}

20
dCommon/BrickByBrickFix.h Normal file
View File

@@ -0,0 +1,20 @@
#pragma once
#include <cstdint>
namespace BrickByBrickFix {
/**
* @brief Deletes all broken BrickByBrick models that have invalid XML
*
* @return The number of BrickByBrick models that were truncated
*/
uint32_t TruncateBrokenBrickByBrickXml();
/**
* @brief Updates all BrickByBrick models in the database to be
* in the sd0 format as opposed to a zlib compressed format.
*
* @return The number of BrickByBrick models that were updated
*/
uint32_t UpdateBrickByBrickModelsToSd0();
};

64
dCommon/CMakeLists.txt Normal file
View File

@@ -0,0 +1,64 @@
set(DCOMMON_SOURCES
"AMFDeserialize.cpp"
"AmfSerialize.cpp"
"BinaryIO.cpp"
"dConfig.cpp"
"Diagnostics.cpp"
"Logger.cpp"
"Game.cpp"
"GeneralUtils.cpp"
"LDFFormat.cpp"
"MD5.cpp"
"Metrics.cpp"
"NiPoint3.cpp"
"NiQuaternion.cpp"
"SHA512.cpp"
"Demangler.cpp"
"ZCompression.cpp"
"BrickByBrickFix.cpp"
"BinaryPathFinder.cpp"
"FdbToSqlite.cpp"
)
add_subdirectory(dClient)
foreach(file ${DCOMMON_DCLIENT_SOURCES})
set(DCOMMON_SOURCES ${DCOMMON_SOURCES} "dClient/${file}")
endforeach()
include_directories(${PROJECT_SOURCE_DIR}/dCommon/)
add_library(dCommon STATIC ${DCOMMON_SOURCES})
target_link_libraries(dCommon bcrypt dDatabase tinyxml2)
if (UNIX)
find_package(ZLIB REQUIRED)
elseif (WIN32)
include(FetchContent)
# TODO Keep an eye on the zlib repository for an update to disable testing. Don't forget to update CMakePresets
FetchContent_Declare(
zlib
URL https://github.com/madler/zlib/archive/refs/tags/v1.2.11.zip
URL_HASH MD5=9d6a627693163bbbf3f26403a3a0b0b1
)
# Disable warning about no project version.
set(CMAKE_POLICY_DEFAULT_CMP0048 NEW)
# Disable warning about the minimum version of cmake used for bcrypt being deprecated in the future
set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(zlib)
set(ZLIB_INCLUDE_DIRS ${zlib_SOURCE_DIR} ${zlib_BINARY_DIR})
set_target_properties(zlib PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${ZLIB_INCLUDE_DIRS}")
add_library(ZLIB::ZLIB ALIAS zlib)
else ()
message(
FATAL_ERROR
"This platform does not have a way to use zlib.\nCreate an issue on GitHub with your build system so it can be configured."
)
endif ()
target_link_libraries(dCommon ZLIB::ZLIB)

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,59 +1,62 @@
#include "Diagnostics.h"
#include "Game.h"
#include "Logger.h"
// If we're on Win32, we'll include our minidump writer
#ifdef _WIN32
#include <Dbghelp.h>
#include <Windows.h>
#include <Dbghelp.h>
#include "Game.h"
#include "dLogger.h"
#include "Logger.h"
void make_minidump(EXCEPTION_POINTERS* e) {
auto hDbgHelp = LoadLibraryA("dbghelp");
if (hDbgHelp == nullptr)
return;
auto pMiniDumpWriteDump = (decltype(&MiniDumpWriteDump))GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
if (pMiniDumpWriteDump == nullptr)
return;
auto hDbgHelp = LoadLibraryA("dbghelp");
if (hDbgHelp == nullptr)
return;
auto pMiniDumpWriteDump = (decltype(&MiniDumpWriteDump))GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
if (pMiniDumpWriteDump == nullptr)
return;
char name[MAX_PATH];
{
auto nameEnd = name + GetModuleFileNameA(GetModuleHandleA(0), name, MAX_PATH);
SYSTEMTIME t;
GetSystemTime(&t);
wsprintfA(nameEnd - strlen(".exe"),
"_%4d%02d%02d_%02d%02d%02d.dmp",
t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond);
}
char name[MAX_PATH];
{
auto nameEnd = name + GetModuleFileNameA(GetModuleHandleA(0), name, MAX_PATH);
SYSTEMTIME t;
GetSystemTime(&t);
wsprintfA(nameEnd - strlen(".exe"),
"_%4d%02d%02d_%02d%02d%02d.dmp",
t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond);
}
LOG("Creating crash dump %s", name);
auto hFile = CreateFileA(name, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile == INVALID_HANDLE_VALUE)
return;
auto hFile = CreateFileA(name, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile == INVALID_HANDLE_VALUE)
return;
MINIDUMP_EXCEPTION_INFORMATION exceptionInfo;
exceptionInfo.ThreadId = GetCurrentThreadId();
exceptionInfo.ExceptionPointers = e;
exceptionInfo.ClientPointers = FALSE;
MINIDUMP_EXCEPTION_INFORMATION exceptionInfo;
exceptionInfo.ThreadId = GetCurrentThreadId();
exceptionInfo.ExceptionPointers = e;
exceptionInfo.ClientPointers = FALSE;
auto dumped = pMiniDumpWriteDump(
GetCurrentProcess(),
GetCurrentProcessId(),
hFile,
MINIDUMP_TYPE(MiniDumpWithIndirectlyReferencedMemory | MiniDumpScanMemory),
e ? &exceptionInfo : nullptr,
nullptr,
nullptr);
auto dumped = pMiniDumpWriteDump(
GetCurrentProcess(),
GetCurrentProcessId(),
hFile,
MINIDUMP_TYPE(MiniDumpWithIndirectlyReferencedMemory | MiniDumpScanMemory),
e ? &exceptionInfo : nullptr,
nullptr,
nullptr);
CloseHandle(hFile);
CloseHandle(hFile);
return;
return;
}
LONG CALLBACK unhandled_handler(EXCEPTION_POINTERS* e) {
make_minidump(e);
if (Game::logger)
Game::logger->Flush(); // Flush our log if we have one, before exiting.
return EXCEPTION_CONTINUE_SEARCH;
make_minidump(e);
if (Game::logger)
Game::logger->Flush(); // Flush our log if we have one, before exiting.
return EXCEPTION_CONTINUE_SEARCH;
}
#endif
@@ -68,152 +71,161 @@ LONG CALLBACK unhandled_handler(EXCEPTION_POINTERS* e) {
#include <cstring>
#include <exception>
#if defined(__include_backtrace__)
#if defined(INCLUDE_BACKTRACE)
#include <backtrace.h>
#include <backtrace-supported.h>
struct bt_ctx {
struct backtrace_state* state;
int error;
struct backtrace_state* state;
int error;
};
static inline void Bt(struct backtrace_state* state) {
std::string fileName = Diagnostics::GetOutDirectory() + "crash_" + Diagnostics::GetProcessName() + "_" + std::to_string(getpid()) + ".log";
FILE* file = fopen(fileName.c_str(), "w+");
if (file != nullptr) {
backtrace_print(state, 2, file);
fclose(file);
}
std::string fileName = Diagnostics::GetOutDirectory() + "crash_" + Diagnostics::GetProcessName() + "_" + std::to_string(getpid()) + ".log";
LOG("backtrace is enabled, crash dump located at %s", fileName.c_str());
FILE* file = fopen(fileName.c_str(), "w+");
if (file != nullptr) {
backtrace_print(state, 2, file);
fclose(file);
}
backtrace_print(state, 2, stdout);
backtrace_print(state, 2, stdout);
}
static void ErrorCallback(void* data, const char* msg, int errnum) {
auto* ctx = (struct bt_ctx*)data;
fprintf(stderr, "ERROR: %s (%d)", msg, errnum);
ctx->error = 1;
auto* ctx = (struct bt_ctx*)data;
fprintf(stderr, "ERROR: %s (%d)", msg, errnum);
ctx->error = 1;
std::string fileName = Diagnostics::GetOutDirectory() + "crash_" + Diagnostics::GetProcessName() + "_" + std::to_string(getpid()) + ".log";
FILE* file = fopen(fileName.c_str(), "w+");
if (file != nullptr) {
fprintf(file, "ERROR: %s (%d)", msg, errnum);
fclose(file);
}
std::string fileName = Diagnostics::GetOutDirectory() + "crash_" + Diagnostics::GetProcessName() + "_" + std::to_string(getpid()) + ".log";
FILE* file = fopen(fileName.c_str(), "w+");
if (file != nullptr) {
fprintf(file, "ERROR: %s (%d)", msg, errnum);
fclose(file);
}
}
#endif
#include "Type.h"
#include "Demangler.h"
void GenerateDump() {
std::string cmd = "sudo gcore " + std::to_string(getpid());
system(cmd.c_str());
std::string cmd = "sudo gcore " + std::to_string(getpid());
int ret = system(cmd.c_str()); // Saving a return just to prevent warning
}
void CatchUnhandled(int sig) {
#ifndef __include_backtrace__
std::exception_ptr eptr = std::current_exception();
try {
if (eptr) std::rethrow_exception(eptr);
} catch(const std::exception& e) {
LOG("Caught exception: '%s'", e.what());
}
if (Diagnostics::GetProduceMemoryDump()) {
GenerateDump();
}
#ifndef INCLUDE_BACKTRACE
void* array[10];
size_t size;
std::string fileName = Diagnostics::GetOutDirectory() + "crash_" + Diagnostics::GetProcessName() + "_" + std::to_string(getpid()) + ".log";
LOG("Encountered signal %i, creating crash dump %s", sig, fileName.c_str());
if (Diagnostics::GetProduceMemoryDump()) {
GenerateDump();
}
constexpr uint8_t MaxStackTrace = 32;
void* array[MaxStackTrace];
size_t size;
// get void*'s for all entries on the stack
size = backtrace(array, 10);
// get void*'s for all entries on the stack
size = backtrace(array, MaxStackTrace);
printf("Fatal error %i\nStacktrace:\n", sig);
#if defined(__GNUG__) and defined(__dynamic)
# if defined(__GNUG__)
// Loop through the returned addresses, and get the symbols to be demangled
char** strings = backtrace_symbols(array, size);
// Loop through the returned addresses, and get the symbols to be demangled
char** strings = backtrace_symbols(array, size);
// Print the stack trace
for (size_t i = 0; i < size; i++) {
// Take a string like './WorldServer(_ZN19SlashCommandHandler17HandleChatCommandERKSbIDsSt11char_traitsIDsESaIDsEEP6EntityRK13SystemAddress+0x6187) [0x55869c44ecf7]' and extract the function name
std::string functionName = strings[i];
std::string::size_type start = functionName.find('(');
std::string::size_type end = functionName.find('+');
if (start != std::string::npos && end != std::string::npos) {
std::string demangled = functionName.substr(start + 1, end - start - 1);
FILE* file = fopen(fileName.c_str(), "w+");
if (file != NULL) {
fprintf(file, "Error: signal %d:\n", sig);
}
// Print the stack trace
for (size_t i = 0; i < size; i++) {
// 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::size_type start = functionName.find('(');
std::string::size_type end = functionName.find('+');
if (start != std::string::npos && end != std::string::npos) {
std::string demangled = functionName.substr(start + 1, end - start - 1);
demangled = demangle(functionName.c_str());
demangled = Demangler::Demangle(demangled.c_str());
if (demangled.empty()) {
printf("[%02d] %s\n", i, demangled.c_str());
} else {
printf("[%02d] %s\n", i, functionName.c_str());
}
} else {
printf("[%02d] %s\n", i, functionName.c_str());
}
}
#else
backtrace_symbols_fd(array, size, STDOUT_FILENO);
#endif
// If the demangled string is not empty, then we can replace the mangled string with the demangled one
if (!demangled.empty()) {
demangled.push_back('(');
demangled += functionName.substr(end);
functionName = demangled;
}
}
std::string fileName = Diagnostics::GetOutDirectory() + "crash_" + Diagnostics::GetProcessName() + "_" + std::to_string(getpid()) + ".log";
FILE* file = fopen(fileName.c_str(), "w+");
if (file != NULL) {
// print out all the frames to stderr
fprintf(file, "Error: signal %d:\n", sig);
backtrace_symbols_fd(array, size, fileno(file));
fclose(file);
}
LOG("[%02zu] %s", i, functionName.c_str());
if (file != NULL) {
fprintf(file, "[%02zu] %s\n", i, functionName.c_str());
}
}
# else // defined(__GNUG__)
backtrace_symbols_fd(array, size, STDOUT_FILENO);
# endif // defined(__GNUG__)
#else
#else // INCLUDE_BACKTRACE
struct backtrace_state* state = backtrace_create_state(
Diagnostics::GetProcessFileName().c_str(),
BACKTRACE_SUPPORTS_THREADS,
ErrorCallback,
nullptr);
struct backtrace_state* state = backtrace_create_state(
Diagnostics::GetProcessFileName().c_str(),
BACKTRACE_SUPPORTS_THREADS,
ErrorCallback,
nullptr);
struct bt_ctx ctx = {state, 0};
Bt(state);
struct bt_ctx ctx = { state, 0 };
Bt(state);
#endif
#endif // INCLUDE_BACKTRACE
exit(EXIT_FAILURE);
exit(EXIT_FAILURE);
}
void CritErrHdlr(int sig_num, siginfo_t* info, void* ucontext) {
CatchUnhandled(sig_num);
CatchUnhandled(sig_num);
}
void OnTerminate() {
CatchUnhandled(-1);
CatchUnhandled(-1);
}
void MakeBacktrace() {
struct sigaction sigact;
struct sigaction sigact;
sigact.sa_sigaction = CritErrHdlr;
sigact.sa_flags = SA_RESTART | SA_SIGINFO;
sigact.sa_sigaction = CritErrHdlr;
sigact.sa_flags = SA_RESTART | SA_SIGINFO;
if (sigaction(SIGSEGV, &sigact, (struct sigaction*)nullptr) != 0 ||
sigaction(SIGFPE, &sigact, (struct sigaction*)nullptr) != 0 ||
sigaction(SIGABRT, &sigact, (struct sigaction*)nullptr) != 0 ||
sigaction(SIGILL, &sigact, (struct sigaction*)nullptr) != 0) {
fprintf(stderr, "error setting signal handler for %d (%s)\n",
SIGSEGV,
strsignal(SIGSEGV));
if (sigaction(SIGSEGV, &sigact, nullptr) != 0 ||
sigaction(SIGFPE, &sigact, nullptr) != 0 ||
sigaction(SIGABRT, &sigact, nullptr) != 0 ||
sigaction(SIGILL, &sigact, nullptr) != 0) {
fprintf(stderr, "error setting signal handler for %d (%s)\n",
SIGSEGV,
strsignal(SIGSEGV));
exit(EXIT_FAILURE);
}
exit(EXIT_FAILURE);
}
std::set_terminate(OnTerminate);
std::set_terminate(OnTerminate);
}
#endif
void Diagnostics::Initialize() {
#ifdef _WIN32
SetUnhandledExceptionFilter(unhandled_handler);
SetUnhandledExceptionFilter(unhandled_handler);
#elif defined(__linux__) //&& !defined(__clang__)
MakeBacktrace();
MakeBacktrace();
#else
fprintf(stderr, "Diagnostics not supported on this platform.\n");
fprintf(stderr, "Diagnostics not supported on this platform.\n");
#endif
}
@@ -223,33 +235,33 @@ std::string Diagnostics::m_OutDirectory{};
bool Diagnostics::m_ProduceMemoryDump{};
void Diagnostics::SetProcessName(const std::string& name) {
m_ProcessName = name;
m_ProcessName = name;
}
void Diagnostics::SetProcessFileName(const std::string& name) {
m_ProcessFileName = name;
m_ProcessFileName = name;
}
void Diagnostics::SetOutDirectory(const std::string& path) {
m_OutDirectory = path;
m_OutDirectory = path;
}
void Diagnostics::SetProduceMemoryDump(bool value) {
m_ProduceMemoryDump = value;
m_ProduceMemoryDump = value;
}
const std::string& Diagnostics::GetProcessName() {
return m_ProcessName;
return m_ProcessName;
}
const std::string& Diagnostics::GetProcessFileName() {
return m_ProcessFileName;
return m_ProcessFileName;
}
const std::string& Diagnostics::GetOutDirectory() {
return m_OutDirectory;
return m_OutDirectory;
}
bool Diagnostics::GetProduceMemoryDump() {
return m_ProduceMemoryDump;
return m_ProduceMemoryDump;
}

View File

@@ -5,27 +5,27 @@
class Diagnostics
{
public:
static void Initialize();
static void Initialize();
static void SetProcessName(const std::string& name);
static void SetProcessName(const std::string& name);
static void SetProcessFileName(const std::string& name);
static void SetProcessFileName(const std::string& name);
static void SetOutDirectory(const std::string& path);
static void SetOutDirectory(const std::string& path);
static void SetProduceMemoryDump(bool value);
static void SetProduceMemoryDump(bool value);
static const std::string& GetProcessName();
static const std::string& GetProcessName();
static const std::string& GetProcessFileName();
static const std::string& GetProcessFileName();
static const std::string& GetOutDirectory();
static const std::string& GetOutDirectory();
static bool GetProduceMemoryDump();
static bool GetProduceMemoryDump();
private:
static std::string m_ProcessName;
static std::string m_ProcessFileName;
static std::string m_OutDirectory;
static bool m_ProduceMemoryDump;
static std::string m_ProcessName;
static std::string m_ProcessFileName;
static std::string m_OutDirectory;
static bool m_ProduceMemoryDump;
};

12
dCommon/DluAssert.h Normal file
View File

@@ -0,0 +1,12 @@
#ifndef __DLUASSERT__H__
#define __DLUASSERT__H__
#include <assert.h>
#ifdef _DEBUG
# define DluAssert(expression) assert(expression)
#else
# define DluAssert(expression)
#endif
#endif //!__DLUASSERT__H__

245
dCommon/FdbToSqlite.cpp Normal file
View File

@@ -0,0 +1,245 @@
#include "FdbToSqlite.h"
#include <map>
#include <fstream>
#include <cassert>
#include <iomanip>
#include "BinaryIO.h"
#include "CDClientDatabase.h"
#include "GeneralUtils.h"
#include "Game.h"
#include "Logger.h"
#include "AssetManager.h"
#include "eSqliteDataType.h"
std::map<eSqliteDataType, std::string> FdbToSqlite::Convert::m_SqliteType = {
{ eSqliteDataType::NONE, "none"},
{ eSqliteDataType::INT32, "int32"},
{ eSqliteDataType::REAL, "real"},
{ eSqliteDataType::TEXT_4, "text_4"},
{ eSqliteDataType::INT_BOOL, "int_bool"},
{ eSqliteDataType::INT64, "int64"},
{ eSqliteDataType::TEXT_8, "text_8"}
};
FdbToSqlite::Convert::Convert(std::string binaryOutPath) {
this->m_BinaryOutPath = binaryOutPath;
}
bool FdbToSqlite::Convert::ConvertDatabase(AssetStream& buffer) {
if (m_ConversionStarted) return false;
this->m_ConversionStarted = true;
try {
CDClientDatabase::Connect(m_BinaryOutPath + "/CDServer.sqlite");
CDClientDatabase::ExecuteQuery("BEGIN TRANSACTION;");
int32_t numberOfTables = ReadInt32(buffer);
ReadTables(numberOfTables, buffer);
CDClientDatabase::ExecuteQuery("COMMIT;");
} catch (CppSQLite3Exception& e) {
LOG("Encountered error %s converting FDB to SQLite", e.errorMessage());
return false;
}
return true;
}
int32_t FdbToSqlite::Convert::ReadInt32(std::istream& cdClientBuffer) {
int32_t nextInt{};
BinaryIO::BinaryRead(cdClientBuffer, nextInt);
return nextInt;
}
int64_t FdbToSqlite::Convert::ReadInt64(std::istream& cdClientBuffer) {
int32_t prevPosition = SeekPointer(cdClientBuffer);
int64_t value{};
BinaryIO::BinaryRead(cdClientBuffer, value);
cdClientBuffer.seekg(prevPosition);
return value;
}
std::string FdbToSqlite::Convert::ReadString(std::istream& cdClientBuffer) {
int32_t prevPosition = SeekPointer(cdClientBuffer);
auto readString = BinaryIO::ReadString(cdClientBuffer);
cdClientBuffer.seekg(prevPosition);
return readString;
}
int32_t FdbToSqlite::Convert::SeekPointer(std::istream& cdClientBuffer) {
int32_t position{};
BinaryIO::BinaryRead(cdClientBuffer, position);
int32_t prevPosition = cdClientBuffer.tellg();
cdClientBuffer.seekg(position);
return prevPosition;
}
std::string FdbToSqlite::Convert::ReadColumnHeader(std::istream& cdClientBuffer) {
int32_t prevPosition = SeekPointer(cdClientBuffer);
int32_t numberOfColumns = ReadInt32(cdClientBuffer);
std::string tableName = ReadString(cdClientBuffer);
auto columns = ReadColumns(numberOfColumns, cdClientBuffer);
std::string newTable = "CREATE TABLE IF NOT EXISTS '" + tableName + "' (" + columns + ");";
CDClientDatabase::ExecuteDML(newTable);
cdClientBuffer.seekg(prevPosition);
return tableName;
}
void FdbToSqlite::Convert::ReadTables(int32_t& numberOfTables, std::istream& cdClientBuffer) {
int32_t prevPosition = SeekPointer(cdClientBuffer);
for (int32_t i = 0; i < numberOfTables; i++) {
auto columnHeader = ReadColumnHeader(cdClientBuffer);
ReadRowHeader(columnHeader, cdClientBuffer);
}
cdClientBuffer.seekg(prevPosition);
}
std::string FdbToSqlite::Convert::ReadColumns(int32_t& numberOfColumns, std::istream& cdClientBuffer) {
std::stringstream columnsToCreate;
int32_t prevPosition = SeekPointer(cdClientBuffer);
std::string name{};
eSqliteDataType dataType{};
for (int32_t i = 0; i < numberOfColumns; i++) {
if (i != 0) columnsToCreate << ", ";
dataType = static_cast<eSqliteDataType>(ReadInt32(cdClientBuffer));
name = ReadString(cdClientBuffer);
columnsToCreate << "'" << name << "' " << FdbToSqlite::Convert::m_SqliteType[dataType];
}
cdClientBuffer.seekg(prevPosition);
return columnsToCreate.str();
}
void FdbToSqlite::Convert::ReadRowHeader(std::string& tableName, std::istream& cdClientBuffer) {
int32_t prevPosition = SeekPointer(cdClientBuffer);
int32_t numberOfAllocatedRows = ReadInt32(cdClientBuffer);
if (numberOfAllocatedRows != 0) assert((numberOfAllocatedRows & (numberOfAllocatedRows - 1)) == 0); // assert power of 2 allocation size
ReadRows(numberOfAllocatedRows, tableName, cdClientBuffer);
cdClientBuffer.seekg(prevPosition);
}
void FdbToSqlite::Convert::ReadRows(int32_t& numberOfAllocatedRows, std::string& tableName, std::istream& cdClientBuffer) {
int32_t prevPosition = SeekPointer(cdClientBuffer);
int32_t rowid = 0;
for (int32_t row = 0; row < numberOfAllocatedRows; row++) {
int32_t rowPointer = ReadInt32(cdClientBuffer);
if (rowPointer == -1) rowid++;
else ReadRow(rowPointer, tableName, cdClientBuffer);
}
cdClientBuffer.seekg(prevPosition);
}
void FdbToSqlite::Convert::ReadRow(int32_t& position, std::string& tableName, std::istream& cdClientBuffer) {
int32_t prevPosition = cdClientBuffer.tellg();
cdClientBuffer.seekg(position);
while (true) {
ReadRowInfo(tableName, cdClientBuffer);
int32_t linked = ReadInt32(cdClientBuffer);
if (linked == -1) break;
cdClientBuffer.seekg(linked);
}
cdClientBuffer.seekg(prevPosition);
}
void FdbToSqlite::Convert::ReadRowInfo(std::string& tableName, std::istream& cdClientBuffer) {
int32_t prevPosition = SeekPointer(cdClientBuffer);
int32_t numberOfColumns = ReadInt32(cdClientBuffer);
ReadRowValues(numberOfColumns, tableName, cdClientBuffer);
cdClientBuffer.seekg(prevPosition);
}
void FdbToSqlite::Convert::ReadRowValues(int32_t& numberOfColumns, std::string& tableName, std::istream& cdClientBuffer) {
int32_t prevPosition = SeekPointer(cdClientBuffer);
int32_t emptyValue{};
int32_t intValue{};
float_t floatValue{};
std::string stringValue{};
int32_t boolValue{};
int64_t int64Value{};
bool insertedFirstEntry = false;
std::stringstream insertedRow;
insertedRow << "INSERT INTO " << tableName << " values (";
for (int32_t i = 0; i < numberOfColumns; i++) {
if (i != 0) insertedRow << ", "; // Only append comma and space after first entry in row.
switch (static_cast<eSqliteDataType>(ReadInt32(cdClientBuffer))) {
case eSqliteDataType::NONE:
BinaryIO::BinaryRead(cdClientBuffer, emptyValue);
assert(emptyValue == 0);
insertedRow << "NULL";
break;
case eSqliteDataType::INT32:
intValue = ReadInt32(cdClientBuffer);
insertedRow << intValue;
break;
case eSqliteDataType::REAL:
BinaryIO::BinaryRead(cdClientBuffer, floatValue);
insertedRow << std::fixed << std::setprecision(34) << floatValue; // maximum precision of floating point number
break;
case eSqliteDataType::TEXT_4:
case eSqliteDataType::TEXT_8: {
stringValue = ReadString(cdClientBuffer);
size_t position = 0;
// Need to escape quote with a double of ".
while (position < stringValue.size()) {
if (stringValue.at(position) == '\"') {
stringValue.insert(position, "\"");
position++;
}
position++;
}
insertedRow << "\"" << stringValue << "\"";
break;
}
case eSqliteDataType::INT_BOOL:
BinaryIO::BinaryRead(cdClientBuffer, boolValue);
insertedRow << static_cast<bool>(boolValue);
break;
case eSqliteDataType::INT64:
int64Value = ReadInt64(cdClientBuffer);
insertedRow << std::to_string(int64Value);
break;
default:
throw std::invalid_argument("Unsupported SQLite type encountered.");
break;
}
}
insertedRow << ");";
auto copiedString = insertedRow.str();
CDClientDatabase::ExecuteDML(copiedString);
cdClientBuffer.seekg(prevPosition);
}

145
dCommon/FdbToSqlite.h Normal file
View File

@@ -0,0 +1,145 @@
#ifndef __FDBTOSQLITE__H__
#define __FDBTOSQLITE__H__
#pragma once
#include <cstdint>
#include <iosfwd>
#include <map>
#include "AssetManager.h"
enum class eSqliteDataType : int32_t;
namespace FdbToSqlite {
class Convert {
public:
/**
* Create a new convert object with an input .fdb file and an output binary path.
*
* @param inputFile The file which ends in .fdb to be converted
* @param binaryPath The base path where the file will be saved
*/
Convert(std::string binaryOutPath);
/**
* Converts the input file to sqlite. Calling multiple times is safe.
*
* @return true if the database was converted properly, false otherwise.
*/
bool ConvertDatabase(AssetStream& buffer);
/**
* @brief Reads a 32 bit int from the fdb file.
*
* @return The read value
*/
int32_t ReadInt32(std::istream& cdClientBuffer);
/**
* @brief Reads a 64 bit integer from the fdb file.
*
* @return The read value
*/
int64_t ReadInt64(std::istream& cdClientBuffer);
/**
* @brief Reads a string from the fdb file.
*
* @return The read string
*
* TODO This needs to be translated to latin-1!
*/
std::string ReadString(std::istream& cdClientBuffer);
/**
* @brief Seeks to a pointer position.
*
* @return The previous position before the seek
*/
int32_t SeekPointer(std::istream& cdClientBuffer);
/**
* @brief Reads a column header from the fdb file and creates the table in the database
*
* @return The table name
*/
std::string ReadColumnHeader(std::istream& cdClientBuffer);
/**
* @brief Read the tables from the fdb file.
*
* @param numberOfTables The number of tables to read
*/
void ReadTables(int32_t& numberOfTables, std::istream& cdClientBuffer);
/**
* @brief Reads the columns from the fdb file.
*
* @param numberOfColumns The number of columns to read
* @return All columns of the table formatted for a sql query
*/
std::string ReadColumns(int32_t& numberOfColumns, std::istream& cdClientBuffer);
/**
* @brief Reads the row header from the fdb file.
*
* @param tableName The tables name
*/
void ReadRowHeader(std::string& tableName, std::istream& cdClientBuffer);
/**
* @brief Read the rows from the fdb file.,
*
* @param numberOfAllocatedRows The number of rows that were allocated. Always a power of 2!
* @param tableName The tables name.
*/
void ReadRows(int32_t& numberOfAllocatedRows, std::string& tableName, std::istream& cdClientBuffer);
/**
* @brief Reads a row from the fdb file.
*
* @param position The position to seek in the fdb to
* @param tableName The tables name
*/
void ReadRow(int32_t& position, std::string& tableName, std::istream& cdClientBuffer);
/**
* @brief Reads the row info from the fdb file.
*
* @param tableName The tables name
*/
void ReadRowInfo(std::string& tableName, std::istream& cdClientBuffer);
/**
* @brief Reads each row and its values from the fdb file and inserts them into the database
*
* @param numberOfColumns The number of columns to read in
* @param tableName The tables name
*/
void ReadRowValues(int32_t& numberOfColumns, std::string& tableName, std::istream& cdClientBuffer);
private:
/**
* Maps each sqlite data type to its string equivalent.
*/
static std::map<eSqliteDataType, std::string> m_SqliteType;
/**
* Base path of the folder containing the fdb file
*/
std::string m_BasePath{};
/**
* Whether or not a conversion was started. If one was started, do not attempt to convert the file again.
*/
bool m_ConversionStarted{};
/**
* The path where the CDServer will be stored
*/
std::string m_BinaryOutPath{};
}; //! class FdbToSqlite
}; //! namespace FdbToSqlite
#endif //!__FDBTOSQLITE__H__

7
dCommon/Game.cpp Normal file
View File

@@ -0,0 +1,7 @@
#include "Game.h"
namespace Game {
void OnSignal(int signal) {
lastSignal = signal;
}
}

View File

@@ -1,26 +1,40 @@
#pragma once
#include <string>
#include <random>
#include <csignal>
class dServer;
class dLogger;
class Logger;
class InstanceManager;
class dpWorld;
class dChatFilter;
class dConfig;
class dLocale;
class RakPeerInterface;
class AssetManager;
struct SystemAddress;
class EntityManager;
class dZoneManager;
class PlayerContainer;
namespace Game {
extern dLogger* logger;
using signal_t = volatile std::sig_atomic_t;
extern Logger* logger;
extern dServer* server;
extern InstanceManager* im;
extern dpWorld* physicsWorld;
extern dChatFilter* chatFilter;
extern dConfig* config;
extern dLocale* locale;
extern std::mt19937 randomEngine;
extern RakPeerInterface* chatServer;
extern AssetManager* assetManager;
extern SystemAddress chatSysAddr;
}
extern signal_t lastSignal;
extern EntityManager* entityManager;
extern dZoneManager* zoneManager;
extern PlayerContainer playerContainer;
extern std::string projectVersion;
inline bool ShouldShutdown() {
return lastSignal != 0;
}
void OnSignal(int signal);
}

View File

@@ -4,168 +4,271 @@
#include <cstdint>
#include <cassert>
#include <algorithm>
#include <filesystem>
#include <map>
template <typename T>
inline size_t MinSize(size_t size, const std::basic_string<T>& string) {
if (size == size_t(-1) || size > string.size()) {
return string.size();
} else {
return size;
}
inline size_t MinSize(size_t size, const std::basic_string_view<T>& string) {
if (size == size_t(-1) || size > string.size()) {
return string.size();
} else {
return size;
}
}
inline bool IsLeadSurrogate(char16_t c) {
return (0xD800 <= c) && (c <= 0xDBFF);
return (0xD800 <= c) && (c <= 0xDBFF);
}
inline bool IsTrailSurrogate(char16_t c) {
return (0xDC00 <= c) && (c <= 0xDFFF);
return (0xDC00 <= c) && (c <= 0xDFFF);
}
inline void PushUTF8CodePoint(std::string& ret, char32_t cp) {
if (cp <= 0x007F) {
ret.push_back(cp);
} else if (cp <= 0x07FF) {
ret.push_back(0xC0 | (cp >> 6));
ret.push_back(0x80 | (cp & 0x3F));
} else if (cp <= 0xFFFF) {
ret.push_back(0xE0 | (cp >> 12));
ret.push_back(0x80 | ((cp >> 6) & 0x3F));
ret.push_back(0x80 | (cp & 0x3F));
} else if (cp <= 0x10FFFF) {
ret.push_back(0xF0 | (cp >> 18));
ret.push_back(0x80 | ((cp >> 12) & 0x3F));
ret.push_back(0x80 | ((cp >> 6) & 0x3F));
ret.push_back(0x80 | (cp & 0x3F));
} else {
assert(false);
}
if (cp <= 0x007F) {
ret.push_back(static_cast<uint8_t>(cp));
} else if (cp <= 0x07FF) {
ret.push_back(0xC0 | (cp >> 6));
ret.push_back(0x80 | (cp & 0x3F));
} else if (cp <= 0xFFFF) {
ret.push_back(0xE0 | (cp >> 12));
ret.push_back(0x80 | ((cp >> 6) & 0x3F));
ret.push_back(0x80 | (cp & 0x3F));
} else if (cp <= 0x10FFFF) {
ret.push_back(0xF0 | (cp >> 18));
ret.push_back(0x80 | ((cp >> 12) & 0x3F));
ret.push_back(0x80 | ((cp >> 6) & 0x3F));
ret.push_back(0x80 | (cp & 0x3F));
} else {
assert(false);
}
}
constexpr const char16_t REPLACEMENT_CHARACTER = 0xFFFD;
bool _IsSuffixChar(uint8_t c) {
return (c & 0xC0) == 0x80;
}
bool GeneralUtils::_NextUTF8Char(std::string_view& slice, uint32_t& out) {
size_t rem = slice.length();
if (slice.empty()) return false;
const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&slice.front());
if (rem > 0) {
uint8_t first = bytes[0];
if (first < 0x80) { // 1 byte character
out = static_cast<uint32_t>(first & 0x7F);
slice.remove_prefix(1);
return true;
} else if (first < 0xC0) {
// middle byte, not valid at start, fall through
} else if (first < 0xE0) { // two byte character
if (rem > 1) {
uint8_t second = bytes[1];
if (_IsSuffixChar(second)) {
out = (static_cast<uint32_t>(first & 0x1F) << 6)
+ static_cast<uint32_t>(second & 0x3F);
slice.remove_prefix(2);
return true;
}
}
} else if (first < 0xF0) { // three byte character
if (rem > 2) {
uint8_t second = bytes[1];
uint8_t third = bytes[2];
if (_IsSuffixChar(second) && _IsSuffixChar(third)) {
out = (static_cast<uint32_t>(first & 0x0F) << 12)
+ (static_cast<uint32_t>(second & 0x3F) << 6)
+ static_cast<uint32_t>(third & 0x3F);
slice.remove_prefix(3);
return true;
}
}
} else if (first < 0xF8) { // four byte character
if (rem > 3) {
uint8_t second = bytes[1];
uint8_t third = bytes[2];
uint8_t fourth = bytes[3];
if (_IsSuffixChar(second) && _IsSuffixChar(third) && _IsSuffixChar(fourth)) {
out = (static_cast<uint32_t>(first & 0x07) << 18)
+ (static_cast<uint32_t>(second & 0x3F) << 12)
+ (static_cast<uint32_t>(third & 0x3F) << 6)
+ static_cast<uint32_t>(fourth & 0x3F);
slice.remove_prefix(4);
return true;
}
}
}
out = static_cast<uint32_t>(REPLACEMENT_CHARACTER);
slice.remove_prefix(1);
return true;
}
return false;
}
/// See <https://www.ietf.org/rfc/rfc2781.html#section-2.1>
bool PushUTF16CodePoint(std::u16string& output, uint32_t U, size_t size) {
if (output.length() >= size) return false;
if (U < 0x10000) {
// If U < 0x10000, encode U as a 16-bit unsigned integer and terminate.
output.push_back(static_cast<uint16_t>(U));
return true;
} else if (U > 0x10FFFF) {
output.push_back(REPLACEMENT_CHARACTER);
return true;
} else if (output.length() + 1 < size) {
// Let U' = U - 0x10000. Because U is less than or equal to 0x10FFFF,
// U' must be less than or equal to 0xFFFFF. That is, U' can be
// represented in 20 bits.
uint32_t Ut = U - 0x10000;
// Initialize two 16-bit unsigned integers, W1 and W2, to 0xD800 and
// 0xDC00, respectively. These integers each have 10 bits free to
// encode the character value, for a total of 20 bits.
uint16_t W1 = 0xD800;
uint16_t W2 = 0xDC00;
// Assign the 10 high-order bits of the 20-bit U' to the 10 low-order
// bits of W1 and the 10 low-order bits of U' to the 10 low-order
// bits of W2.
W1 += static_cast<uint16_t>((Ut & 0x3FC00) >> 10);
W2 += static_cast<uint16_t>((Ut & 0x3FF) >> 0);
// Terminate.
output.push_back(W1); // high surrogate
output.push_back(W2); // low surrogate
return true;
} else return false;
}
std::u16string GeneralUtils::UTF8ToUTF16(const std::string_view& string, size_t size) {
size_t newSize = MinSize(size, string);
std::u16string output;
output.reserve(newSize);
std::string_view iterator = string;
uint32_t c;
while (_NextUTF8Char(iterator, c) && PushUTF16CodePoint(output, c, size)) {}
return output;
}
//! Converts an std::string (ASCII) to UCS-2 / UTF-16
std::u16string GeneralUtils::ASCIIToUTF16(const std::string& string, size_t size) {
size_t newSize = MinSize(size, string);
std::u16string ret;
ret.reserve(newSize);
std::u16string GeneralUtils::ASCIIToUTF16(const std::string_view& string, size_t size) {
size_t newSize = MinSize(size, string);
std::u16string ret;
ret.reserve(newSize);
for (size_t i = 0; i < newSize; i++) {
char c = string[i];
assert(c > 0 && c <= 127);
ret.push_back(static_cast<char16_t>(c));
}
for (size_t i = 0; i < newSize; i++) {
char c = string[i];
// Note: both 7-bit ascii characters and REPLACEMENT_CHARACTER fit in one char16_t
ret.push_back((c > 0 && c <= 127) ? static_cast<char16_t>(c) : REPLACEMENT_CHARACTER);
}
return ret;
return ret;
}
//! Converts a (potentially-ill-formed) UTF-16 string to UTF-8
//! See: <http://simonsapin.github.io/wtf-8/#decoding-ill-formed-utf-16>
std::string GeneralUtils::UTF16ToWTF8(const std::u16string& string, size_t size) {
size_t newSize = MinSize(size, string);
std::string ret;
ret.reserve(newSize);
std::string GeneralUtils::UTF16ToWTF8(const std::u16string_view& string, size_t size) {
size_t newSize = MinSize(size, string);
std::string ret;
ret.reserve(newSize);
for (size_t i = 0; i < newSize; i++) {
char16_t u = string[i];
if (IsLeadSurrogate(u) && (i + 1) < newSize) {
char16_t next = string[i + 1];
if (IsTrailSurrogate(next)) {
i += 1;
char32_t cp = 0x10000
+ ((static_cast<char32_t>(u) - 0xD800) << 10)
+ (static_cast<char32_t>(next) - 0xDC00);
PushUTF8CodePoint(ret, cp);
} else {
PushUTF8CodePoint(ret, u);
}
} else {
PushUTF8CodePoint(ret, u);
}
}
for (size_t i = 0; i < newSize; i++) {
char16_t u = string[i];
if (IsLeadSurrogate(u) && (i + 1) < newSize) {
char16_t next = string[i + 1];
if (IsTrailSurrogate(next)) {
i += 1;
char32_t cp = 0x10000
+ ((static_cast<char32_t>(u) - 0xD800) << 10)
+ (static_cast<char32_t>(next) - 0xDC00);
PushUTF8CodePoint(ret, cp);
} else {
PushUTF8CodePoint(ret, u);
}
} else {
PushUTF8CodePoint(ret, u);
}
}
return ret;
return ret;
}
bool GeneralUtils::CaseInsensitiveStringCompare(const std::string& a, const std::string& b) {
return std::equal(a.begin(), a.end (), b.begin(), b.end(),[](char a, char b) { return tolower(a) == tolower(b); });
return std::equal(a.begin(), a.end(), b.begin(), b.end(), [](char a, char b) { return tolower(a) == tolower(b); });
}
// MARK: Bits
//! Sets a specific bit in a signed 64-bit integer
int64_t GeneralUtils::SetBit(int64_t value, uint32_t index) {
return value |= 1ULL << index;
return value |= 1ULL << index;
}
//! Clears a specific bit in a signed 64-bit integer
int64_t GeneralUtils::ClearBit(int64_t value, uint32_t index) {
return value &= ~(1ULL << index);
return value &= ~(1ULL << index);
}
//! Checks a specific bit in a signed 64-bit integer
bool GeneralUtils::CheckBit(int64_t value, uint32_t index) {
return value & (1ULL << index);
return value & (1ULL << index);
}
bool GeneralUtils::ReplaceInString(std::string& str, const std::string& from, const std::string& to) {
size_t start_pos = str.find(from);
if(start_pos == std::string::npos)
return false;
str.replace(start_pos, from.length(), to);
return true;
size_t start_pos = str.find(from);
if (start_pos == std::string::npos)
return false;
str.replace(start_pos, from.length(), to);
return true;
}
std::vector<std::wstring> GeneralUtils::SplitString(std::wstring& str, wchar_t delimiter)
{
std::vector<std::wstring> vector = std::vector<std::wstring>();
std::wstring current;
std::vector<std::wstring> GeneralUtils::SplitString(std::wstring& str, wchar_t delimiter) {
std::vector<std::wstring> vector = std::vector<std::wstring>();
std::wstring current;
for (const auto& c : str) {
if (c == delimiter) {
vector.push_back(current);
current = L"";
} else {
current += c;
}
}
for (const auto& c : str) {
if (c == delimiter) {
vector.push_back(current);
current = L"";
} else {
current += c;
}
}
vector.push_back(current);
return vector;
vector.push_back(current);
return vector;
}
std::vector<std::u16string> GeneralUtils::SplitString(std::u16string& str, char16_t delimiter)
{
std::vector<std::u16string> vector = std::vector<std::u16string>();
std::u16string current;
std::vector<std::u16string> GeneralUtils::SplitString(const std::u16string& str, char16_t delimiter) {
std::vector<std::u16string> vector = std::vector<std::u16string>();
std::u16string current;
for (const auto& c : str) {
if (c == delimiter) {
vector.push_back(current);
current = u"";
} else {
current += c;
}
}
for (const auto& c : str) {
if (c == delimiter) {
vector.push_back(current);
current = u"";
} else {
current += c;
}
}
vector.push_back(current);
return vector;
vector.push_back(current);
return vector;
}
std::vector<std::string> GeneralUtils::SplitString(const std::string& str, char delimiter)
{
std::vector<std::string> GeneralUtils::SplitString(const std::string& str, char delimiter) {
std::vector<std::string> vector = std::vector<std::string>();
std::string current = "";
for (size_t i = 0; i < str.length(); i++)
{
for (size_t i = 0; i < str.length(); i++) {
char c = str[i];
if (c == delimiter)
{
if (c == delimiter) {
vector.push_back(current);
current = "";
}
else
{
} else {
current += c;
}
}
@@ -175,16 +278,48 @@ std::vector<std::string> GeneralUtils::SplitString(const std::string& str, char
return vector;
}
std::u16string GeneralUtils::ReadWString(RakNet::BitStream *inStream) {
uint32_t length;
inStream->Read<uint32_t>(length);
std::u16string GeneralUtils::ReadWString(RakNet::BitStream* inStream) {
uint32_t length;
inStream->Read<uint32_t>(length);
std::u16string string;
for (auto i = 0; i < length; i++) {
uint16_t c;
inStream->Read(c);
string.push_back(c);
}
std::u16string string;
for (auto i = 0; i < length; i++) {
uint16_t c;
inStream->Read(c);
string.push_back(c);
}
return string;
return string;
}
std::vector<std::string> GeneralUtils::GetSqlFileNamesFromFolder(const std::string& folder) {
// Because we dont know how large the initial number before the first _ is we need to make it a map like so.
std::map<uint32_t, std::string> filenames{};
for (auto& t : std::filesystem::directory_iterator(folder)) {
auto filename = t.path().filename().string();
auto index = std::stoi(GeneralUtils::SplitString(filename, '_').at(0));
filenames.insert(std::make_pair(index, filename));
}
// Now sort the map by the oldest migration.
std::vector<std::string> sortedFiles{};
auto fileIterator = filenames.begin();
std::map<uint32_t, std::string>::iterator oldest = filenames.begin();
while (!filenames.empty()) {
if (fileIterator == filenames.end()) {
sortedFiles.push_back(oldest->second);
filenames.erase(oldest);
fileIterator = filenames.begin();
oldest = filenames.begin();
continue;
}
if (oldest->first > fileIterator->first) oldest = fileIterator;
fileIterator++;
}
return sortedFiles;
}
bool GeneralUtils::TryParse(const std::string& x, const std::string& y, const std::string& z, NiPoint3& dst) {
return TryParse<float>(x.c_str(), dst.x) && TryParse<float>(y.c_str(), dst.y) && TryParse<float>(z.c_str(), dst.z);
}

View File

@@ -9,202 +9,255 @@
#include <functional>
#include <type_traits>
#include <stdexcept>
#include <BitStream.h>
#include "BitStream.h"
#include "NiPoint3.h"
#include "Game.h"
#include "Logger.h"
enum eInventoryType : uint32_t;
enum class eObjectBits : size_t;
enum class eReplicaComponentType : uint32_t;
/*!
\file GeneralUtils.hpp
\brief A namespace containing general utility functions
*/
//! The general utils namespace
//! The general utils namespace
namespace GeneralUtils {
//! Converts a plain ASCII string to a UTF-16 string
/*!
\param string The string to convert
\param size A size to trim the string to. Default is -1 (No trimming)
\return An UTF-16 representation of the string
*/
std::u16string ASCIIToUTF16(const std::string& string, size_t size = -1);
//! Converts a plain ASCII string to a UTF-16 string
/*!
\param string The string to convert
\param size A size to trim the string to. Default is -1 (No trimming)
\return An UTF-16 representation of the string
*/
std::u16string ASCIIToUTF16(const std::string_view& string, size_t size = -1);
//! Converts a UTF-16 string to a UTF-8 string
/*!
\param string The string to convert
\param size A size to trim the string to. Default is -1 (No trimming)
\return An UTF-8 representation of the string
*/
std::string UTF16ToWTF8(const std::u16string& string, size_t size = -1);
//! Converts a UTF-8 String to a UTF-16 string
/*!
\param string The string to convert
\param size A size to trim the string to. Default is -1 (No trimming)
\return An UTF-16 representation of the string
*/
std::u16string UTF8ToUTF16(const std::string_view& string, size_t size = -1);
/**
* Compares two basic strings but does so ignoring case sensitivity
* \param a the first string to compare against the second string
* \param b the second string to compare against the first string
* @return if the two strings are equal
*/
bool CaseInsensitiveStringCompare(const std::string& a, const std::string& b);
//! Internal, do not use
bool _NextUTF8Char(std::string_view& slice, uint32_t& out);
// MARK: Bits
//! Converts a UTF-16 string to a UTF-8 string
/*!
\param string The string to convert
\param size A size to trim the string to. Default is -1 (No trimming)
\return An UTF-8 representation of the string
*/
std::string UTF16ToWTF8(const std::u16string_view& string, size_t size = -1);
// MARK: Bits
/**
* Compares two basic strings but does so ignoring case sensitivity
* \param a the first string to compare against the second string
* \param b the second string to compare against the first string
* @return if the two strings are equal
*/
bool CaseInsensitiveStringCompare(const std::string& a, const std::string& b);
//! Sets a bit on a numerical value
template <typename T>
void SetBit(T& value, size_t index) {
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
if (index > (sizeof(T) * 8) - 1) {
return;
}
value |= static_cast<T>(1) << index;
}
//! Clears a bit on a numerical value
template <typename T>
void ClearBit(T& value, size_t index) {
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
if (index > (sizeof(T) * 8 - 1)) {
return;
}
value &= ~(static_cast<T>(1) << index);
}
//! Sets a specific bit in a signed 64-bit integer
/*!
\param value The value to set the bit for
\param index The index of the bit
*/
int64_t SetBit(int64_t value, uint32_t index);
//! Clears a specific bit in a signed 64-bit integer
/*!
\param value The value to clear the bit from
\param index The index of the bit
*/
int64_t ClearBit(int64_t value, uint32_t index);
//! Checks a specific bit in a signed 64-bit integer
/*!
\parma value The value to check the bit in
\param index The index of the bit
\return Whether or not the bit is set
*/
bool CheckBit(int64_t value, uint32_t index);
// MARK: Bits
// MARK: Random Number Generation
// MARK: Bits
//! 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");
//! Sets a bit on a numerical value
template <typename T>
inline void SetBit(T& value, eObjectBits bits) {
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
auto index = static_cast<size_t>(bits);
if (index > (sizeof(T) * 8) - 1) {
return;
}
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);
}
value |= static_cast<T>(1) << index;
}
//! Clears a bit on a numerical value
template <typename T>
inline void ClearBit(T& value, eObjectBits bits) {
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
auto index = static_cast<size_t>(bits);
if (index > (sizeof(T) * 8 - 1)) {
return;
}
value &= ~(static_cast<T>(1) << index);
}
//! Sets a specific bit in a signed 64-bit integer
/*!
\param value The value to set the bit for
\param index The index of the bit
*/
int64_t SetBit(int64_t value, uint32_t index);
//! Clears a specific bit in a signed 64-bit integer
/*!
\param value The value to clear the bit from
\param index The index of the bit
*/
int64_t ClearBit(int64_t value, uint32_t index);
//! Checks a specific bit in a signed 64-bit integer
/*!
\parma value The value to check the bit in
\param index The index of the bit
\return Whether or not the bit is set
*/
bool CheckBit(int64_t value, uint32_t index);
return T();
}
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);
std::vector<std::wstring> SplitString(std::wstring& str, wchar_t delimiter);
std::vector<std::u16string> SplitString(std::u16string& str, char16_t delimiter);
std::vector<std::u16string> SplitString(const std::u16string& str, char16_t delimiter);
std::vector<std::string> SplitString(const std::string& str, char delimiter);
template <typename T>
T Parse(const char* value);
std::vector<std::string> GetSqlFileNamesFromFolder(const std::string& folder);
template <typename T>
T Parse(const char* value);
template <>
inline int32_t Parse(const char* value)
{
return std::stoi(value);
inline bool Parse(const char* value) {
return std::stoi(value);
}
template <>
inline int64_t Parse(const char* value)
{
return std::stoll(value);
}
template <>
inline int32_t Parse(const char* value) {
return std::stoi(value);
}
template <>
inline float Parse(const char* value)
{
return std::stof(value);
}
template <>
inline int64_t Parse(const char* value) {
return std::stoll(value);
}
template <>
inline double Parse(const char* value)
{
return std::stod(value);
}
template <>
inline uint32_t Parse(const char* value)
{
return std::stoul(value);
}
template <>
inline float Parse(const char* value) {
return std::stof(value);
}
template <>
inline uint64_t Parse(const char* value)
{
return std::stoull(value);
}
template <typename T>
bool TryParse(const char* value, T& dst)
{
try
{
dst = Parse<T>(value);
template <>
inline double Parse(const char* value) {
return std::stod(value);
}
return true;
}
catch (...)
{
return false;
}
}
template <>
inline uint16_t Parse(const char* value) {
return std::stoul(value);
}
template <typename T>
T Parse(const std::string& value)
{
return Parse<T>(value.c_str());
}
template <>
inline uint32_t Parse(const char* value) {
return std::stoul(value);
}
template <typename T>
bool TryParse(const std::string& value, T& dst)
{
return TryParse<T>(value.c_str(), dst);
}
template <>
inline uint64_t Parse(const char* value) {
return std::stoull(value);
}
template<typename T>
std::u16string to_u16string(T value)
{
return GeneralUtils::ASCIIToUTF16(std::to_string(value));
}
template <>
inline eInventoryType Parse(const char* value) {
return static_cast<eInventoryType>(std::stoul(value));
}
// From boost::hash_combine
template <class T>
void hash_combine(std::size_t& s, const T& v)
{
std::hash<T> h;
s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2);
}
template <>
inline eReplicaComponentType Parse(const char* value) {
return static_cast<eReplicaComponentType>(std::stoul(value));
}
template <typename T>
bool TryParse(const char* value, T& dst) {
try {
dst = Parse<T>(value);
return true;
} catch (...) {
return false;
}
}
template <typename T>
T Parse(const std::string& value) {
return Parse<T>(value.c_str());
}
template <typename T>
bool TryParse(const std::string& value, T& dst) {
return TryParse<T>(value.c_str(), dst);
}
bool TryParse(const std::string& x, const std::string& y, const std::string& z, NiPoint3& dst);
template<typename T>
std::u16string to_u16string(T value) {
return GeneralUtils::ASCIIToUTF16(std::to_string(value));
}
// From boost::hash_combine
template <class T>
void hash_combine(std::size_t& s, const T& v) {
std::hash<T> h;
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();
}
/**
* Casts the value of an enum entry to its underlying type
* @param entry Enum entry to cast
* @returns The enum entry's value in its underlying type
*/
template <typename eType>
inline constexpr typename std::underlying_type_t<eType> CastUnderlyingType(const eType entry) {
static_assert(std::is_enum_v<eType>, "Not an enum");
return static_cast<typename std::underlying_type_t<eType>>(entry);
}
// 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

@@ -3,132 +3,166 @@
// Custom Classes
#include "GeneralUtils.h"
#include "Game.h"
#include "Logger.h"
// C++
#include <sstream>
#include <string_view>
#include <vector>
//! Returns a pointer to a LDFData value based on string format
LDFBaseData * LDFBaseData::DataFromString(const std::string& format) {
// First, check the format
std::istringstream ssFormat(format);
std::string token;
std::vector<std::string> keyValueArray;
while (std::getline(ssFormat, token, '=')) {
keyValueArray.push_back(token);
}
if (keyValueArray.size() == 2) {
std::u16string key = GeneralUtils::ASCIIToUTF16(keyValueArray[0]);
std::vector<std::string> dataArray;
std::istringstream ssData(keyValueArray[1]);
while (std::getline(ssData, token, ':')) {
dataArray.push_back(token);
}
using LDFKey = std::string_view;
using LDFTypeAndValue = std::string_view;
if (dataArray.size() > 2) { // hacky fix for strings with colons in them
std::vector<std::string> newDataArray;
newDataArray.push_back(dataArray[0]);
std::string value = "";
for (size_t i = 1; i < dataArray.size(); ++i) {
value += dataArray[i] + ':';
}
value.pop_back(); // remove last colon
newDataArray.push_back(value);
dataArray = newDataArray;
using LDFType = std::string_view;
using LDFValue = std::string_view;
//! Returns a pointer to a LDFData value based on string format
LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
// A valid LDF must be at least 3 characters long (=0:) is the shortest valid LDF (empty UTF-16 key with no initial value)
if (format.empty() || format.length() <= 2) return nullptr;
auto equalsPosition = format.find('=');
// You can have an empty key, just make sure the type and value might exist
if (equalsPosition == std::string::npos || equalsPosition == (format.size() - 1)) return nullptr;
std::pair<LDFKey, LDFTypeAndValue> keyValue;
keyValue.first = format.substr(0, equalsPosition);
keyValue.second = format.substr(equalsPosition + 1, format.size());
std::u16string key = GeneralUtils::ASCIIToUTF16(keyValue.first);
auto colonPosition = keyValue.second.find(':');
// If : is the first thing after an =, then this is an invalid LDF since
// we dont have a type to use.
if (colonPosition == std::string::npos || colonPosition == 0) return nullptr;
std::pair<LDFType, LDFValue> ldfTypeAndValue;
ldfTypeAndValue.first = keyValue.second.substr(0, colonPosition);
ldfTypeAndValue.second = keyValue.second.substr(colonPosition + 1, keyValue.second.size());
// Only allow empty values for string values.
if (ldfTypeAndValue.second.size() == 0 && !(ldfTypeAndValue.first == "0" || ldfTypeAndValue.first == "13")) return nullptr;
eLDFType type;
char* storage;
try {
type = static_cast<eLDFType>(strtol(ldfTypeAndValue.first.data(), &storage, 10));
} catch (std::exception) {
LOG("Attempted to process invalid ldf type (%s) from string (%s)", ldfTypeAndValue.first.data(), format.data());
return nullptr;
}
LDFBaseData* returnValue = nullptr;
switch (type) {
case LDF_TYPE_UTF_16: {
std::u16string data = GeneralUtils::UTF8ToUTF16(ldfTypeAndValue.second);
returnValue = new LDFData<std::u16string>(key, data);
break;
}
case LDF_TYPE_S32: {
int32_t data;
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
LOG("Warning: Attempted to process invalid int32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr;
}
if ((dataArray[0] == "0" || dataArray[0] == "13") && dataArray.size() == 1) {
dataArray.push_back("");
}
if (dataArray.size() == 2) {
eLDFType type = static_cast<eLDFType>(stoi(dataArray[0]));
switch (type) {
case LDF_TYPE_UTF_16: {
std::u16string data = GeneralUtils::ASCIIToUTF16(dataArray[1]);
return new LDFData<std::u16string>(key, data);
}
case LDF_TYPE_S32: {
int32_t data = static_cast<int32_t>(stol(dataArray[1]));
return new LDFData<int32_t>(key, data);
}
case LDF_TYPE_FLOAT: {
float data = static_cast<float>(stof(dataArray[1]));
return new LDFData<float>(key, data);
}
case LDF_TYPE_DOUBLE: {
double data = static_cast<float>(stod(dataArray[1]));
return new LDFData<double>(key, data);
}
case LDF_TYPE_U32:
{
uint32_t data;
if (dataArray[1] == "true")
{
data = 1;
}
else if (dataArray[1] == "false")
{
data = 0;
}
else
{
data = static_cast<uint32_t>(stoul(dataArray[1]));
}
return new LDFData<uint32_t>(key, data);
}
case LDF_TYPE_BOOLEAN: {
bool data;
if (dataArray[1] == "true")
{
data = true;
}
else if (dataArray[1] == "false")
{
data = false;
}
else
{
data = static_cast<bool>(stoi(dataArray[1]));
}
return new LDFData<bool>(key, data);
}
case LDF_TYPE_U64: {
uint64_t data = static_cast<uint64_t>(stoull(dataArray[1]));
return new LDFData<uint64_t>(key, data);
}
case LDF_TYPE_OBJID: {
LWOOBJID data = static_cast<LWOOBJID>(stoll(dataArray[1]));
return new LDFData<LWOOBJID>(key, data);
}
case LDF_TYPE_UTF_8: {
std::string data = dataArray[1];
return new LDFData<std::string>(key, data);
}
case LDF_TYPE_UNKNOWN: {
return nullptr;
}
}
}
}
return nullptr;
returnValue = new LDFData<int32_t>(key, data);
break;
}
case LDF_TYPE_FLOAT: {
float data;
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
LOG("Warning: Attempted to process invalid float value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr;
}
returnValue = new LDFData<float>(key, data);
break;
}
case LDF_TYPE_DOUBLE: {
double data;
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
LOG("Warning: Attempted to process invalid double value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr;
}
returnValue = new LDFData<double>(key, data);
break;
}
case LDF_TYPE_U32:
{
uint32_t data;
if (ldfTypeAndValue.second == "true") {
data = 1;
} else if (ldfTypeAndValue.second == "false") {
data = 0;
} else {
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
LOG("Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr;
}
}
returnValue = new LDFData<uint32_t>(key, data);
break;
}
case LDF_TYPE_BOOLEAN: {
bool data;
if (ldfTypeAndValue.second == "true") {
data = true;
} else if (ldfTypeAndValue.second == "false") {
data = false;
} else {
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
LOG("Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr;
}
}
returnValue = new LDFData<bool>(key, data);
break;
}
case LDF_TYPE_U64: {
uint64_t data;
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
LOG("Warning: Attempted to process invalid uint64 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr;
}
returnValue = new LDFData<uint64_t>(key, data);
break;
}
case LDF_TYPE_OBJID: {
LWOOBJID data;
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
LOG("Warning: Attempted to process invalid LWOOBJID value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr;
}
returnValue = new LDFData<LWOOBJID>(key, data);
break;
}
case LDF_TYPE_UTF_8: {
std::string data = ldfTypeAndValue.second.data();
returnValue = new LDFData<std::string>(key, data);
break;
}
case LDF_TYPE_UNKNOWN: {
LOG("Warning: Attempted to process invalid unknown value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
break;
}
default: {
LOG("Warning: Attempted to process invalid LDF type (%d) from string (%s)", type, format.data());
break;
}
}
return returnValue;
}

View File

@@ -1,4 +1,5 @@
#pragma once
#ifndef __LDFFORMAT__H__
#define __LDFFORMAT__H__
// Custom Classes
#include "dCommonVars.h"
@@ -6,191 +7,162 @@
// C++
#include <string>
#include <string_view>
#include <sstream>
// RakNet
#include "BitStream.h"
#include "../thirdparty/raknet/Source/BitStream.h"
/*!
\file LDFFormat.hpp
\brief A collection of LDF format classes
*/
//! An enum for LDF Data Types
enum eLDFType {
LDF_TYPE_UNKNOWN = -1, //!< Unknown data type
LDF_TYPE_UTF_16 = 0, //!< UTF-16 wstring data type
LDF_TYPE_S32 = 1, //!< Signed 32-bit data type
LDF_TYPE_FLOAT = 3, //!< Float data type
LDF_TYPE_DOUBLE = 4, //!< Double data type
LDF_TYPE_U32 = 5, //!< Unsigned 32-bit data type
LDF_TYPE_BOOLEAN = 7, //!< Boolean data type
LDF_TYPE_U64 = 8, //!< Unsigned 64-bit data type (originally signed, templates won't work with both S64 & OBJID
LDF_TYPE_OBJID = 9, //!< Signed 64-bit data type (reserved for object IDs)
LDF_TYPE_UTF_8 = 13, //!< UTF-8 string data type
LDF_TYPE_UNKNOWN = -1, //!< Unknown data type
LDF_TYPE_UTF_16 = 0, //!< UTF-16 wstring data type
LDF_TYPE_S32 = 1, //!< Signed 32-bit data type
LDF_TYPE_FLOAT = 3, //!< Float data type
LDF_TYPE_DOUBLE = 4, //!< Double data type
LDF_TYPE_U32 = 5, //!< Unsigned 32-bit data type
LDF_TYPE_BOOLEAN = 7, //!< Boolean data type
LDF_TYPE_U64 = 8, //!< Unsigned 64-bit data type (originally signed, templates won't work with both S64 & OBJID
LDF_TYPE_OBJID = 9, //!< Signed 64-bit data type (reserved for object IDs)
LDF_TYPE_UTF_8 = 13, //!< UTF-8 string data type
};
//! A base class for the LDF data
class LDFBaseData {
public:
//! Destructor
virtual ~LDFBaseData(void) { }
//! Writes the data to a packet
/*!
\param packet The packet
*/
virtual void WriteToPacket(RakNet::BitStream * packet) = 0;
//! Gets the key
/*!
\return The key
*/
virtual const std::u16string& GetKey(void) = 0;
//! Gets the value type
/*!
\return The value type
*/
virtual eLDFType GetValueType(void) = 0;
//! Gets a string from the key/value pair
/*!
\param includeKey Whether or not to include the key in the data
\param includeTypeId Whether or not to include the type id in the data
\return The string representation of the data
*/
virtual std::string GetString(bool includeKey = true, bool includeTypeId = true) = 0;
virtual std::string GetValueAsString() = 0;
virtual LDFBaseData * Copy() = 0;
// MARK: Functions
//! Returns a pointer to a LDFData value based on string format
/*!
\param format The format
*/
static LDFBaseData * DataFromString(const std::string& format);
virtual ~LDFBaseData() {}
virtual void WriteToPacket(RakNet::BitStream* packet) = 0;
virtual const std::u16string& GetKey() = 0;
virtual eLDFType GetValueType() = 0;
/** Gets a string from the key/value pair
* @param includeKey Whether or not to include the key in the data
* @param includeTypeId Whether or not to include the type id in the data
* @return The string representation of the data
*/
virtual std::string GetString(bool includeKey = true, bool includeTypeId = true) = 0;
virtual std::string GetValueAsString() = 0;
virtual LDFBaseData* Copy() = 0;
/**
* Given an input string, return the data as a LDF key.
*/
static LDFBaseData* DataFromString(const std::string_view& format);
};
//! A structure for an LDF key-value pair
template<typename T>
class LDFData : public LDFBaseData {
class LDFData: public LDFBaseData {
private:
std::u16string key;
T value;
//! Writes the key to the packet
void WriteKey(RakNet::BitStream * packet) {
packet->Write(static_cast<uint8_t>(this->key.length() * sizeof(uint16_t)));
for (uint32_t i = 0; i < this->key.length(); ++i) {
packet->Write(static_cast<uint16_t>(this->key[i]));
}
}
//! Writes the value to the packet
void WriteValue(RakNet::BitStream * packet) {
packet->Write(static_cast<uint8_t>(this->GetValueType()));
packet->Write(this->value);
}
std::u16string key;
T value;
//! Writes the key to the packet
void WriteKey(RakNet::BitStream* packet) {
packet->Write<uint8_t>(this->key.length() * sizeof(uint16_t));
for (uint32_t i = 0; i < this->key.length(); ++i) {
packet->Write<uint16_t>(this->key[i]);
}
}
//! Writes the value to the packet
void WriteValue(RakNet::BitStream* packet) {
packet->Write<uint8_t>(this->GetValueType());
packet->Write(this->value);
}
public:
//! Initializer
LDFData(const std::u16string& key, const T& value) {
this->key = key;
this->value = value;
}
//! Destructor
~LDFData(void) override { }
//! Gets the value
/*!
\return The value
*/
const T& GetValue(void) { return this->value; }
//! Sets the value
/*!
\param value The value to set to
*/
void SetValue(T value) { this->value = value; };
//! Gets the value string
/*!
\return The value string
*/
std::string GetValueString(void) { return ""; }
//! Writes the data to a packet
/*!
\param packet The packet
*/
void WriteToPacket(RakNet::BitStream * packet) override {
this->WriteKey(packet);
this->WriteValue(packet);
}
//! Gets the key
/*!
\return The key
*/
const std::u16string& GetKey(void) override { return this->key; }
//! Gets the LDF Type
/*!
\return The LDF value type
*/
eLDFType GetValueType(void) override { return LDF_TYPE_UNKNOWN; }
//! Gets the string data
/*!
\param includeKey Whether or not to include the key in the data
\param includeTypeId Whether or not to include the type id in the data
\return The string representation of the data
*/
std::string GetString(const bool includeKey = true, const bool includeTypeId = true) override {
if (GetValueType() == -1) {
return GeneralUtils::UTF16ToWTF8(this->key) + "=-1:<server variable>";
}
//! Initializer
LDFData(const std::u16string& key, const T& value) {
this->key = key;
this->value = value;
}
std::stringstream stream;
//! Destructor
~LDFData(void) override {}
if (includeKey) {
const std::string& sKey = GeneralUtils::UTF16ToWTF8(this->key, this->key.size());
stream << sKey << "=";
}
//! Gets the value
/*!
\return The value
*/
const T& GetValue(void) { return this->value; }
if (includeTypeId) {
const std::string& sType = std::to_string(this->GetValueType());
//! Sets the value
/*!
\param value The value to set to
*/
void SetValue(T value) { this->value = value; };
stream << sType << ":";
}
//! Gets the value string
/*!
\return The value string
*/
std::string GetValueString(void) { return ""; }
const std::string& sData = this->GetValueString();
stream << sData;
//! Writes the data to a packet
/*!
\param packet The packet
*/
void WriteToPacket(RakNet::BitStream* packet) override {
this->WriteKey(packet);
this->WriteValue(packet);
}
return stream.str();
}
std::string GetValueAsString() override {
return this->GetValueString();
}
LDFBaseData * Copy() override {
return new LDFData<T>(key, value);
}
inline static T Default = {};
//! Gets the key
/*!
\return The key
*/
const std::u16string& GetKey(void) override { return this->key; }
//! Gets the LDF Type
/*!
\return The LDF value type
*/
eLDFType GetValueType(void) override { return LDF_TYPE_UNKNOWN; }
//! Gets the string data
/*!
\param includeKey Whether or not to include the key in the data
\param includeTypeId Whether or not to include the type id in the data
\return The string representation of the data
*/
std::string GetString(const bool includeKey = true, const bool includeTypeId = true) override {
if (GetValueType() == -1) {
return GeneralUtils::UTF16ToWTF8(this->key) + "=-1:<server variable>";
}
std::stringstream stream;
if (includeKey) {
const std::string& sKey = GeneralUtils::UTF16ToWTF8(this->key, this->key.size());
stream << sKey << '=';
}
if (includeTypeId) {
stream << this->GetValueType() << ':';
}
const std::string& sData = this->GetValueString();
stream << sData;
return stream.str();
}
std::string GetValueAsString() override {
return this->GetValueString();
}
LDFBaseData* Copy() override {
return new LDFData<T>(key, value);
}
inline static T Default = {};
};
// LDF Types
@@ -206,48 +178,46 @@ template<> inline eLDFType LDFData<std::string>::GetValueType(void) { return LDF
// The specialized version for std::u16string (UTF-16)
template<>
inline void LDFData<std::u16string>::WriteValue(RakNet::BitStream * packet) {
packet->Write(static_cast<uint8_t>(this->GetValueType()));
packet->Write(static_cast<uint32_t>(this->value.length()));
for (uint32_t i = 0; i < this->value.length(); ++i) {
packet->Write(static_cast<uint16_t>(this->value[i]));
}
inline void LDFData<std::u16string>::WriteValue(RakNet::BitStream* packet) {
packet->Write<uint8_t>(this->GetValueType());
packet->Write<uint32_t>(this->value.length());
for (uint32_t i = 0; i < this->value.length(); ++i) {
packet->Write<uint16_t>(this->value[i]);
}
}
// The specialized version for bool
template<>
inline void LDFData<bool>::WriteValue(RakNet::BitStream * packet) {
packet->Write(static_cast<uint8_t>(this->GetValueType()));
packet->Write(static_cast<uint8_t>(this->value));
inline void LDFData<bool>::WriteValue(RakNet::BitStream* packet) {
packet->Write<uint8_t>(this->GetValueType());
packet->Write<uint8_t>(this->value);
}
// The specialized version for std::string (UTF-8)
template<>
inline void LDFData<std::string>::WriteValue(RakNet::BitStream * packet) {
packet->Write(static_cast<uint8_t>(this->GetValueType()));
packet->Write(static_cast<uint32_t>(this->value.length()));
for (uint32_t i = 0; i < this->value.length(); ++i) {
packet->Write(static_cast<uint8_t>(this->value[i]));
}
inline void LDFData<std::string>::WriteValue(RakNet::BitStream* packet) {
packet->Write<uint8_t>(this->GetValueType());
packet->Write<uint32_t>(this->value.length());
for (uint32_t i = 0; i < this->value.length(); ++i) {
packet->Write<uint8_t>(this->value[i]);
}
}
// MARK: String Data
template<> inline std::string LDFData<std::u16string>::GetValueString(void) {
//std::string toReturn(this->value.begin(), this->value.end());
//return toReturn;
template<> inline std::string LDFData<std::u16string>::GetValueString() {
return GeneralUtils::UTF16ToWTF8(this->value, this->value.size());
}
template<> inline std::string LDFData<int32_t>::GetValueString(void) { return std::to_string(this->value); }
template<> inline std::string LDFData<float>::GetValueString(void) { return std::to_string(this->value); }
template<> inline std::string LDFData<double>::GetValueString(void) { return std::to_string(this->value); }
template<> inline std::string LDFData<uint32_t>::GetValueString(void) { return std::to_string(this->value); }
template<> inline std::string LDFData<bool>::GetValueString(void) { return std::to_string(this->value); }
template<> inline std::string LDFData<uint64_t>::GetValueString(void) { return std::to_string(this->value); }
template<> inline std::string LDFData<LWOOBJID>::GetValueString(void) { return std::to_string(this->value); }
template<> inline std::string LDFData<int32_t>::GetValueString() { return std::to_string(this->value); }
template<> inline std::string LDFData<float>::GetValueString() { return std::to_string(this->value); }
template<> inline std::string LDFData<double>::GetValueString() { return std::to_string(this->value); }
template<> inline std::string LDFData<uint32_t>::GetValueString() { return std::to_string(this->value); }
template<> inline std::string LDFData<bool>::GetValueString() { return std::to_string(this->value); }
template<> inline std::string LDFData<uint64_t>::GetValueString() { return std::to_string(this->value); }
template<> inline std::string LDFData<LWOOBJID>::GetValueString() { return std::to_string(this->value); }
template<> inline std::string LDFData<std::string>::GetValueString(void) { return this->value; }
template<> inline std::string LDFData<std::string>::GetValueString() { return this->value; }
#endif //!__LDFFORMAT__H__

98
dCommon/Logger.cpp Normal file
View File

@@ -0,0 +1,98 @@
#include "Logger.h"
#include <algorithm>
#include <ctime>
#include <filesystem>
#include <stdarg.h>
Writer::~Writer() {
// Flush before we close
Flush();
// 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 || !m_Enabled) 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

@@ -1,36 +1,36 @@
/* MD5
converted to C++ class by Frank Thilo (thilo@unix-ag.org)
for bzflag (http://www.bzflag.org)
based on:
md5.h and md5.c
reference implemantion of RFC 1321
Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
/* interface header */
/* interface header */
#include "MD5.h"
/* system implementation headers */
@@ -59,304 +59,290 @@
// F, G, H and I are basic MD5 functions.
inline MD5::uint4 MD5::F(uint4 x, uint4 y, uint4 z) {
return x&y | ~x&z;
return x & y | ~x & z;
}
inline MD5::uint4 MD5::G(uint4 x, uint4 y, uint4 z) {
return x&z | y&~z;
return x & z | y & ~z;
}
inline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z) {
return x^y^z;
return x ^ y ^ z;
}
inline MD5::uint4 MD5::I(uint4 x, uint4 y, uint4 z) {
return y ^ (x | ~z);
return y ^ (x | ~z);
}
// rotate_left rotates x left n bits.
inline MD5::uint4 MD5::rotate_left(uint4 x, int n) {
return (x << n) | (x >> (32 - n));
return (x << n) | (x >> (32 - n));
}
// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
// Rotation is separate from addition to prevent recomputation.
inline void MD5::FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
a = rotate_left(a + F(b, c, d) + x + ac, s) + b;
inline void MD5::FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
a = rotate_left(a + F(b, c, d) + x + ac, s) + b;
}
inline void MD5::GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
a = rotate_left(a + G(b, c, d) + x + ac, s) + b;
inline void MD5::GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
a = rotate_left(a + G(b, c, d) + x + ac, s) + b;
}
inline void MD5::HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
a = rotate_left(a + H(b, c, d) + x + ac, s) + b;
inline void MD5::HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
a = rotate_left(a + H(b, c, d) + x + ac, s) + b;
}
inline void MD5::II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
a = rotate_left(a + I(b, c, d) + x + ac, s) + b;
inline void MD5::II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
a = rotate_left(a + I(b, c, d) + x + ac, s) + b;
}
//////////////////////////////////////////////
// default ctor, just initailize
MD5::MD5()
{
init();
MD5::MD5() {
init();
}
//////////////////////////////////////////////
// nifty shortcut ctor, compute MD5 for string and finalize it right away
MD5::MD5(const std::string &text)
{
init();
update(text.c_str(), text.length());
finalize();
MD5::MD5(const std::string& text) {
init();
update(text.c_str(), text.length());
finalize();
}
//////////////////////////////
void MD5::init()
{
finalized = false;
count[0] = 0;
count[1] = 0;
// load magic initialization constants.
state[0] = 0x67452301;
state[1] = 0xefcdab89;
state[2] = 0x98badcfe;
state[3] = 0x10325476;
void MD5::init() {
finalized = false;
count[0] = 0;
count[1] = 0;
// load magic initialization constants.
state[0] = 0x67452301;
state[1] = 0xefcdab89;
state[2] = 0x98badcfe;
state[3] = 0x10325476;
}
//////////////////////////////
// decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4.
void MD5::decode(uint4 output[], const uint1 input[], size_type len)
{
for (unsigned int i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((uint4)input[j]) | (((uint4)input[j + 1]) << 8) |
(((uint4)input[j + 2]) << 16) | (((uint4)input[j + 3]) << 24);
void MD5::decode(uint4 output[], const uint1 input[], size_type len) {
for (unsigned int i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((uint4)input[j]) | (((uint4)input[j + 1]) << 8) |
(((uint4)input[j + 2]) << 16) | (((uint4)input[j + 3]) << 24);
}
//////////////////////////////
// encodes input (uint4) into output (unsigned char). Assumes len is
// a multiple of 4.
void MD5::encode(uint1 output[], const uint4 input[], size_type len)
{
for (size_type i = 0, j = 0; j < len; i++, j += 4) {
output[j] = input[i] & 0xff;
output[j + 1] = (input[i] >> 8) & 0xff;
output[j + 2] = (input[i] >> 16) & 0xff;
output[j + 3] = (input[i] >> 24) & 0xff;
}
void MD5::encode(uint1 output[], const uint4 input[], size_type len) {
for (size_type i = 0, j = 0; j < len; i++, j += 4) {
output[j] = input[i] & 0xff;
output[j + 1] = (input[i] >> 8) & 0xff;
output[j + 2] = (input[i] >> 16) & 0xff;
output[j + 3] = (input[i] >> 24) & 0xff;
}
}
//////////////////////////////
// apply MD5 algo on a block
void MD5::transform(const uint1 block[blocksize])
{
uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
decode(x, block, blocksize);
/* Round 1 */
FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
// Zeroize sensitive information.
memset(x, 0, sizeof x);
void MD5::transform(const uint1 block[blocksize]) {
uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
decode(x, block, blocksize);
/* Round 1 */
FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
// Zeroize sensitive information.
memset(x, 0, sizeof x);
}
//////////////////////////////
// MD5 block update operation. Continues an MD5 message-digest
// operation, processing another message block
void MD5::update(const unsigned char input[], size_type length)
{
// compute number of bytes mod 64
size_type index = count[0] / 8 % blocksize;
// Update number of bits
if ((count[0] += (length << 3)) < (length << 3))
count[1]++;
count[1] += (length >> 29);
// number of bytes we need to fill in buffer
size_type firstpart = 64 - index;
size_type i;
// transform as many times as possible.
if (length >= firstpart)
{
// fill buffer first, transform
memcpy(&buffer[index], input, firstpart);
transform(buffer);
// transform chunks of blocksize (64 bytes)
for (i = firstpart; i + blocksize <= length; i += blocksize)
transform(&input[i]);
index = 0;
}
else
i = 0;
// buffer remaining input
memcpy(&buffer[index], &input[i], length - i);
void MD5::update(const unsigned char input[], size_type length) {
// compute number of bytes mod 64
size_type index = count[0] / 8 % blocksize;
// Update number of bits
if ((count[0] += (length << 3)) < (length << 3))
count[1]++;
count[1] += (length >> 29);
// number of bytes we need to fill in buffer
size_type firstpart = 64 - index;
size_type i;
// transform as many times as possible.
if (length >= firstpart) {
// fill buffer first, transform
memcpy(&buffer[index], input, firstpart);
transform(buffer);
// transform chunks of blocksize (64 bytes)
for (i = firstpart; i + blocksize <= length; i += blocksize)
transform(&input[i]);
index = 0;
} else
i = 0;
// buffer remaining input
memcpy(&buffer[index], &input[i], length - i);
}
//////////////////////////////
// for convenience provide a verson with signed char
void MD5::update(const char input[], size_type length)
{
update((const unsigned char*)input, length);
void MD5::update(const char input[], size_type length) {
update((const unsigned char*)input, length);
}
//////////////////////////////
// MD5 finalization. Ends an MD5 message-digest operation, writing the
// the message digest and zeroizing the context.
MD5& MD5::finalize()
{
static unsigned char padding[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
if (!finalized) {
// Save number of bits
unsigned char bits[8];
encode(bits, count, 8);
// pad out to 56 mod 64.
size_type index = count[0] / 8 % 64;
size_type padLen = (index < 56) ? (56 - index) : (120 - index);
update(padding, padLen);
// Append length (before padding)
update(bits, 8);
// Store state in digest
encode(digest, state, 16);
// Zeroize sensitive information.
memset(buffer, 0, sizeof buffer);
memset(count, 0, sizeof count);
finalized = true;
}
return *this;
MD5& MD5::finalize() {
static unsigned char padding[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
if (!finalized) {
// Save number of bits
unsigned char bits[8];
encode(bits, count, 8);
// pad out to 56 mod 64.
size_type index = count[0] / 8 % 64;
size_type padLen = (index < 56) ? (56 - index) : (120 - index);
update(padding, padLen);
// Append length (before padding)
update(bits, 8);
// Store state in digest
encode(digest, state, 16);
// Zeroize sensitive information.
memset(buffer, 0, sizeof buffer);
memset(count, 0, sizeof count);
finalized = true;
}
return *this;
}
//////////////////////////////
// return hex representation of digest as string
std::string MD5::hexdigest() const
{
if (!finalized)
return "";
char buf[33];
for (int i = 0; i<16; i++)
sprintf(buf + i * 2, "%02x", digest[i]);
buf[32] = 0;
return std::string(buf);
std::string MD5::hexdigest() const {
if (!finalized)
return "";
char buf[33];
for (int i = 0; i < 16; i++)
sprintf(buf + i * 2, "%02x", digest[i]);
buf[32] = 0;
return std::string(buf);
}
//////////////////////////////
std::ostream& operator<<(std::ostream& out, MD5 md5)
{
return out << md5.hexdigest();
std::ostream& operator<<(std::ostream& out, MD5 md5) {
return out << md5.hexdigest();
}
//////////////////////////////
std::string md5(const std::string str)
{
MD5 md5 = MD5(str);
return md5.hexdigest();
std::string md5(const std::string str) {
MD5 md5 = MD5(str);
return md5.hexdigest();
}

View File

@@ -1,33 +1,33 @@
/* MD5
converted to C++ class by Frank Thilo (thilo@unix-ag.org)
for bzflag (http://www.bzflag.org)
based on:
md5.h and md5.c
reference implementation of RFC 1321
Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
#ifndef BZF_MD5_H
@@ -37,55 +37,55 @@
#include <iostream>
// a small class for calculating MD5 hashes of strings or byte arrays
// it is not meant to be fast or secure
//
// usage: 1) feed it blocks of uchars with update()
// 2) finalize()
// 3) get hexdigest() string
// or
// MD5(std::string).hexdigest()
//
// assumes that char is 8 bit and int is 32 bit
// a small class for calculating MD5 hashes of strings or byte arrays
// it is not meant to be fast or secure
//
// usage: 1) feed it blocks of uchars with update()
// 2) finalize()
// 3) get hexdigest() string
// or
// MD5(std::string).hexdigest()
//
// assumes that char is 8 bit and int is 32 bit
class MD5
{
public:
typedef unsigned int size_type; // must be 32bit
MD5();
MD5(const std::string& text);
void update(const unsigned char *buf, size_type length);
void update(const char *buf, size_type length);
MD5& finalize();
std::string hexdigest() const;
friend std::ostream& operator<<(std::ostream&, MD5 md5);
typedef unsigned int size_type; // must be 32bit
MD5();
MD5(const std::string& text);
void update(const unsigned char* buf, size_type length);
void update(const char* buf, size_type length);
MD5& finalize();
std::string hexdigest() const;
friend std::ostream& operator<<(std::ostream&, MD5 md5);
private:
void init();
typedef unsigned char uint1; // 8bit
typedef unsigned int uint4; // 32bit
enum { blocksize = 64 }; // VC6 won't eat a const static int here
void transform(const uint1 block[blocksize]);
static void decode(uint4 output[], const uint1 input[], size_type len);
static void encode(uint1 output[], const uint4 input[], size_type len);
bool finalized;
uint1 buffer[blocksize]; // bytes that didn't fit in last 64 byte chunk
uint4 count[2]; // 64bit counter for number of bits (lo, hi)
uint4 state[4]; // digest so far
uint1 digest[16]; // the result
// low level logic operations
static inline uint4 F(uint4 x, uint4 y, uint4 z);
static inline uint4 G(uint4 x, uint4 y, uint4 z);
static inline uint4 H(uint4 x, uint4 y, uint4 z);
static inline uint4 I(uint4 x, uint4 y, uint4 z);
static inline uint4 rotate_left(uint4 x, int n);
static inline void FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
static inline void GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
static inline void HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
static inline void II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
void init();
typedef unsigned char uint1; // 8bit
typedef unsigned int uint4; // 32bit
enum { blocksize = 64 }; // VC6 won't eat a const static int here
void transform(const uint1 block[blocksize]);
static void decode(uint4 output[], const uint1 input[], size_type len);
static void encode(uint1 output[], const uint4 input[], size_type len);
bool finalized;
uint1 buffer[blocksize]; // bytes that didn't fit in last 64 byte chunk
uint4 count[2]; // 64bit counter for number of bits (lo, hi)
uint4 state[4]; // digest so far
uint1 digest[16]; // the result
// low level logic operations
static inline uint4 F(uint4 x, uint4 y, uint4 z);
static inline uint4 G(uint4 x, uint4 y, uint4 z);
static inline uint4 H(uint4 x, uint4 y, uint4 z);
static inline uint4 I(uint4 x, uint4 y, uint4 z);
static inline uint4 rotate_left(uint4 x, int n);
static inline void FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
static inline void GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
static inline void HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
static inline void II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
};
std::string md5(const std::string str);

View File

@@ -4,174 +4,150 @@
std::unordered_map<MetricVariable, Metric*> Metrics::m_Metrics = {};
std::vector<MetricVariable> Metrics::m_Variables = {
MetricVariable::GameLoop,
MetricVariable::PacketHandling,
MetricVariable::UpdateEntities,
MetricVariable::UpdateSpawners,
MetricVariable::Physics,
MetricVariable::UpdateReplica,
MetricVariable::Ghosting,
MetricVariable::CPUTime,
MetricVariable::Sleep,
MetricVariable::Frame,
MetricVariable::GameLoop,
MetricVariable::PacketHandling,
MetricVariable::UpdateEntities,
MetricVariable::UpdateSpawners,
MetricVariable::Physics,
MetricVariable::UpdateReplica,
MetricVariable::Ghosting,
MetricVariable::CPUTime,
MetricVariable::Sleep,
MetricVariable::Frame,
};
void Metrics::AddMeasurement(MetricVariable variable, int64_t value)
{
const auto& iter = m_Metrics.find(variable);
void Metrics::AddMeasurement(MetricVariable variable, int64_t value) {
const auto& iter = m_Metrics.find(variable);
Metric* metric;
Metric* metric;
if (iter == m_Metrics.end())
{
metric = new Metric();
if (iter == m_Metrics.end()) {
metric = new Metric();
m_Metrics[variable] = metric;
}
else
{
metric = iter->second;
}
m_Metrics[variable] = metric;
} else {
metric = iter->second;
}
AddMeasurement(metric, value);
AddMeasurement(metric, value);
}
void Metrics::AddMeasurement(Metric* metric, int64_t value)
{
const auto index = metric->measurementIndex;
void Metrics::AddMeasurement(Metric* metric, int64_t value) {
const auto index = metric->measurementIndex;
metric->measurements[index] = value;
metric->measurements[index] = value;
if (metric->max == -1 || value > metric->max)
{
metric->max = value;
}
else if (metric->min == -1 || metric->min > value)
{
metric->min = value;
}
if (metric->max == -1 || value > metric->max) {
metric->max = value;
} else if (metric->min == -1 || metric->min > value) {
metric->min = value;
}
if (metric->measurementSize < MAX_MEASURMENT_POINTS)
{
metric->measurementSize++;
}
if (metric->measurementSize < MAX_MEASURMENT_POINTS) {
metric->measurementSize++;
}
metric->measurementIndex = (index + 1) % MAX_MEASURMENT_POINTS;
metric->measurementIndex = (index + 1) % MAX_MEASURMENT_POINTS;
}
const Metric* Metrics::GetMetric(MetricVariable variable)
{
const auto& iter = m_Metrics.find(variable);
const Metric* Metrics::GetMetric(MetricVariable variable) {
const auto& iter = m_Metrics.find(variable);
if (iter == m_Metrics.end())
{
return nullptr;
}
if (iter == m_Metrics.end()) {
return nullptr;
}
Metric* metric = iter->second;
Metric* metric = iter->second;
int64_t average = 0;
int64_t average = 0;
for (size_t i = 0; i < metric->measurementSize; i++)
{
average += metric->measurements[i];
}
for (size_t i = 0; i < metric->measurementSize; i++) {
average += metric->measurements[i];
}
average /= metric->measurementSize;
average /= metric->measurementSize;
metric->average = average;
return metric;
metric->average = average;
return metric;
}
void Metrics::StartMeasurement(MetricVariable variable)
{
const auto& iter = m_Metrics.find(variable);
void Metrics::StartMeasurement(MetricVariable variable) {
const auto& iter = m_Metrics.find(variable);
Metric* metric;
Metric* metric;
if (iter == m_Metrics.end())
{
metric = new Metric();
if (iter == m_Metrics.end()) {
metric = new Metric();
m_Metrics[variable] = metric;
}
else
{
metric = iter->second;
}
m_Metrics[variable] = metric;
} else {
metric = iter->second;
}
metric->activeMeasurement = std::chrono::high_resolution_clock::now();
metric->activeMeasurement = std::chrono::high_resolution_clock::now();
}
void Metrics::EndMeasurement(MetricVariable variable)
{
const auto end = std::chrono::high_resolution_clock::now();
void Metrics::EndMeasurement(MetricVariable variable) {
const auto end = std::chrono::high_resolution_clock::now();
const auto& iter = m_Metrics.find(variable);
const auto& iter = m_Metrics.find(variable);
if (iter == m_Metrics.end())
{
return;
}
if (iter == m_Metrics.end()) {
return;
}
Metric* metric = iter->second;
Metric* metric = iter->second;
const auto elapsed = end - metric->activeMeasurement;
const auto elapsed = end - metric->activeMeasurement;
const auto nanoseconds = std::chrono::duration_cast<std::chrono::nanoseconds>(elapsed).count();
const auto nanoseconds = std::chrono::duration_cast<std::chrono::nanoseconds>(elapsed).count();
AddMeasurement(metric, nanoseconds);
AddMeasurement(metric, nanoseconds);
}
float Metrics::ToMiliseconds(int64_t nanoseconds)
{
return (float) nanoseconds / 1e6;
float Metrics::ToMiliseconds(int64_t nanoseconds) {
return static_cast<float>(nanoseconds) / 1e6;
}
std::string Metrics::MetricVariableToString(MetricVariable variable)
{
switch (variable)
{
case MetricVariable::GameLoop:
return "GameLoop";
case MetricVariable::PacketHandling:
return "PacketHandling";
case MetricVariable::UpdateEntities:
return "UpdateEntities";
case MetricVariable::UpdateSpawners:
return "UpdateSpawners";
case MetricVariable::Physics:
return "Physics";
case MetricVariable::UpdateReplica:
return "UpdateReplica";
case MetricVariable::Sleep:
return "Sleep";
case MetricVariable::CPUTime:
return "CPUTime";
case MetricVariable::Frame:
return "Frame";
case MetricVariable::Ghosting:
return "Ghosting";
default:
return "Invalid";
}
std::string Metrics::MetricVariableToString(MetricVariable variable) {
switch (variable) {
case MetricVariable::GameLoop:
return "GameLoop";
case MetricVariable::PacketHandling:
return "PacketHandling";
case MetricVariable::UpdateEntities:
return "UpdateEntities";
case MetricVariable::UpdateSpawners:
return "UpdateSpawners";
case MetricVariable::Physics:
return "Physics";
case MetricVariable::UpdateReplica:
return "UpdateReplica";
case MetricVariable::Sleep:
return "Sleep";
case MetricVariable::CPUTime:
return "CPUTime";
case MetricVariable::Frame:
return "Frame";
case MetricVariable::Ghosting:
return "Ghosting";
default:
return "Invalid";
}
}
const std::vector<MetricVariable>& Metrics::GetAllMetrics()
{
return m_Variables;
const std::vector<MetricVariable>& Metrics::GetAllMetrics() {
return m_Variables;
}
void Metrics::Clear()
{
for (const auto& pair : m_Metrics)
{
delete pair.second;
}
m_Metrics.clear();
void Metrics::Clear() {
for (const auto& pair : m_Metrics) {
delete pair.second;
}
m_Metrics.clear();
}
/* RSS Memory utilities
@@ -207,46 +183,44 @@ void Metrics::Clear()
#error "Cannot define getPeakRSS( ) or getCurrentRSS( ) for an unknown OS."
#endif
/**
* Returns the peak (maximum so far) resident set size (physical
* memory use) measured in bytes, or zero if the value cannot be
* determined on this OS.
*/
size_t Metrics::GetPeakRSS()
{
/**
* Returns the peak (maximum so far) resident set size (physical
* memory use) measured in bytes, or zero if the value cannot be
* determined on this OS.
*/
size_t Metrics::GetPeakRSS() {
#if defined(_WIN32)
/* Windows -------------------------------------------------- */
PROCESS_MEMORY_COUNTERS info;
GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
return (size_t)info.PeakWorkingSetSize;
/* Windows -------------------------------------------------- */
PROCESS_MEMORY_COUNTERS info;
GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info));
return static_cast<size_t>(info.PeakWorkingSetSize);
#elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
/* AIX and Solaris ------------------------------------------ */
struct psinfo psinfo;
int fd = -1;
if ( (fd = open( "/proc/self/psinfo", O_RDONLY )) == -1 )
return (size_t)0L; /* Can't open? */
if ( read( fd, &psinfo, sizeof(psinfo) ) != sizeof(psinfo) )
{
close( fd );
return (size_t)0L; /* Can't read? */
}
close( fd );
return (size_t)(psinfo.pr_rssize * 1024L);
/* AIX and Solaris ------------------------------------------ */
struct psinfo psinfo;
int fd = -1;
if ((fd = open("/proc/self/psinfo", O_RDONLY)) == -1)
return static_cast<size_t>(0L); /* Can't open? */
if (read(fd, &psinfo, sizeof(psinfo)) != sizeof(psinfo)) {
close(fd);
return static_cast<size_t>(0L); /* Can't read? */
}
close(fd);
return static_cast<size_t>(psinfo.pr_rssize * 1024L);
#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
/* BSD, Linux, and OSX -------------------------------------- */
struct rusage rusage;
getrusage( RUSAGE_SELF, &rusage );
/* BSD, Linux, and OSX -------------------------------------- */
struct rusage rusage;
getrusage(RUSAGE_SELF, &rusage);
#if defined(__APPLE__) && defined(__MACH__)
return (size_t)rusage.ru_maxrss;
return static_cast<size_t>(rusage.ru_maxrss);
#else
return (size_t)(rusage.ru_maxrss * 1024L);
return static_cast<size_t>(rusage.ru_maxrss * 1024L);
#endif
#else
/* Unknown OS ----------------------------------------------- */
return (size_t)0L; /* Unsupported. */
/* Unknown OS ----------------------------------------------- */
return static_cast<size_t>(0L); /* Unsupported. */
#endif
}
@@ -255,49 +229,46 @@ size_t Metrics::GetPeakRSS()
* Returns the current resident set size (physical memory use) measured
* in bytes, or zero if the value cannot be determined on this OS.
*/
size_t Metrics::GetCurrentRSS()
{
size_t Metrics::GetCurrentRSS() {
#if defined(_WIN32)
/* Windows -------------------------------------------------- */
PROCESS_MEMORY_COUNTERS info;
GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
return (size_t)info.WorkingSetSize;
/* Windows -------------------------------------------------- */
PROCESS_MEMORY_COUNTERS info;
GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info));
return static_cast<size_t>(info.WorkingSetSize);
#elif defined(__APPLE__) && defined(__MACH__)
/* OSX ------------------------------------------------------ */
struct mach_task_basic_info info;
mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
if ( task_info( mach_task_self( ), MACH_TASK_BASIC_INFO,
(task_info_t)&info, &infoCount ) != KERN_SUCCESS )
return (size_t)0L; /* Can't access? */
return (size_t)info.resident_size;
/* OSX ------------------------------------------------------ */
struct mach_task_basic_info info;
mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO,
reinterpret_cast<task_info_t>(&info), &infoCount) != KERN_SUCCESS)
return static_cast<size_t>(0L); /* Can't access? */
return static_cast<size_t>(info.resident_size);
#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
/* Linux ---------------------------------------------------- */
long rss = 0L;
FILE* fp = NULL;
if ( (fp = fopen( "/proc/self/statm", "r" )) == NULL )
return (size_t)0L; /* Can't open? */
if ( fscanf( fp, "%*s%ld", &rss ) != 1 )
{
fclose( fp );
return (size_t)0L; /* Can't read? */
}
fclose( fp );
return (size_t)rss * (size_t)sysconf( _SC_PAGESIZE);
/* Linux ---------------------------------------------------- */
long rss = 0L;
FILE* fp = NULL;
if ((fp = fopen("/proc/self/statm", "r")) == NULL)
return static_cast<size_t>(0L); /* Can't open? */
if (fscanf(fp, "%*s%ld", &rss) != 1) {
fclose(fp);
return static_cast<size_t>(0L); /* Can't read? */
}
fclose(fp);
return static_cast<size_t>(rss) * static_cast<size_t>(sysconf(_SC_PAGESIZE));
#else
/* AIX, BSD, Solaris, and Unknown OS ------------------------ */
return (size_t)0L; /* Unsupported. */
/* AIX, BSD, Solaris, and Unknown OS ------------------------ */
return static_cast<size_t>(0L); /* Unsupported. */
#endif
}
size_t Metrics::GetProcessID()
{
size_t Metrics::GetProcessID() {
#if defined(_WIN32)
return GetCurrentProcessId();
return GetCurrentProcessId();
#else
return getpid();
return getpid();
#endif
}

View File

@@ -10,52 +10,52 @@
enum class MetricVariable : int32_t
{
GameLoop,
PacketHandling,
UpdateEntities,
UpdateSpawners,
Physics,
UpdateReplica,
Ghosting,
CPUTime,
Sleep,
Frame,
GameLoop,
PacketHandling,
UpdateEntities,
UpdateSpawners,
Physics,
UpdateReplica,
Ghosting,
CPUTime,
Sleep,
Frame,
};
struct Metric
{
int64_t measurements[MAX_MEASURMENT_POINTS] = {};
size_t measurementIndex = 0;
size_t measurementSize = 0;
int64_t max = -1;
int64_t min = -1;
int64_t average = 0;
std::chrono::time_point<std::chrono::high_resolution_clock> activeMeasurement;
int64_t measurements[MAX_MEASURMENT_POINTS] = {};
size_t measurementIndex = 0;
size_t measurementSize = 0;
int64_t max = -1;
int64_t min = -1;
int64_t average = 0;
std::chrono::time_point<std::chrono::high_resolution_clock> activeMeasurement;
};
class Metrics
{
public:
~Metrics();
~Metrics();
static void AddMeasurement(MetricVariable variable, int64_t value);
static void AddMeasurement(Metric* metric, int64_t value);
static const Metric* GetMetric(MetricVariable variable);
static void StartMeasurement(MetricVariable variable);
static void EndMeasurement(MetricVariable variable);
static float ToMiliseconds(int64_t nanoseconds);
static std::string MetricVariableToString(MetricVariable variable);
static const std::vector<MetricVariable>& GetAllMetrics();
static void AddMeasurement(MetricVariable variable, int64_t value);
static void AddMeasurement(Metric* metric, int64_t value);
static const Metric* GetMetric(MetricVariable variable);
static void StartMeasurement(MetricVariable variable);
static void EndMeasurement(MetricVariable variable);
static float ToMiliseconds(int64_t nanoseconds);
static std::string MetricVariableToString(MetricVariable variable);
static const std::vector<MetricVariable>& GetAllMetrics();
static size_t GetPeakRSS();
static size_t GetCurrentRSS();
static size_t GetProcessID();
static size_t GetPeakRSS();
static size_t GetCurrentRSS();
static size_t GetProcessID();
static void Clear();
static void Clear();
private:
Metrics();
Metrics();
static std::unordered_map<MetricVariable, Metric*> m_Metrics;
static std::vector<MetricVariable> m_Variables;
static std::unordered_map<MetricVariable, Metric*> m_Metrics;
static std::vector<MetricVariable> m_Variables;
};

View File

@@ -13,23 +13,23 @@ const NiPoint3 NiPoint3::UNIT_ALL(1.0f, 1.0f, 1.0f);
//! Initializer
NiPoint3::NiPoint3(void) {
this->x = 0;
this->y = 0;
this->z = 0;
this->x = 0;
this->y = 0;
this->z = 0;
}
//! Initializer
NiPoint3::NiPoint3(float x, float y, float z) {
this->x = x;
this->y = y;
this->z = z;
this->x = x;
this->y = y;
this->z = z;
}
//! Copy Constructor
NiPoint3::NiPoint3(const NiPoint3& point) {
this->x = point.x;
this->y = point.y;
this->z = point.z;
this->x = point.x;
this->y = point.y;
this->z = point.z;
}
//! Destructor
@@ -39,68 +39,63 @@ NiPoint3::~NiPoint3(void) {}
//! Gets the X coordinate
float NiPoint3::GetX(void) const {
return this->x;
return this->x;
}
//! Sets the X coordinate
void NiPoint3::SetX(float x) {
this->x = x;
this->x = x;
}
//! Gets the Y coordinate
float NiPoint3::GetY(void) const {
return this->y;
return this->y;
}
//! Sets the Y coordinate
void NiPoint3::SetY(float y) {
this->y = y;
this->y = y;
}
//! Gets the Z coordinate
float NiPoint3::GetZ(void) const {
return this->z;
return this->z;
}
//! Sets the Z coordinate
void NiPoint3::SetZ(float z) {
this->z = z;
this->z = z;
}
// MARK: Functions
//! Gets the length of the vector
float NiPoint3::Length(void) const {
return sqrt(x*x + y*y + z*z);
return sqrt(x * x + y * y + z * z);
}
//! Gets the squared length of a vector
float NiPoint3::SquaredLength(void) const {
return (x*x + y*y + z*z);
return (x * x + y * y + z * z);
}
//! Returns the dot product of the vector dotted with another vector
float NiPoint3::DotProduct(const Vector3& vec) const {
return ((this->x * vec.x) + (this->y * vec.y) + (this->z * vec.z));
return ((this->x * vec.x) + (this->y * vec.y) + (this->z * vec.z));
}
//! Returns the cross product of the vector crossed with another vector
Vector3 NiPoint3::CrossProduct(const Vector3& vec) const {
return Vector3(((this->y * vec.z) - (this->z * vec.y)),
((this->z * vec.x) - (this->x * vec.z)),
((this->x * vec.y) - (this->y * vec.x)));
return Vector3(((this->y * vec.z) - (this->z * vec.y)),
((this->z * vec.x) - (this->x * vec.z)),
((this->x * vec.y) - (this->y * vec.x)));
}
//! Unitize the vector
NiPoint3 NiPoint3::Unitize(void) const {
NiPoint3 unitVec;
float length = this->Length();
float length = this->Length();
unitVec.x = length != 0 ? this->x / length : 0;
unitVec.y = length != 0 ? this->y / length : 0;
unitVec.z = length != 0 ? this->z / length : 0;
return unitVec;
return length != 0 ? *this / length : NiPoint3::ZERO;
}
@@ -108,57 +103,72 @@ NiPoint3 NiPoint3::Unitize(void) const {
//! Operator to check for equality
bool NiPoint3::operator==(const NiPoint3& point) const {
return point.x == this->x && point.y == this->y && point.z == this->z;
return point.x == this->x && point.y == this->y && point.z == this->z;
}
//! Operator to check for inequality
bool NiPoint3::operator!=(const NiPoint3& point) const {
return !(*this == point);
return !(*this == point);
}
//! Operator for subscripting
float& NiPoint3::operator[](int i) {
float * base = &x;
return (float&)base[i];
float* base = &x;
return base[i];
}
//! Operator for subscripting
const float& NiPoint3::operator[](int i) const {
const float * base = &x;
return (float&)base[i];
const float* base = &x;
return base[i];
}
//! Operator for addition of vectors
NiPoint3 NiPoint3::operator+(const NiPoint3& point) const {
return NiPoint3(this->x + point.x, this->y + point.y, this->z + point.z);
return NiPoint3(this->x + point.x, this->y + point.y, this->z + point.z);
}
//! Operator for addition of vectors
NiPoint3& NiPoint3::operator+=(const NiPoint3& point) {
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
NiPoint3 NiPoint3::operator-(const NiPoint3& point) const {
return NiPoint3(this->x - point.x, this->y - point.y, this->z - point.z);
return NiPoint3(this->x - point.x, this->y - point.y, this->z - point.z);
}
//! Operator for addition of a scalar on all vector components
NiPoint3 NiPoint3::operator+(float fScalar) const {
return NiPoint3(this->x + fScalar, this->y + fScalar, this->z + fScalar);
return NiPoint3(this->x + fScalar, this->y + fScalar, this->z + fScalar);
}
//! Operator for subtraction of a scalar on all vector components
NiPoint3 NiPoint3::operator-(float fScalar) const {
return NiPoint3(this->x - fScalar, this->y - fScalar, this->z - fScalar);
return NiPoint3(this->x - fScalar, this->y - fScalar, this->z - fScalar);
}
//! Operator for scalar multiplication of a vector
NiPoint3 NiPoint3::operator*(float fScalar) const {
return NiPoint3(this->x * fScalar, this->y * fScalar, this->z * fScalar);
return NiPoint3(this->x * fScalar, this->y * fScalar, this->z * fScalar);
}
//! Operator for scalar division of a vector
NiPoint3 NiPoint3::operator/(float fScalar) const {
float retX = this->x != 0 ? this->x / fScalar : 0;
float retY = this->y != 0 ? this->y / fScalar : 0;
float retZ = this->z != 0 ? this->z / fScalar : 0;
return NiPoint3(retX, retY, retZ);
float retX = this->x != 0 ? this->x / fScalar : 0;
float retY = this->y != 0 ? this->y / fScalar : 0;
float retZ = this->z != 0 ? this->z / fScalar : 0;
return NiPoint3(retX, retY, retZ);
}
@@ -166,96 +176,102 @@ NiPoint3 NiPoint3::operator/(float fScalar) const {
//! Checks to see if the point (or vector) is with an Axis-Aligned Bounding Box
bool NiPoint3::IsWithinAxisAlignedBox(const NiPoint3& minPoint, const NiPoint3& maxPoint) {
if (this->x < minPoint.x) return false;
if (this->x > maxPoint.x) return false;
if (this->y < minPoint.y) return false;
if (this->y > maxPoint.y) return false;
if (this->x < minPoint.x) return false;
if (this->x > maxPoint.x) return false;
if (this->y < minPoint.y) return false;
if (this->y > maxPoint.y) return false;
return (this->z < maxPoint.z && this->z > minPoint.z);
return (this->z < maxPoint.z && this->z > minPoint.z);
}
//! Checks to see if the point (or vector) is within a sphere
bool NiPoint3::IsWithinSpehere(const NiPoint3& sphereCenter, float radius) {
Vector3 diffVec = Vector3(x - sphereCenter.GetX(), y - sphereCenter.GetY(), z - sphereCenter.GetZ());
return (diffVec.SquaredLength() <= (radius * radius));
Vector3 diffVec = Vector3(x - sphereCenter.GetX(), y - sphereCenter.GetY(), z - sphereCenter.GetZ());
return (diffVec.SquaredLength() <= (radius * radius));
}
NiPoint3 NiPoint3::ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, const NiPoint3& p)
{
if (a == b) return a;
NiPoint3 NiPoint3::ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, const NiPoint3& p) {
if (a == b) return a;
const auto pa = p - a;
const auto ab = b - a;
const auto pa = p - a;
const auto ab = b - a;
const auto t = pa.DotProduct(ab) / ab.SquaredLength();
const auto t = pa.DotProduct(ab) / ab.SquaredLength();
if (t <= 0.0f) return a;
if (t >= 1.0f) return b;
return a + ab * t;
if (t <= 0.0f) return a;
if (t >= 1.0f) return b;
return a + ab * t;
}
float NiPoint3::Angle(const NiPoint3& a, const NiPoint3& b)
{
const auto dot = a.DotProduct(b);
const auto lenA = a.SquaredLength();
const auto lenB = a.SquaredLength();
return acos(dot / sqrt(lenA * lenB));
float NiPoint3::Angle(const NiPoint3& a, const NiPoint3& b) {
const auto dot = a.DotProduct(b);
const auto lenA = a.SquaredLength();
const auto lenB = a.SquaredLength();
return acos(dot / sqrt(lenA * lenB));
}
float NiPoint3::Distance(const NiPoint3& a, const NiPoint3& b)
{
const auto dx = a.x - b.x;
const auto dy = a.y - b.y;
const auto dz = a.z - b.z;
float NiPoint3::Distance(const NiPoint3& a, const NiPoint3& b) {
const auto dx = a.x - b.x;
const auto dy = a.y - b.y;
const auto dz = a.z - b.z;
return std::sqrt(dx * dx + dy * dy + dz * dz);
return std::sqrt(dx * dx + dy * dy + dz * dz);
}
float NiPoint3::DistanceSquared(const NiPoint3& a, const NiPoint3& b)
{
const auto dx = a.x - b.x;
const auto dy = a.y - b.y;
const auto dz = a.z - b.z;
float NiPoint3::DistanceSquared(const NiPoint3& a, const NiPoint3& b) {
const auto dx = a.x - b.x;
const auto dy = a.y - b.y;
const auto dz = a.z - b.z;
return dx * dx + dy * dy + dz * dz;
return dx * dx + dy * dy + dz * dz;
}
NiPoint3 NiPoint3::MoveTowards(const NiPoint3& current, const NiPoint3& target, float maxDistanceDelta)
{
float dx = target.x - current.x;
float dy = target.y - current.y;
float dz = target.z - current.z;
float lengthSquared = (float) ((double) dx * (double) dx + (double) dy * (double) dy + (double) dz * (double) dz);
if ((double) lengthSquared == 0.0 || (double) maxDistanceDelta >= 0.0 && (double) lengthSquared <= (double) maxDistanceDelta * (double) maxDistanceDelta)
return target;
float length = (float) std::sqrt((double) lengthSquared);
return NiPoint3(current.x + dx / length * maxDistanceDelta, current.y + dy / length * maxDistanceDelta, current.z + dz / length * maxDistanceDelta);
NiPoint3 NiPoint3::MoveTowards(const NiPoint3& current, const NiPoint3& target, float maxDistanceDelta) {
float dx = target.x - current.x;
float dy = target.y - current.y;
float dz = target.z - current.z;
float lengthSquared = static_cast<float>(
static_cast<double>(dx) * static_cast<double>(dx) +
static_cast<double>(dy) * static_cast<double>(dy) +
static_cast<double>(dz) * static_cast<double>(dz)
);
if (static_cast<double>(lengthSquared) == 0.0
|| static_cast<double>(maxDistanceDelta) >= 0.0
&& static_cast<double>(lengthSquared)
<= static_cast<double>(maxDistanceDelta) * static_cast<double>(maxDistanceDelta)) {
return target;
}
float length = std::sqrt(lengthSquared);
return NiPoint3(current.x + dx / length * maxDistanceDelta, current.y + dy / length * maxDistanceDelta, current.z + dz / length * maxDistanceDelta);
}
//This code is yoinked from the MS XNA code, so it should be right, even if it's horrible.
NiPoint3 NiPoint3::RotateByQuaternion(const NiQuaternion& rotation) {
Vector3 vector;
float num12 = rotation.x + rotation.x;
float num2 = rotation.y + rotation.y;
float num = rotation.z + rotation.z;
float num11 = rotation.w * num12;
float num10 = rotation.w * num2;
float num9 = rotation.w * num;
float num8 = rotation.x * num12;
float num7 = rotation.x * num2;
float num6 = rotation.x * num;
float num5 = rotation.y * num2;
float num4 = rotation.y * num;
float num3 = rotation.z * num;
Vector3 vector;
float num12 = rotation.x + rotation.x;
float num2 = rotation.y + rotation.y;
float num = rotation.z + rotation.z;
float num11 = rotation.w * num12;
float num10 = rotation.w * num2;
float num9 = rotation.w * num;
float num8 = rotation.x * num12;
float num7 = rotation.x * num2;
float num6 = rotation.x * num;
float num5 = rotation.y * num2;
float num4 = rotation.y * num;
float num3 = rotation.z * num;
NiPoint3 value = *this;
float num15 = ((value.x * ((1.0f - num5) - num3)) + (value.y * (num7 - num9))) + (value.z * (num6 + num10));
float num14 = ((value.x * (num7 + num9)) + (value.y * ((1.0f - num8) - num3))) + (value.z * (num4 - num11));
float num13 = ((value.x * (num6 - num10)) + (value.y * (num4 + num11))) + (value.z * ((1.0f - num8) - num5));
vector.x = num15;
vector.y = num14;
vector.z = num13;
return vector;
}
NiPoint3 value = *this;
float num15 = ((value.x * ((1.0f - num5) - num3)) + (value.y * (num7 - num9))) + (value.z * (num6 + num10));
float num14 = ((value.x * (num7 + num9)) + (value.y * ((1.0f - num8) - num3))) + (value.z * (num4 - num11));
float num13 = ((value.x * (num6 - num10)) + (value.y * (num4 + num11))) + (value.z * ((1.0f - num8) - num5));
vector.x = num15;
vector.y = num14;
vector.z = num13;
return vector;
}

View File

@@ -12,177 +12,182 @@ typedef NiPoint3 Vector3; //!< The Vector3 class is technically the NiPoin
//! A custom class the defines a point in space
class NiPoint3 {
public:
float x; //!< The x position
float y; //!< The y position
float z; //!< The z position
float x; //!< The x position
float y; //!< The y position
float z; //!< The z position
//! Initializer
NiPoint3(void);
//! Initializer
NiPoint3(void);
//! Initializer
/*!
\param x The x coordinate
\param y The y coordinate
\param z The z coordinate
*/
NiPoint3(float x, float y, float z);
//! Initializer
/*!
\param x The x coordinate
\param y The y coordinate
\param z The z coordinate
*/
NiPoint3(float x, float y, float z);
//! Copy Constructor
/*!
\param point The point to copy
*/
NiPoint3(const NiPoint3& point);
//! Copy Constructor
/*!
\param point The point to copy
*/
NiPoint3(const NiPoint3& point);
//! Destructor
~NiPoint3(void);
//! Destructor
~NiPoint3(void);
// MARK: Constants
static const NiPoint3 ZERO; //!< Point(0, 0, 0)
static const NiPoint3 UNIT_X; //!< Point(1, 0, 0)
static const NiPoint3 UNIT_Y; //!< Point(0, 1, 0)
static const NiPoint3 UNIT_Z; //!< Point(0, 0, 1)
static const NiPoint3 UNIT_ALL; //!< Point(1, 1, 1)
// MARK: Constants
static const NiPoint3 ZERO; //!< Point(0, 0, 0)
static const NiPoint3 UNIT_X; //!< Point(1, 0, 0)
static const NiPoint3 UNIT_Y; //!< Point(0, 1, 0)
static const NiPoint3 UNIT_Z; //!< Point(0, 0, 1)
static const NiPoint3 UNIT_ALL; //!< Point(1, 1, 1)
// MARK: Getters / Setters
// MARK: Getters / Setters
//! Gets the X coordinate
/*!
\return The x coordinate
*/
float GetX(void) const;
//! Gets the X coordinate
/*!
\return The x coordinate
*/
float GetX(void) const;
//! Sets the X coordinate
/*!
\param x The x coordinate
*/
void SetX(float x);
//! Sets the X coordinate
/*!
\param x The x coordinate
*/
void SetX(float x);
//! Gets the Y coordinate
/*!
\return The y coordinate
*/
float GetY(void) const;
//! Gets the Y coordinate
/*!
\return The y coordinate
*/
float GetY(void) const;
//! Sets the Y coordinate
/*!
\param y The y coordinate
*/
void SetY(float y);
//! Sets the Y coordinate
/*!
\param y The y coordinate
*/
void SetY(float y);
//! Gets the Z coordinate
/*!
\return The z coordinate
*/
float GetZ(void) const;
//! Gets the Z coordinate
/*!
\return The z coordinate
*/
float GetZ(void) const;
//! Sets the Z coordinate
/*!
\param z The z coordinate
*/
void SetZ(float z);
//! Sets the Z coordinate
/*!
\param z The z coordinate
*/
void SetZ(float z);
// MARK: Member Functions
// MARK: Member Functions
//! Gets the length of the vector
/*!
\return The scalar length of the vector
*/
float Length(void) const;
//! Gets the length of the vector
/*!
\return The scalar length of the vector
*/
float Length(void) const;
//! Gets the squared length of a vector
/*!
\return The squared length of a vector
*/
float SquaredLength(void) const;
//! Gets the squared length of a vector
/*!
\return The squared length of a vector
*/
float SquaredLength(void) const;
//! Returns the dot product of the vector dotted with another vector
/*!
\param vec The second vector
\return The dot product of the two vectors
*/
float DotProduct(const Vector3& vec) const;
//! Returns the dot product of the vector dotted with another vector
/*!
\param vec The second vector
\return The dot product of the two vectors
*/
float DotProduct(const Vector3& vec) const;
//! Returns the cross product of the vector crossed with another vector
/*!
\param vec The second vector
\return The cross product of the two vectors
*/
Vector3 CrossProduct(const Vector3& vec) const;
//! Returns the cross product of the vector crossed with another vector
/*!
\param vec The second vector
\return The cross product of the two vectors
*/
Vector3 CrossProduct(const Vector3& vec) const;
//! Unitize the vector
/*!
\returns The current vector
*/
NiPoint3 Unitize(void) const;
//! Unitize the vector
/*!
\returns The current vector
*/
NiPoint3 Unitize(void) const;
// MARK: Operators
// MARK: Operators
//! Operator to check for equality
bool operator==(const NiPoint3& point) const;
//! Operator to check for equality
bool operator==(const NiPoint3& point) const;
//! Operator to check for inequality
bool operator!=(const NiPoint3& point) const;
//! Operator to check for inequality
bool operator!=(const NiPoint3& point) const;
//! Operator for subscripting
float& operator[](int i);
//! Operator for subscripting
float& operator[](int i);
//! Operator for subscripting
const float& operator[](int i) const;
//! Operator for subscripting
const float& operator[](int i) const;
//! Operator for addition of vectors
NiPoint3 operator+(const NiPoint3& point) const;
//! Operator for addition of vectors
NiPoint3 operator+(const NiPoint3& point) const;
//! Operator for subtraction of vectors
NiPoint3 operator-(const NiPoint3& point) const;
//! Operator for addition of vectors
NiPoint3& operator+=(const NiPoint3& point);
//! Operator for addition of a scalar on all vector components
NiPoint3 operator+(float fScalar) const;
NiPoint3& operator*=(const float scalar);
//! Operator for subtraction of a scalar on all vector components
NiPoint3 operator-(float fScalar) const;
//! Operator for subtraction of vectors
NiPoint3 operator-(const NiPoint3& point) const;
//! Operator for scalar multiplication of a vector
NiPoint3 operator*(float fScalar) const;
//! Operator for addition of a scalar on all vector components
NiPoint3 operator+(float fScalar) const;
//! Operator for scalar division of a vector
NiPoint3 operator/(float fScalar) const;
//! Operator for subtraction of a scalar on all vector components
NiPoint3 operator-(float fScalar) const;
//! Operator for scalar multiplication of a vector
NiPoint3 operator*(float fScalar) const;
//! Operator for scalar division of a vector
NiPoint3 operator/(float fScalar) const;
// MARK: Helper Functions
// MARK: Helper Functions
//! Checks to see if the point (or vector) is with an Axis-Aligned Bounding Box
/*!
\param minPoint The minimum point of the bounding box
\param maxPoint The maximum point of the bounding box
\return Whether or not this point lies within the box
*/
bool IsWithinAxisAlignedBox(const NiPoint3& minPoint, const NiPoint3& maxPoint);
//! Checks to see if the point (or vector) is with an Axis-Aligned Bounding Box
/*!
\param minPoint The minimum point of the bounding box
\param maxPoint The maximum point of the bounding box
\return Whether or not this point lies within the box
*/
bool IsWithinAxisAlignedBox(const NiPoint3& minPoint, const NiPoint3& maxPoint);
//! Checks to see if the point (or vector) is within a sphere
/*!
\param sphereCenter The sphere center
\param radius The radius
*/
bool IsWithinSpehere(const NiPoint3& sphereCenter, float radius);
//! Checks to see if the point (or vector) is within a sphere
/*!
\param sphereCenter The sphere center
\param radius The radius
*/
bool IsWithinSpehere(const NiPoint3& sphereCenter, float radius);
/*!
\param a Start of line
\param b End of line
\param p Refrence point
\return The point of line AB which is closest to P
*/
static NiPoint3 ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, const NiPoint3& p);
/*!
\param a Start of line
\param b End of line
\param p Refrence point
\return The point of line AB which is closest to P
*/
static NiPoint3 ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, const NiPoint3& p);
static float Angle(const NiPoint3& a, const NiPoint3& b);
static float Angle(const NiPoint3& a, const NiPoint3& b);
static float Distance(const NiPoint3& a, const NiPoint3& b);
static float DistanceSquared(const NiPoint3& a, const NiPoint3& b);
static float Distance(const NiPoint3& a, const NiPoint3& b);
static NiPoint3 MoveTowards(const NiPoint3& current, const NiPoint3& target, float maxDistanceDelta);
static float DistanceSquared(const NiPoint3& a, const NiPoint3& b);
NiPoint3 RotateByQuaternion(const NiQuaternion& rotation);
static NiPoint3 MoveTowards(const NiPoint3& current, const NiPoint3& target, float maxDistanceDelta);
NiPoint3 RotateByQuaternion(const NiQuaternion& rotation);
};

View File

@@ -8,18 +8,18 @@ const NiQuaternion NiQuaternion::IDENTITY(1, 0, 0, 0);
//! The initializer
NiQuaternion::NiQuaternion(void) {
this->w = 1;
this->x = 0;
this->y = 0;
this->z = 0;
this->w = 1;
this->x = 0;
this->y = 0;
this->z = 0;
}
//! The initializer
NiQuaternion::NiQuaternion(float w, float x, float y, float z) {
this->w = w;
this->x = x;
this->y = y;
this->z = z;
this->w = w;
this->x = x;
this->y = y;
this->z = z;
}
//! Destructor
@@ -30,42 +30,42 @@ NiQuaternion::~NiQuaternion(void) {}
//! Gets the W coordinate
float NiQuaternion::GetW(void) const {
return this->w;
return this->w;
}
//! Sets the W coordinate
void NiQuaternion::SetW(float w) {
this->w = w;
this->w = w;
}
//! Gets the X coordinate
float NiQuaternion::GetX(void) const {
return this->x;
return this->x;
}
//! Sets the X coordinate
void NiQuaternion::SetX(float x) {
this->x = x;
this->x = x;
}
//! Gets the Y coordinate
float NiQuaternion::GetY(void) const {
return this->y;
return this->y;
}
//! Sets the Y coordinate
void NiQuaternion::SetY(float y) {
this->y = y;
this->y = y;
}
//! Gets the Z coordinate
float NiQuaternion::GetZ(void) const {
return this->z;
return this->z;
}
//! Sets the Z coordinate
void NiQuaternion::SetZ(float z) {
this->z = z;
this->z = z;
}
@@ -73,55 +73,54 @@ void NiQuaternion::SetZ(float z) {
//! Returns the forward vector from the quaternion
Vector3 NiQuaternion::GetForwardVector(void) const {
return Vector3(2 * (x * z + w * y), 2 * (y * z - w * x), 1 - 2 * (x * x + y * y));
return Vector3(2 * (x * z + w * y), 2 * (y * z - w * x), 1 - 2 * (x * x + y * y));
}
//! Returns the up vector from the quaternion
Vector3 NiQuaternion::GetUpVector(void) const {
return Vector3(2 * (x * y - w * z), 1 - 2 * (x * x + z * z), 2 * (y * z + w * x));
return Vector3(2 * (x * y - w * z), 1 - 2 * (x * x + z * z), 2 * (y * z + w * x));
}
//! Returns the right vector from the quaternion
Vector3 NiQuaternion::GetRightVector(void) const {
return Vector3(1 - 2 * (y * y + z * z), 2 * (x * y + w * z), 2 * (x * z - w * y));
return Vector3(1 - 2 * (y * y + z * z), 2 * (x * y + w * z), 2 * (x * z - w * y));
}
Vector3 NiQuaternion::GetEulerAngles() const {
Vector3 angles;
Vector3 angles;
// roll (x-axis rotation)
const float sinr_cosp = 2 * (w * x + y * z);
const float cosr_cosp = 1 - 2 * (x * x + y * y);
angles.x = std::atan2(sinr_cosp, cosr_cosp);
// roll (x-axis rotation)
const float sinr_cosp = 2 * (w * x + y * z);
const float cosr_cosp = 1 - 2 * (x * x + y * y);
angles.x = std::atan2(sinr_cosp, cosr_cosp);
// pitch (y-axis rotation)
const float sinp = 2 * (w * y - z * x);
if (std::abs(sinp) >= 1) {
angles.y = std::copysign(3.14 / 2, sinp); // use 90 degrees if out of range
}
else {
angles.y = std::asin(sinp);
}
// pitch (y-axis rotation)
const float sinp = 2 * (w * y - z * x);
// yaw (z-axis rotation)
const float siny_cosp = 2 * (w * z + x * y);
const float cosy_cosp = 1 - 2 * (y * y + z * z);
angles.z = std::atan2(siny_cosp, cosy_cosp);
if (std::abs(sinp) >= 1) {
angles.y = std::copysign(3.14 / 2, sinp); // use 90 degrees if out of range
} else {
angles.y = std::asin(sinp);
}
return angles;
// yaw (z-axis rotation)
const float siny_cosp = 2 * (w * z + x * y);
const float cosy_cosp = 1 - 2 * (y * y + z * z);
angles.z = std::atan2(siny_cosp, cosy_cosp);
return angles;
}
// MARK: Operators
//! Operator to check for equality
bool NiQuaternion::operator==(const NiQuaternion& rot) const {
return rot.x == this->x && rot.y == this->y && rot.z == this->z && rot.w == this->w;
return rot.x == this->x && rot.y == this->y && rot.z == this->z && rot.w == this->w;
}
//! Operator to check for inequality
bool NiQuaternion::operator!=(const NiQuaternion& rot) const {
return !(*this == rot);
return !(*this == rot);
}
@@ -135,65 +134,63 @@ NiQuaternion NiQuaternion::LookAt(const NiPoint3& sourcePoint, const NiPoint3& d
source.y = 0.0f;
dest.y = 0.0f;
NiPoint3 forwardVector = NiPoint3(dest - source).Unitize();
NiPoint3 posZ = NiPoint3::UNIT_Z;
NiPoint3 vecA = posZ.CrossProduct(forwardVector).Unitize();
float dot = posZ.DotProduct(forwardVector);
float rotAngle = static_cast<float>(acos(dot));
NiPoint3 vecB = vecA.CrossProduct(posZ);
if (vecB.DotProduct(forwardVector) < 0) rotAngle = -rotAngle;
return NiQuaternion::CreateFromAxisAngle(vecA, rotAngle);
NiPoint3 forwardVector = NiPoint3(dest - source).Unitize();
NiPoint3 posZ = NiPoint3::UNIT_Z;
NiPoint3 vecA = posZ.CrossProduct(forwardVector).Unitize();
float dot = posZ.DotProduct(forwardVector);
float rotAngle = static_cast<float>(acos(dot));
NiPoint3 vecB = vecA.CrossProduct(posZ);
if (vecB.DotProduct(forwardVector) < 0) rotAngle = -rotAngle;
return NiQuaternion::CreateFromAxisAngle(vecA, rotAngle);
}
NiQuaternion NiQuaternion::LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint)
{
NiPoint3 forwardVector = NiPoint3(destPoint - sourcePoint).Unitize();
NiPoint3 posZ = NiPoint3::UNIT_Z;
NiPoint3 vecA = posZ.CrossProduct(forwardVector).Unitize();
float dot = posZ.DotProduct(forwardVector);
float rotAngle = static_cast<float>(acos(dot));
NiPoint3 vecB = vecA.CrossProduct(posZ);
if (vecB.DotProduct(forwardVector) < 0) rotAngle = -rotAngle;
return NiQuaternion::CreateFromAxisAngle(vecA, rotAngle);
NiQuaternion NiQuaternion::LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint) {
NiPoint3 forwardVector = NiPoint3(destPoint - sourcePoint).Unitize();
NiPoint3 posZ = NiPoint3::UNIT_Z;
NiPoint3 vecA = posZ.CrossProduct(forwardVector).Unitize();
float dot = posZ.DotProduct(forwardVector);
float rotAngle = static_cast<float>(acos(dot));
NiPoint3 vecB = vecA.CrossProduct(posZ);
if (vecB.DotProduct(forwardVector) < 0) rotAngle = -rotAngle;
return NiQuaternion::CreateFromAxisAngle(vecA, rotAngle);
}
//! Creates a Quaternion from a specific axis and angle relative to that axis
NiQuaternion NiQuaternion::CreateFromAxisAngle(const Vector3& axis, float angle) {
float halfAngle = angle * 0.5f;
float s = static_cast<float>(sin(halfAngle));
NiQuaternion q;
q.x = axis.GetX() * s;
q.y = axis.GetY() * s;
q.z = axis.GetZ() * s;
q.w = static_cast<float>(cos(halfAngle));
return q;
float halfAngle = angle * 0.5f;
float s = static_cast<float>(sin(halfAngle));
NiQuaternion q;
q.x = axis.GetX() * s;
q.y = axis.GetY() * s;
q.z = axis.GetZ() * s;
q.w = static_cast<float>(cos(halfAngle));
return q;
}
NiQuaternion NiQuaternion::FromEulerAngles(const NiPoint3& eulerAngles)
{
// Abbreviations for the various angular functions
float cy = cos(eulerAngles.z * 0.5);
float sy = sin(eulerAngles.z * 0.5);
float cp = cos(eulerAngles.y * 0.5);
float sp = sin(eulerAngles.y * 0.5);
float cr = cos(eulerAngles.x * 0.5);
float sr = sin(eulerAngles.x * 0.5);
NiQuaternion NiQuaternion::FromEulerAngles(const NiPoint3& eulerAngles) {
// Abbreviations for the various angular functions
float cy = cos(eulerAngles.z * 0.5);
float sy = sin(eulerAngles.z * 0.5);
float cp = cos(eulerAngles.y * 0.5);
float sp = sin(eulerAngles.y * 0.5);
float cr = cos(eulerAngles.x * 0.5);
float sr = sin(eulerAngles.x * 0.5);
NiQuaternion q;
q.w = cr * cp * cy + sr * sp * sy;
q.x = sr * cp * cy - cr * sp * sy;
q.y = cr * sp * cy + sr * cp * sy;
q.z = cr * cp * sy - sr * sp * cy;
NiQuaternion q;
q.w = cr * cp * cy + sr * sp * sy;
q.x = sr * cp * cy - cr * sp * sy;
q.y = cr * sp * cy + sr * cp * sy;
q.z = cr * cp * sy - sr * sp * cy;
return q;
return q;
}

View File

@@ -14,138 +14,138 @@ typedef NiQuaternion Quaternion; //!< A typedef for a shorthand version o
//! A class that defines a rotation in space
class NiQuaternion {
public:
float w; //!< The w coordinate
float x; //!< The x coordinate
float y; //!< The y coordinate
float z; //!< The z coordinate
//! The initializer
NiQuaternion(void);
//! The initializer
/*!
\param w The w coordinate
\param x The x coordinate
\param y The y coordinate
\param z The z coordinate
*/
NiQuaternion(float w, float x, float y, float z);
//! Destructor
~NiQuaternion(void);
// MARK: Constants
static const NiQuaternion IDENTITY; //!< Quaternion(1, 0, 0, 0)
// MARK: Setters / Getters
//! Gets the W coordinate
/*!
\return The w coordinate
*/
float GetW(void) const;
//! Sets the W coordinate
/*!
\param w The w coordinate
*/
void SetW(float w);
//! Gets the X coordinate
/*!
\return The x coordinate
*/
float GetX(void) const;
//! Sets the X coordinate
/*!
\param x The x coordinate
*/
void SetX(float x);
//! Gets the Y coordinate
/*!
\return The y coordinate
*/
float GetY(void) const;
//! Sets the Y coordinate
/*!
\param y The y coordinate
*/
void SetY(float y);
//! Gets the Z coordinate
/*!
\return The z coordinate
*/
float GetZ(void) const;
//! Sets the Z coordinate
/*!
\param z The z coordinate
*/
void SetZ(float z);
// MARK: Member Functions
//! Returns the forward vector from the quaternion
/*!
\return The forward vector of the quaternion
*/
Vector3 GetForwardVector(void) const;
//! Returns the up vector from the quaternion
/*!
\return The up vector fo the quaternion
*/
Vector3 GetUpVector(void) const;
//! Returns the right vector from the quaternion
/*!
\return The right vector of the quaternion
*/
Vector3 GetRightVector(void) const;
float w; //!< The w coordinate
float x; //!< The x coordinate
float y; //!< The y coordinate
float z; //!< The z coordinate
Vector3 GetEulerAngles() const;
// MARK: Operators
//! Operator to check for equality
bool operator==(const NiQuaternion& rot) const;
//! Operator to check for inequality
bool operator!=(const NiQuaternion& rot) const;
// MARK: Helper Functions
//! Look from a specific point in space to another point in space (Y-locked)
/*!
\param sourcePoint The source location
\param destPoint The destination location
\return The Quaternion with the rotation towards the destination
*/
static NiQuaternion LookAt(const NiPoint3& sourcePoint, const NiPoint3& destPoint);
//! Look from a specific point in space to another point in space
/*!
\param sourcePoint The source location
\param destPoint The destination location
\return The Quaternion with the rotation towards the destination
*/
static NiQuaternion LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint);
//! Creates a Quaternion from a specific axis and angle relative to that axis
/*!
\param axis The axis that is used
\param angle The angle relative to this axis
\return A quaternion created from the axis and angle
*/
static NiQuaternion CreateFromAxisAngle(const Vector3& axis, float angle);
static NiQuaternion FromEulerAngles(const NiPoint3& eulerAngles);
//! The initializer
NiQuaternion(void);
//! The initializer
/*!
\param w The w coordinate
\param x The x coordinate
\param y The y coordinate
\param z The z coordinate
*/
NiQuaternion(float w, float x, float y, float z);
//! Destructor
~NiQuaternion(void);
// MARK: Constants
static const NiQuaternion IDENTITY; //!< Quaternion(1, 0, 0, 0)
// MARK: Setters / Getters
//! Gets the W coordinate
/*!
\return The w coordinate
*/
float GetW(void) const;
//! Sets the W coordinate
/*!
\param w The w coordinate
*/
void SetW(float w);
//! Gets the X coordinate
/*!
\return The x coordinate
*/
float GetX(void) const;
//! Sets the X coordinate
/*!
\param x The x coordinate
*/
void SetX(float x);
//! Gets the Y coordinate
/*!
\return The y coordinate
*/
float GetY(void) const;
//! Sets the Y coordinate
/*!
\param y The y coordinate
*/
void SetY(float y);
//! Gets the Z coordinate
/*!
\return The z coordinate
*/
float GetZ(void) const;
//! Sets the Z coordinate
/*!
\param z The z coordinate
*/
void SetZ(float z);
// MARK: Member Functions
//! Returns the forward vector from the quaternion
/*!
\return The forward vector of the quaternion
*/
Vector3 GetForwardVector(void) const;
//! Returns the up vector from the quaternion
/*!
\return The up vector fo the quaternion
*/
Vector3 GetUpVector(void) const;
//! Returns the right vector from the quaternion
/*!
\return The right vector of the quaternion
*/
Vector3 GetRightVector(void) const;
Vector3 GetEulerAngles() const;
// MARK: Operators
//! Operator to check for equality
bool operator==(const NiQuaternion& rot) const;
//! Operator to check for inequality
bool operator!=(const NiQuaternion& rot) const;
// MARK: Helper Functions
//! Look from a specific point in space to another point in space (Y-locked)
/*!
\param sourcePoint The source location
\param destPoint The destination location
\return The Quaternion with the rotation towards the destination
*/
static NiQuaternion LookAt(const NiPoint3& sourcePoint, const NiPoint3& destPoint);
//! Look from a specific point in space to another point in space
/*!
\param sourcePoint The source location
\param destPoint The destination location
\return The Quaternion with the rotation towards the destination
*/
static NiQuaternion LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint);
//! Creates a Quaternion from a specific axis and angle relative to that axis
/*!
\param axis The axis that is used
\param angle The angle relative to this axis
\return A quaternion created from the axis and angle
*/
static NiQuaternion CreateFromAxisAngle(const Vector3& axis, float angle);
static NiQuaternion FromEulerAngles(const NiPoint3& eulerAngles);
};

View File

@@ -1,42 +0,0 @@
#pragma once
#include <cstdint>
/**
* Bitmap of permissions and restrictions for characters.
*/
enum class PermissionMap : uint64_t
{
/**
* Reserved for future use, bit 0-3.
*/
/**
* The character has restricted trade acccess, bit 4.
*/
RestrictedTradeAccess = 0x1 << 4,
/**
* The character has restricted mail access, bit 5.
*/
RestrictedMailAccess = 0x1 << 5,
/**
* The character has restricted chat access, bit 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,
};

50
dCommon/PositionUpdate.h Normal file
View File

@@ -0,0 +1,50 @@
#ifndef __POSITIONUPDATE__H__
#define __POSITIONUPDATE__H__
#include "NiPoint3.h"
#include "NiQuaternion.h"
struct RemoteInputInfo {
RemoteInputInfo() {
m_RemoteInputX = 0;
m_RemoteInputY = 0;
m_IsPowersliding = false;
m_IsModified = false;
}
void operator=(const RemoteInputInfo& other) {
m_RemoteInputX = other.m_RemoteInputX;
m_RemoteInputY = other.m_RemoteInputY;
m_IsPowersliding = other.m_IsPowersliding;
m_IsModified = other.m_IsModified;
}
bool operator==(const RemoteInputInfo& other) {
return m_RemoteInputX == other.m_RemoteInputX && m_RemoteInputY == other.m_RemoteInputY && m_IsPowersliding == other.m_IsPowersliding && m_IsModified == other.m_IsModified;
}
float m_RemoteInputX;
float m_RemoteInputY;
bool m_IsPowersliding;
bool m_IsModified;
};
struct LocalSpaceInfo {
LWOOBJID objectId = LWOOBJID_EMPTY;
NiPoint3 position = NiPoint3::ZERO;
NiPoint3 linearVelocity = NiPoint3::ZERO;
};
struct PositionUpdate {
NiPoint3 position = NiPoint3::ZERO;
NiQuaternion rotation = NiQuaternion::IDENTITY;
bool onGround = false;
bool onRail = false;
NiPoint3 velocity = NiPoint3::ZERO;
NiPoint3 angularVelocity = NiPoint3::ZERO;
LocalSpaceInfo localSpaceInfo;
RemoteInputInfo remoteInputInfo;
};
#endif //!__POSITIONUPDATE__H__

View File

@@ -1,3 +1,5 @@
// Source: http://www.zedwood.com/article/cpp-sha512-function
#include "SHA512.h"
#include <cstring>
@@ -5,153 +7,148 @@
const unsigned long long SHA512::sha512_k[80] = //ULL = uint64
{ 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL };
0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL };
void SHA512::transform(const unsigned char *message, unsigned int block_nb)
{
uint64 w[80];
uint64 wv[8];
uint64 t1, t2;
const unsigned char *sub_block;
int i, j;
for (i = 0; i < (int)block_nb; i++) {
sub_block = message + (i << 7);
for (j = 0; j < 16; j++) {
SHA2_PACK64(&sub_block[j << 3], &w[j]);
}
for (j = 16; j < 80; j++) {
w[j] = SHA512_F4(w[j - 2]) + w[j - 7] + SHA512_F3(w[j - 15]) + w[j - 16];
}
for (j = 0; j < 8; j++) {
wv[j] = m_h[j];
}
for (j = 0; j < 80; j++) {
t1 = wv[7] + SHA512_F2(wv[4]) + SHA2_CH(wv[4], wv[5], wv[6])
+ sha512_k[j] + w[j];
t2 = SHA512_F1(wv[0]) + SHA2_MAJ(wv[0], wv[1], wv[2]);
wv[7] = wv[6];
wv[6] = wv[5];
wv[5] = wv[4];
wv[4] = wv[3] + t1;
wv[3] = wv[2];
wv[2] = wv[1];
wv[1] = wv[0];
wv[0] = t1 + t2;
}
for (j = 0; j < 8; j++) {
m_h[j] += wv[j];
}
}
void SHA512::transform(const unsigned char* message, unsigned int block_nb) {
uint64 w[80];
uint64 wv[8];
uint64 t1, t2;
const unsigned char* sub_block;
int i, j;
for (i = 0; i < (int)block_nb; i++) {
sub_block = message + (i << 7);
for (j = 0; j < 16; j++) {
SHA2_PACK64(&sub_block[j << 3], &w[j]);
}
for (j = 16; j < 80; j++) {
w[j] = SHA512_F4(w[j - 2]) + w[j - 7] + SHA512_F3(w[j - 15]) + w[j - 16];
}
for (j = 0; j < 8; j++) {
wv[j] = m_h[j];
}
for (j = 0; j < 80; j++) {
t1 = wv[7] + SHA512_F2(wv[4]) + SHA2_CH(wv[4], wv[5], wv[6])
+ sha512_k[j] + w[j];
t2 = SHA512_F1(wv[0]) + SHA2_MAJ(wv[0], wv[1], wv[2]);
wv[7] = wv[6];
wv[6] = wv[5];
wv[5] = wv[4];
wv[4] = wv[3] + t1;
wv[3] = wv[2];
wv[2] = wv[1];
wv[1] = wv[0];
wv[0] = t1 + t2;
}
for (j = 0; j < 8; j++) {
m_h[j] += wv[j];
}
}
}
void SHA512::init()
{
m_h[0] = 0x6a09e667f3bcc908ULL;
m_h[1] = 0xbb67ae8584caa73bULL;
m_h[2] = 0x3c6ef372fe94f82bULL;
m_h[3] = 0xa54ff53a5f1d36f1ULL;
m_h[4] = 0x510e527fade682d1ULL;
m_h[5] = 0x9b05688c2b3e6c1fULL;
m_h[6] = 0x1f83d9abfb41bd6bULL;
m_h[7] = 0x5be0cd19137e2179ULL;
m_len = 0;
m_tot_len = 0;
void SHA512::init() {
m_h[0] = 0x6a09e667f3bcc908ULL;
m_h[1] = 0xbb67ae8584caa73bULL;
m_h[2] = 0x3c6ef372fe94f82bULL;
m_h[3] = 0xa54ff53a5f1d36f1ULL;
m_h[4] = 0x510e527fade682d1ULL;
m_h[5] = 0x9b05688c2b3e6c1fULL;
m_h[6] = 0x1f83d9abfb41bd6bULL;
m_h[7] = 0x5be0cd19137e2179ULL;
m_len = 0;
m_tot_len = 0;
}
void SHA512::update(const unsigned char *message, unsigned int len)
{
unsigned int block_nb;
unsigned int new_len, rem_len, tmp_len;
const unsigned char *shifted_message;
tmp_len = SHA384_512_BLOCK_SIZE - m_len;
rem_len = len < tmp_len ? len : tmp_len;
memcpy(&m_block[m_len], message, rem_len);
if (m_len + len < SHA384_512_BLOCK_SIZE) {
m_len += len;
return;
}
new_len = len - rem_len;
block_nb = new_len / SHA384_512_BLOCK_SIZE;
shifted_message = message + rem_len;
transform(m_block, 1);
transform(shifted_message, block_nb);
rem_len = new_len % SHA384_512_BLOCK_SIZE;
memcpy(m_block, &shifted_message[block_nb << 7], rem_len);
m_len = rem_len;
m_tot_len += (block_nb + 1) << 7;
void SHA512::update(const unsigned char* message, unsigned int len) {
unsigned int block_nb;
unsigned int new_len, rem_len, tmp_len;
const unsigned char* shifted_message;
tmp_len = SHA384_512_BLOCK_SIZE - m_len;
rem_len = len < tmp_len ? len : tmp_len;
memcpy(&m_block[m_len], message, rem_len);
if (m_len + len < SHA384_512_BLOCK_SIZE) {
m_len += len;
return;
}
new_len = len - rem_len;
block_nb = new_len / SHA384_512_BLOCK_SIZE;
shifted_message = message + rem_len;
transform(m_block, 1);
transform(shifted_message, block_nb);
rem_len = new_len % SHA384_512_BLOCK_SIZE;
memcpy(m_block, &shifted_message[block_nb << 7], rem_len);
m_len = rem_len;
m_tot_len += (block_nb + 1) << 7;
}
void SHA512::final(unsigned char *digest)
{
unsigned int block_nb;
unsigned int pm_len;
unsigned int len_b;
int i;
block_nb = 1 + ((SHA384_512_BLOCK_SIZE - 17)
< (m_len % SHA384_512_BLOCK_SIZE));
len_b = (m_tot_len + m_len) << 3;
pm_len = block_nb << 7;
memset(m_block + m_len, 0, pm_len - m_len);
m_block[m_len] = 0x80;
SHA2_UNPACK32(len_b, m_block + pm_len - 4);
transform(m_block, block_nb);
for (i = 0; i < 8; i++) {
SHA2_UNPACK64(m_h[i], &digest[i << 3]);
}
void SHA512::final(unsigned char* digest) {
unsigned int block_nb;
unsigned int pm_len;
unsigned int len_b;
int i;
block_nb = 1 + ((SHA384_512_BLOCK_SIZE - 17)
< (m_len % SHA384_512_BLOCK_SIZE));
len_b = (m_tot_len + m_len) << 3;
pm_len = block_nb << 7;
memset(m_block + m_len, 0, pm_len - m_len);
m_block[m_len] = 0x80;
SHA2_UNPACK32(len_b, m_block + pm_len - 4);
transform(m_block, block_nb);
for (i = 0; i < 8; i++) {
SHA2_UNPACK64(m_h[i], &digest[i << 3]);
}
}
std::string sha512(std::string input)
{
unsigned char digest[SHA512::DIGEST_SIZE];
memset(digest, 0, SHA512::DIGEST_SIZE);
class SHA512 ctx;
ctx.init();
ctx.update((unsigned char*)input.c_str(), input.length());
ctx.final(digest);
std::string sha512(std::string input) {
unsigned char digest[SHA512::DIGEST_SIZE];
memset(digest, 0, SHA512::DIGEST_SIZE);
class SHA512 ctx;
ctx.init();
ctx.update((unsigned char*)input.c_str(), input.length());
ctx.final(digest);
char buf[2 * SHA512::DIGEST_SIZE + 1];
buf[2 * SHA512::DIGEST_SIZE] = 0;
for (int i = 0; i < SHA512::DIGEST_SIZE; i++)
sprintf(buf + i * 2, "%02x", digest[i]);
char buf[2 * SHA512::DIGEST_SIZE + 1];
buf[2 * SHA512::DIGEST_SIZE] = 0;
for (int i = 0; i < SHA512::DIGEST_SIZE; i++)
sprintf(buf + i * 2, "%02x", digest[i]);
return std::string(buf);
return std::string(buf);
}

View File

@@ -5,25 +5,25 @@
class SHA512 {
protected:
typedef unsigned char uint8;
typedef unsigned int uint32;
typedef unsigned long long uint64;
const static uint64 sha512_k[];
static const unsigned int SHA384_512_BLOCK_SIZE = (1024 / 8);
typedef unsigned char uint8;
typedef unsigned int uint32;
typedef unsigned long long uint64;
const static uint64 sha512_k[];
static const unsigned int SHA384_512_BLOCK_SIZE = (1024 / 8);
public:
void init();
void update(const unsigned char *message, unsigned int len);
void final(unsigned char *digest);
static const unsigned int DIGEST_SIZE = (512 / 8);
void init();
void update(const unsigned char* message, unsigned int len);
void final(unsigned char* digest);
static const unsigned int DIGEST_SIZE = (512 / 8);
protected:
void transform(const unsigned char *message, unsigned int block_nb);
unsigned int m_tot_len;
unsigned int m_len;
unsigned char m_block[2 * SHA384_512_BLOCK_SIZE];
uint64 m_h[8];
void transform(const unsigned char* message, unsigned int block_nb);
unsigned int m_tot_len;
unsigned int m_len;
unsigned char m_block[2 * SHA384_512_BLOCK_SIZE];
uint64 m_h[8];
};
std::string sha512(std::string input);

View File

@@ -16,4 +16,4 @@ public:
protected:
Singleton() = default;
};
};

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

@@ -1,73 +1,50 @@
#include "ZCompression.h"
#include "ZCompression.h"
#include <zlib.h>
#include "zlib.h"
namespace ZCompression
{
int32_t GetMaxCompressedLength(int32_t nLenSrc)
{
int32_t n16kBlocks = (nLenSrc + 16383) / 16384; // round up any fraction of a block
return (nLenSrc + 6 + (n16kBlocks * 5));
}
namespace ZCompression {
int32_t GetMaxCompressedLength(int32_t nLenSrc) {
int32_t n16kBlocks = (nLenSrc + 16383) / 16384; // round up any fraction of a block
return (nLenSrc + 6 + (n16kBlocks * 5));
}
int32_t Compress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst)
{
z_stream zInfo = { 0 };
zInfo.total_in = zInfo.avail_in = nLenSrc;
zInfo.total_out = zInfo.avail_out = nLenDst;
zInfo.next_in = const_cast<Bytef*>(abSrc);
zInfo.next_out = abDst;
int32_t Compress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst) {
z_stream zInfo = { 0 };
zInfo.total_in = zInfo.avail_in = nLenSrc;
zInfo.total_out = zInfo.avail_out = nLenDst;
zInfo.next_in = const_cast<Bytef*>(abSrc);
zInfo.next_out = abDst;
int nErr, nRet = -1;
nErr = deflateInit(&zInfo, Z_DEFAULT_COMPRESSION); // zlib function
if (nErr == Z_OK) {
nErr = deflate(&zInfo, Z_FINISH); // zlib function
if (nErr == Z_STREAM_END) {
nRet = zInfo.total_out;
}
}
deflateEnd(&zInfo); // zlib function
return(nRet);
int nErr, nRet = -1;
nErr = deflateInit(&zInfo, Z_DEFAULT_COMPRESSION); // zlib function
if (nErr == Z_OK) {
nErr = deflate(&zInfo, Z_FINISH); // zlib function
if (nErr == Z_STREAM_END) {
nRet = zInfo.total_out;
}
}
deflateEnd(&zInfo); // zlib function
return(nRet);
}
}
int32_t Decompress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst, int32_t& nErr) {
// Get the size of the decompressed data
z_stream zInfo = { 0 };
zInfo.total_in = zInfo.avail_in = nLenSrc;
zInfo.total_out = zInfo.avail_out = nLenDst;
zInfo.next_in = const_cast<Bytef*>(abSrc);
zInfo.next_out = abDst;
int32_t Decompress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst, int32_t& nErr)
{
// Get the size of the decompressed data
z_stream zInfo = { 0 };
zInfo.total_in = zInfo.avail_in = nLenSrc;
zInfo.total_out = zInfo.avail_out = nLenDst;
zInfo.next_in = const_cast<Bytef*>(abSrc);
zInfo.next_out = abDst;
int nRet = -1;
nErr = inflateInit(&zInfo); // zlib function
if (nErr == Z_OK) {
nErr = inflate(&zInfo, Z_FINISH); // zlib function
if (nErr == Z_STREAM_END) {
nRet = zInfo.total_out;
}
}
inflateEnd(&zInfo); // zlib function
return(nRet);
}
}
int nRet = -1;
nErr = inflateInit(&zInfo); // zlib function
if (nErr == Z_OK) {
nErr = inflate(&zInfo, Z_FINISH); // zlib function
if (nErr == Z_STREAM_END) {
nRet = zInfo.total_out;
}
}
inflateEnd(&zInfo); // zlib function
return(nRet);
/*
z_stream zInfo = { 0 };
zInfo.total_in = zInfo.avail_in = nLenSrc;
zInfo.total_out = zInfo.avail_out = nLenDst;
zInfo.next_in = const_cast<Bytef*>(abSrc);
zInfo.next_out = const_cast<Bytef*>(abDst);
int nRet = -1;
nErr = inflateInit(&zInfo); // zlib function
if (nErr == Z_OK) {
nErr = inflate(&zInfo, Z_FINISH); // zlib function
if (nErr == Z_STREAM_END) {
nRet = zInfo.total_out;
}
}
inflateEnd(&zInfo); // zlib function
return(nRet); // -1 or len of output
*/
}
}

View File

@@ -1,12 +1,18 @@
#pragma once
#pragma once
#include <cstdint>
namespace ZCompression
{
namespace ZCompression {
int32_t GetMaxCompressedLength(int32_t nLenSrc);
int32_t Compress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst);
int32_t Decompress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst, int32_t& nErr);
/**
* @brief Max size of an inflated sd0 zlib chunk
*
*/
constexpr uint32_t MAX_SD0_CHUNK_SIZE = 1024 * 256;
}

View File

@@ -0,0 +1,182 @@
#include <filesystem>
#include "AssetManager.h"
#include "Game.h"
#include "Logger.h"
#include "zlib.h"
AssetManager::AssetManager(const std::filesystem::path& path) {
if (!std::filesystem::is_directory(path)) {
throw std::runtime_error("Attempted to load asset bundle (" + path.string() + ") however it is not a valid directory.");
}
m_Path = path;
if (std::filesystem::exists(m_Path / "client") && std::filesystem::exists(m_Path / "versions")) {
m_AssetBundleType = eAssetBundleType::Packed;
m_RootPath = m_Path;
m_ResPath = (m_Path / "client" / "res");
} else if (std::filesystem::exists(m_Path / ".." / "versions") && std::filesystem::exists(m_Path / "res")) {
m_AssetBundleType = eAssetBundleType::Packed;
m_RootPath = (m_Path / "..");
m_ResPath = (m_Path / "res");
} else if (std::filesystem::exists(m_Path / "pack") && std::filesystem::exists(m_Path / ".." / ".." / "versions")) {
m_AssetBundleType = eAssetBundleType::Packed;
m_RootPath = (m_Path / ".." / "..");
m_ResPath = m_Path;
} else if ((std::filesystem::exists(m_Path / "res" / "cdclient.fdb") || std::filesystem::exists(m_Path / "res" / "CDServer.sqlite")) && !std::filesystem::exists(m_Path / "res" / "pack")) {
m_AssetBundleType = eAssetBundleType::Unpacked;
m_ResPath = (m_Path / "res");
} else if ((std::filesystem::exists(m_Path / "cdclient.fdb") || std::filesystem::exists(m_Path / "CDServer.sqlite")) && !std::filesystem::exists(m_Path / "pack")) {
m_AssetBundleType = eAssetBundleType::Unpacked;
m_ResPath = m_Path;
}
if (m_AssetBundleType == eAssetBundleType::None) {
throw std::runtime_error("Failed to identify client type, cannot read client data.");
}
switch (m_AssetBundleType) {
case eAssetBundleType::Packed: {
this->LoadPackIndex();
break;
}
case eAssetBundleType::None:
case eAssetBundleType::Unpacked: {
break;
}
}
}
void AssetManager::LoadPackIndex() {
m_PackIndex = new PackIndex(m_RootPath);
}
std::filesystem::path AssetManager::GetResPath() {
return m_ResPath;
}
eAssetBundleType AssetManager::GetAssetBundleType() {
return m_AssetBundleType;
}
bool AssetManager::HasFile(const char* name) {
auto fixedName = std::string(name);
std::transform(fixedName.begin(), fixedName.end(), fixedName.begin(), [](uint8_t c) { return std::tolower(c); });
// Special case for unpacked client have BrickModels in upper case
if (this->m_AssetBundleType == eAssetBundleType::Unpacked) GeneralUtils::ReplaceInString(fixedName, "brickmodels", "BrickModels");
std::replace(fixedName.begin(), fixedName.end(), '\\', '/');
if (std::filesystem::exists(m_ResPath / fixedName)) return true;
if (this->m_AssetBundleType == eAssetBundleType::Unpacked) return false;
std::replace(fixedName.begin(), fixedName.end(), '/', '\\');
if (fixedName.rfind("client\\res\\", 0) != 0) fixedName = "client\\res\\" + fixedName;
uint32_t crc = crc32b(0xFFFFFFFF, reinterpret_cast<uint8_t*>(const_cast<char*>(fixedName.c_str())), fixedName.size());
crc = crc32b(crc, reinterpret_cast<Bytef*>(const_cast<char*>("\0\0\0\0")), 4);
for (const auto& item : this->m_PackIndex->GetPackFileIndices()) {
if (item.m_Crc == crc) {
return true;
}
}
return false;
}
bool AssetManager::GetFile(const char* name, char** data, uint32_t* len) {
auto fixedName = std::string(name);
std::transform(fixedName.begin(), fixedName.end(), fixedName.begin(), [](uint8_t c) { return std::tolower(c); });
std::replace(fixedName.begin(), fixedName.end(), '\\', '/'); // On the off chance someone has the wrong slashes, force forward slashes
// Special case for unpacked client have BrickModels in upper case
if (this->m_AssetBundleType == eAssetBundleType::Unpacked) GeneralUtils::ReplaceInString(fixedName, "brickmodels", "BrickModels");
if (std::filesystem::exists(m_ResPath / fixedName)) {
FILE* file;
#ifdef _WIN32
fopen_s(&file, (m_ResPath / fixedName).string().c_str(), "rb");
#elif __APPLE__
// macOS has 64bit file IO by default
file = fopen((m_ResPath / fixedName).string().c_str(), "rb");
#else
file = fopen64((m_ResPath / fixedName).string().c_str(), "rb");
#endif
fseek(file, 0, SEEK_END);
*len = ftell(file);
*data = static_cast<char*>(malloc(*len));
fseek(file, 0, SEEK_SET);
int32_t readInData = fread(*data, sizeof(uint8_t), *len, file);
fclose(file);
return true;
}
if (this->m_AssetBundleType == eAssetBundleType::Unpacked) return false;
// The crc in side of the pack always uses backslashes, so we need to convert them again...
std::replace(fixedName.begin(), fixedName.end(), '/', '\\');
if (fixedName.rfind("client\\res\\", 0) != 0) {
fixedName = "client\\res\\" + fixedName;
}
int32_t packIndex = -1;
uint32_t crc = crc32b(0xFFFFFFFF, reinterpret_cast<uint8_t*>(const_cast<char*>(fixedName.c_str())), fixedName.size());
crc = crc32b(crc, reinterpret_cast<Bytef*>(const_cast<char*>("\0\0\0\0")), 4);
for (const auto& item : this->m_PackIndex->GetPackFileIndices()) {
if (item.m_Crc == crc) {
packIndex = item.m_PackFileIndex;
crc = item.m_Crc;
break;
}
}
if (packIndex == -1 || !crc) {
return false;
}
auto packs = this->m_PackIndex->GetPacks();
auto* pack = packs.at(packIndex);
bool success = pack->ReadFileFromPack(crc, data, len);
return success;
}
AssetStream AssetManager::GetFile(const char* name) {
char* buf; uint32_t len;
bool success = this->GetFile(name, &buf, &len);
return AssetStream(buf, len, success);
}
uint32_t AssetManager::crc32b(uint32_t base, uint8_t* message, size_t l) {
size_t i, j;
uint32_t crc, msb;
crc = base;
for (i = 0; i < l; i++) {
// xor next byte to upper bits of crc
crc ^= (static_cast<unsigned int>(message[i]) << 24);
for (j = 0; j < 8; j++) { // Do eight times.
msb = crc >> 31;
crc <<= 1;
crc ^= (0 - msb) & 0x04C11DB7;
}
}
return crc; // don't complement crc on output
}
AssetManager::~AssetManager() {
delete m_PackIndex;
}

View File

@@ -0,0 +1,89 @@
#pragma once
#include <string>
#include <vector>
#include <unordered_map>
#include <filesystem>
#include "Pack.h"
#include "PackIndex.h"
enum class eAssetBundleType {
None,
Unpacked,
Packed
};
struct AssetMemoryBuffer : std::streambuf {
char* m_Base;
bool m_Success;
AssetMemoryBuffer(char* base, std::ptrdiff_t n, bool success) {
m_Base = base;
m_Success = success;
if (!m_Success) return;
this->setg(base, base, base + n);
}
~AssetMemoryBuffer() {
if (m_Success) free(m_Base);
}
pos_type seekpos(pos_type sp, std::ios_base::openmode which) override {
return seekoff(sp - pos_type(off_type(0)), std::ios_base::beg, which);
}
pos_type seekoff(off_type off,
std::ios_base::seekdir dir,
std::ios_base::openmode which = std::ios_base::in) override {
if (dir == std::ios_base::cur)
gbump(off);
else if (dir == std::ios_base::end)
setg(eback(), egptr() + off, egptr());
else if (dir == std::ios_base::beg)
setg(eback(), eback() + off, egptr());
return gptr() - eback();
}
};
struct AssetStream : std::istream {
AssetStream(char* base, std::ptrdiff_t n, bool success) : std::istream(new AssetMemoryBuffer(base, n, success)) {}
~AssetStream() {
delete rdbuf();
}
operator bool() {
return reinterpret_cast<AssetMemoryBuffer*>(rdbuf())->m_Success;
}
};
class AssetManager {
public:
AssetManager(const std::filesystem::path& path);
~AssetManager();
std::filesystem::path GetResPath();
eAssetBundleType GetAssetBundleType();
bool HasFile(const char* name);
bool GetFile(const char* name, char** data, uint32_t* len);
AssetStream GetFile(const char* name);
private:
void LoadPackIndex();
// Modified crc algorithm (mpeg2)
// Reference: https://stackoverflow.com/questions/54339800/how-to-modify-crc-32-to-crc-32-mpeg-2
inline uint32_t crc32b(uint32_t base, uint8_t* message, size_t l);
bool m_SuccessfullyLoaded;
std::filesystem::path m_Path;
std::filesystem::path m_RootPath;
std::filesystem::path m_ResPath;
eAssetBundleType m_AssetBundleType = eAssetBundleType::None;
PackIndex* m_PackIndex;
};

View File

@@ -0,0 +1,6 @@
set(DCOMMON_DCLIENT_SOURCES
"PackIndex.cpp"
"Pack.cpp"
"AssetManager.cpp"
PARENT_SCOPE
)

119
dCommon/dClient/Pack.cpp Normal file
View File

@@ -0,0 +1,119 @@
#include "Pack.h"
#include "BinaryIO.h"
#include "ZCompression.h"
Pack::Pack(const std::filesystem::path& filePath) {
m_FilePath = filePath;
if (!std::filesystem::exists(filePath)) {
return;
}
m_FileStream = std::ifstream(filePath, std::ios::in | std::ios::binary);
m_FileStream.read(m_Version, 7);
m_FileStream.seekg(-8, std::ios::end); // move file pointer to 8 bytes before the end (location of the address of the record count)
uint32_t recordCountPos = 0;
BinaryIO::BinaryRead<uint32_t>(m_FileStream, recordCountPos);
m_FileStream.seekg(recordCountPos, std::ios::beg);
BinaryIO::BinaryRead<uint32_t>(m_FileStream, m_RecordCount);
for (int i = 0; i < m_RecordCount; i++) {
PackRecord record;
BinaryIO::BinaryRead<PackRecord>(m_FileStream, record);
m_Records.push_back(record);
}
m_FileStream.close();
}
bool Pack::HasFile(uint32_t crc) {
for (const auto& record : m_Records) {
if (record.m_Crc == crc) {
return true;
}
}
return false;
}
bool Pack::ReadFileFromPack(uint32_t crc, char** data, uint32_t* len) {
// Time for some wacky C file reading for speed reasons
PackRecord pkRecord{};
for (const auto& record : m_Records) {
if (record.m_Crc == crc) {
pkRecord = record;
break;
}
}
if (pkRecord.m_Crc == 0) return false;
size_t pos = 0;
pos += pkRecord.m_FilePointer;
bool isCompressed = (pkRecord.m_IsCompressed & 0xff) > 0;
auto inPackSize = isCompressed ? pkRecord.m_CompressedSize : pkRecord.m_UncompressedSize;
FILE* file;
#ifdef _WIN32
fopen_s(&file, m_FilePath.string().c_str(), "rb");
#elif __APPLE__
// macOS has 64bit file IO by default
file = fopen(m_FilePath.string().c_str(), "rb");
#else
file = fopen64(m_FilePath.string().c_str(), "rb");
#endif
fseek(file, pos, SEEK_SET);
if (!isCompressed) {
char* tempData = static_cast<char*>(malloc(pkRecord.m_UncompressedSize));
int32_t readInData = fread(tempData, sizeof(uint8_t), pkRecord.m_UncompressedSize, file);
*data = tempData;
*len = pkRecord.m_UncompressedSize;
fclose(file);
return true;
}
pos += 5; // skip header
fseek(file, pos, SEEK_SET);
char* decompressedData = static_cast<char*>(malloc(pkRecord.m_UncompressedSize));
uint32_t currentReadPos = 0;
while (true) {
if (currentReadPos >= pkRecord.m_UncompressedSize) break;
uint32_t size;
int32_t readInData = fread(&size, sizeof(uint32_t), 1, file);
pos += 4; // Move pointer position 4 to the right
char* chunk = static_cast<char*>(malloc(size));
int32_t readInData2 = fread(chunk, sizeof(int8_t), size, file);
pos += size; // Move pointer position the amount of bytes read to the right
int32_t err;
currentReadPos += ZCompression::Decompress(reinterpret_cast<uint8_t*>(chunk), size, reinterpret_cast<uint8_t*>(decompressedData + currentReadPos), ZCompression::MAX_SD0_CHUNK_SIZE, err);
free(chunk);
}
*data = decompressedData;
*len = pkRecord.m_UncompressedSize;
fclose(file);
return true;
}

39
dCommon/dClient/Pack.h Normal file
View File

@@ -0,0 +1,39 @@
#pragma once
#include <vector>
#include <string>
#include <filesystem>
#include <fstream>
#pragma pack(push, 1)
struct PackRecord {
uint32_t m_Crc;
int32_t m_LowerCrc;
int32_t m_UpperCrc;
uint32_t m_UncompressedSize;
char m_UncompressedHash[32];
uint32_t m_Padding1;
uint32_t m_CompressedSize;
char m_CompressedHash[32];
uint32_t m_Padding2;
uint32_t m_FilePointer;
uint32_t m_IsCompressed; // u32 bool
};
#pragma pack(pop)
class Pack {
public:
Pack(const std::filesystem::path& filePath);
~Pack() = default;
bool HasFile(uint32_t crc);
bool ReadFileFromPack(uint32_t crc, char** data, uint32_t* len);
private:
std::ifstream m_FileStream;
std::filesystem::path m_FilePath;
char m_Version[7];
uint32_t m_RecordCount;
std::vector<PackRecord> m_Records;
};

View File

@@ -0,0 +1,43 @@
#include "PackIndex.h"
#include "BinaryIO.h"
#include "Game.h"
#include "Logger.h"
PackIndex::PackIndex(const std::filesystem::path& filePath) {
m_FileStream = std::ifstream(filePath / "versions" / "primary.pki", std::ios::in | std::ios::binary);
BinaryIO::BinaryRead<uint32_t>(m_FileStream, m_Version);
BinaryIO::BinaryRead<uint32_t>(m_FileStream, m_PackPathCount);
m_PackPaths.resize(m_PackPathCount);
for (auto& item : m_PackPaths) {
BinaryIO::ReadString<uint32_t>(m_FileStream, item, BinaryIO::ReadType::String);
}
BinaryIO::BinaryRead<uint32_t>(m_FileStream, m_PackFileIndexCount);
for (int i = 0; i < m_PackFileIndexCount; i++) {
PackFileIndex packFileIndex;
BinaryIO::BinaryRead<PackFileIndex>(m_FileStream, packFileIndex);
m_PackFileIndices.push_back(packFileIndex);
}
LOG("Loaded pack catalog with %i pack files and %i files", m_PackPaths.size(), m_PackFileIndices.size());
for (auto& item : m_PackPaths) {
std::replace(item.begin(), item.end(), '\\', '/');
auto* pack = new Pack(filePath / item);
m_Packs.push_back(pack);
}
m_FileStream.close();
}
PackIndex::~PackIndex() {
for (const auto* item : m_Packs) {
delete item;
}
}

View File

@@ -0,0 +1,40 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#include <filesystem>
#include "Pack.h"
#pragma pack(push, 1)
struct PackFileIndex {
uint32_t m_Crc;
int32_t m_LowerCrc;
int32_t m_UpperCrc;
uint32_t m_PackFileIndex;
uint32_t m_IsCompressed; // u32 bool?
};
#pragma pack(pop)
class PackIndex {
public:
PackIndex(const std::filesystem::path& filePath);
~PackIndex();
const std::vector<std::string>& GetPackPaths() { return m_PackPaths; }
const std::vector<PackFileIndex>& GetPackFileIndices() { return m_PackFileIndices; }
const std::vector<Pack*>& GetPacks() { return m_Packs; }
private:
std::ifstream m_FileStream;
uint32_t m_Version;
uint32_t m_PackPathCount;
std::vector<std::string> m_PackPaths;
uint32_t m_PackFileIndexCount;
std::vector<PackFileIndex> m_PackFileIndices;
std::vector<Pack*> m_Packs;
};

View File

@@ -1,642 +0,0 @@
#pragma once
#include <cstdint>
#include <string>
#include <set>
#include "../thirdparty/raknet/Source/BitStream.h"
#pragma warning (disable:4251) //Disables SQL warnings
typedef int RESTICKET;
const int highFrameRate = 16; //60fps
const int mediumFramerate = 33; //30fps
const int lowFramerate = 66; //15fps
//========== MACROS ===========
#define CBITSTREAM RakNet::BitStream bitStream;
#define CINSTREAM RakNet::BitStream inStream(packet->data, packet->length, false);
#define CMSGHEADER PacketUtils::WriteHeader(bitStream, CLIENT, MSG_CLIENT_GAME_MSG);
#define SEND_PACKET Game::server->Send(&bitStream, sysAddr, false);
#define SEND_PACKET_BROADCAST Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
//=========== TYPEDEFS ==========
typedef int32_t LOT; //!< A LOT
typedef int64_t LWOOBJID; //!< An object ID (should be unsigned actually but ok)
typedef int32_t TSkillID; //!< A skill ID
typedef uint32_t LWOCLONEID; //!< Used for Clone IDs
typedef uint16_t LWOMAPID; //!< Used for Map IDs
typedef uint16_t LWOINSTANCEID; //!< Used for Instance IDs
typedef uint32_t PROPERTYCLONELIST; //!< Used for Property Clone IDs
typedef int32_t PetTamingPiece; //!< Pet Taming Pieces
const LWOOBJID LWOOBJID_EMPTY = 0; //!< An empty object ID
const LOT LOT_NULL = -1; //!< A null LOT
const int32_t LOOTTYPE_NONE = 0; //!< No loot type available
const float SECONDARY_PRIORITY = 1.0f; //!< Secondary Priority
const uint32_t INVENTORY_INVALID = -1; //!< Invalid Inventory
const uint32_t INVENTORY_DEFAULT = -1; //!< Default Inventory
const uint32_t StatusChangeInfo = 0; //!< Status Change Info (???)
const uint32_t INVENTORY_MAX = 9999999; //!< The Maximum Inventory Size
const uint32_t LWOCLONEID_INVALID = -1; //!< Invalid LWOCLONEID
const uint16_t LWOINSTANCEID_INVALID = -1; //!< Invalid LWOINSTANCEID
const uint16_t LWOMAPID_INVALID = -1; //!< Invalid LWOMAPID
const uint64_t LWOZONEID_INVALID = 0; //!< Invalid LWOZONEID
typedef std::set<LWOOBJID> TSetObjID;
const float PI = 3.14159f;
#if defined(__unix) || defined(__APPLE__)
//For Linux:
typedef __int64_t __int64;
#endif
//============ STRUCTS ==============
struct LWOSCENEID {
public:
LWOSCENEID() { m_sceneID = -1; m_layerID = 0; }
LWOSCENEID(int sceneID) { m_sceneID = sceneID; m_layerID = 0; }
LWOSCENEID(int sceneID, unsigned int layerID) { m_sceneID = sceneID; m_layerID = layerID; }
LWOSCENEID& operator=(const LWOSCENEID& rhs) { m_sceneID = rhs.m_sceneID; m_layerID = rhs.m_layerID; return *this; }
LWOSCENEID& operator=(const int rhs) { m_sceneID = rhs; m_layerID = 0; return *this; }
bool operator<(const LWOSCENEID& rhs) const { return (m_sceneID < rhs.m_sceneID || (m_sceneID == rhs.m_sceneID && m_layerID < rhs.m_layerID)); }
bool operator<(const int rhs) const { return m_sceneID < rhs; }
bool operator==(const LWOSCENEID& rhs) const { return (m_sceneID == rhs.m_sceneID && m_layerID == rhs.m_layerID); }
bool operator==(const int rhs) const { return m_sceneID == rhs; }
const int GetSceneID() const { return m_sceneID; }
const unsigned int GetLayerID() const { return m_layerID; }
void SetSceneID(const int sceneID) { m_sceneID = sceneID; }
void SetLayerID(const unsigned int layerID) { m_layerID = layerID; }
private:
int m_sceneID;
unsigned int m_layerID;
};
struct LWOZONEID {
public:
const LWOMAPID& GetMapID() const { return m_MapID; }
const LWOINSTANCEID& GetInstanceID() const { return m_InstanceID; }
const LWOCLONEID& GetCloneID() const { return m_CloneID; }
//In order: def constr, constr, assign op
LWOZONEID() { m_MapID = LWOMAPID_INVALID; m_InstanceID = LWOINSTANCEID_INVALID; m_CloneID = LWOCLONEID_INVALID; }
LWOZONEID(const LWOMAPID& mapID, const LWOINSTANCEID& instanceID, const LWOCLONEID& cloneID) { m_MapID = mapID; m_InstanceID = instanceID; m_CloneID = cloneID; }
LWOZONEID(const LWOZONEID& replacement) { *this = replacement; }
private:
LWOMAPID m_MapID; //1000 for VE, 1100 for AG, etc...
LWOINSTANCEID m_InstanceID; //Instances host the same world, but on a different dWorld process.
LWOCLONEID m_CloneID; //To differentiate between "your property" and "my property". Always 0 for non-prop worlds.
};
const LWOSCENEID LWOSCENEID_INVALID = -1;
struct LWONameValue {
uint32_t length = 0; //!< The length of the name
std::u16string name; //!< The name
LWONameValue(void) {}
LWONameValue(const std::u16string& name) {
this->name = name;
this->length = static_cast<uint32_t>(name.length());
}
~LWONameValue(void) {}
};
struct FriendData {
public:
bool isOnline = false;
bool isBestFriend = false;
bool isFTP = false;
LWOZONEID zoneID;
LWOOBJID friendID;
std::string friendName;
void Serialize(RakNet::BitStream& bitStream) {
bitStream.Write<uint8_t>(isOnline);
bitStream.Write<uint8_t>(isBestFriend);
bitStream.Write<uint8_t>(isFTP);
bitStream.Write<uint32_t>(0); //???
bitStream.Write<uint8_t>(0); //???
bitStream.Write(zoneID.GetMapID());
bitStream.Write(zoneID.GetInstanceID());
bitStream.Write(zoneID.GetCloneID());
bitStream.Write(friendID);
uint32_t maxSize = 33;
uint32_t size = static_cast<uint32_t>(friendName.length());
uint32_t remSize = static_cast<uint32_t>(maxSize - size);
if (size > maxSize) size = maxSize;
for (uint32_t i = 0; i < size; ++i) {
bitStream.Write(static_cast<uint16_t>(friendName[i]));
}
for (uint32_t j = 0; j < remSize; ++j) {
bitStream.Write(static_cast<uint16_t>(0));
}
bitStream.Write<uint32_t>(0); //???
bitStream.Write<uint16_t>(0); //???
}
};
struct Brick {
uint32_t designerID;
uint32_t materialID;
};
//This union is used by the behavior system
union suchar {
unsigned char usigned;
char svalue;
};
//=========== DLU ENUMS ============
enum eGameMasterLevel : int32_t {
GAME_MASTER_LEVEL_CIVILIAN = 0, // Normal player.
GAME_MASTER_LEVEL_FORUM_MODERATOR = 1, // No permissions on live servers.
GAME_MASTER_LEVEL_JUNIOR_MODERATOR = 2, // Can kick/mute and pull chat logs.
GAME_MASTER_LEVEL_MODERATOR = 3, // Can return lost items.
GAME_MASTER_LEVEL_SENIOR_MODERATOR = 4, // Can ban.
GAME_MASTER_LEVEL_LEAD_MODERATOR = 5, // Can approve properties.
GAME_MASTER_LEVEL_JUNIOR_DEVELOPER = 6, // Junior developer & future content team. Civilan on live.
GAME_MASTER_LEVEL_INACTIVE_DEVELOPER = 7, // Inactive developer, limited permissions.
GAME_MASTER_LEVEL_DEVELOPER = 8, // Active developer, full permissions on live.
GAME_MASTER_LEVEL_OPERATOR = 9 // Can shutdown server for restarts & updates.
};
//=========== LU ENUMS ============
//! An enum for object ID bits
enum eObjectBits : int32_t {
OBJECT_BIT_PERSISTENT = 32, //!< The 32 bit index
OBJECT_BIT_CLIENT = 46, //!< The 46 bit index
OBJECT_BIT_SPAWNED = 58, //!< The 58 bit index
OBJECT_BIT_CHARACTER = 60 //!< The 60 bit index
};
//! An enum for MatchUpdate types
enum eMatchUpdate : int {
MATCH_UPDATE_PLAYER_JOINED = 0,
MATCH_UPDATE_PLAYER_LEFT = 1,
MATCH_UPDATE_TIME = 3,
MATCH_UPDATE_TIME_START_DELAY = 4,
MATCH_UPDATE_PLAYER_READY = 5,
MATCH_UPDATE_PLAYER_UNREADY = 6
};
//! An enum for camera cycling modes
enum eCyclingMode : uint32_t {
ALLOW_CYCLE_TEAMMATES,
DISALLOW_CYCLING
};
enum eCinematicEvent : uint32_t {
STARTED,
WAYPOINT,
ENDED,
};
//! An enum for character creation responses
enum eCreationResponse : uint8_t {
CREATION_RESPONSE_SUCCESS = 0, //!< The creation was successful
CREATION_RESPONSE_OBJECT_ID_UNAVAILABLE, //!< The Object ID can't be used
CREATION_RESPONSE_NAME_NOT_ALLOWED, //!< The name is not allowed
CREATION_RESPONSE_PREDEFINED_NAME_IN_USE, //!< The predefined name is already in use
CREATION_RESPONSE_CUSTOM_NAME_IN_USE //!< The custom name is already in use
};
//! An enum for login responses
enum eLoginResponse : uint8_t {
LOGIN_RESPONSE_GENERAL_FAILED = 0,
LOGIN_RESPONSE_SUCCESS = 1,
LOGIN_RESPONSE_BANNED = 2,
LOGIN_RESPONSE_PERMISSIONS_NOT_HIGH_ENOUGH = 5,
LOGIN_RESPONSE_WRONG_PASS_OR_USER = 6,
LOGIN_RESPONSE_ACCOUNT_LOCKED = 7
};
//! An enum for character rename responses
enum eRenameResponse : uint8_t {
RENAME_RESPONSE_SUCCESS = 0, //!< The renaming was successful
RENAME_RESPONSE_UNKNOWN_ERROR, //!< There was an unknown error
RENAME_RESPONSE_NAME_UNAVAILABLE, //!< The name is unavailable
RENAME_RESPONSE_NAME_IN_USE //!< The name is already in use
};
//! A replica packet type
enum eReplicaPacketType {
PACKET_TYPE_CONSTRUCTION, //!< A construction packet
PACKET_TYPE_SERIALIZATION, //!< A serialization packet
PACKET_TYPE_DESTRUCTION //!< A destruction packet
};
enum ServerDisconnectIdentifiers {
SERVER_DISCON_UNKNOWN_SERVER_ERROR = 0, //!< Unknown server error
SERVER_DISCON_DUPLICATE_LOGIN = 4, //!< Used when another user with the same username is logged in (duplicate login)
SERVER_DISCON_SERVER_SHUTDOWN = 5, //!< Used when the server is shutdown
SERVER_DISCON_SERVER_MAP_LOAD_FAILURE = 6, //!< Used when the server cannot load a map
SERVER_DISCON_INVALID_SESSION_KEY = 7, //!< Used if the session is invalid
SERVER_DISCON_ACCOUNT_NOT_IN_PENDING_LIST = 8, //!< ???
SERVER_DISCON_CHARACTER_NOT_FOUND = 9, //!< Used if a character that the server has is not found (i.e, corruption with user-player data)
SERVER_DISCON_CHARACTER_CORRUPTED = 10, //!< Similar to abovce
SERVER_DISCON_KICK = 11, //!< Used if the user is kicked from the server
SERVER_DISCON_FREE_TRIAL_EXPIRED = 12, //!< Used if the user's free trial expired
SERVER_DISCON_PLAY_SCHEDULE_TIME_DONE = 13 //!< Used if the user's play time is used up
};
//! The Behavior Types for use with the AI system
enum eCombatBehaviorTypes : uint32_t {
PASSIVE = 0, //!< The object is passive
AGGRESSIVE = 1, //!< The object is aggressive
PASSIVE_TURRET = 2, //!< The object is a passive turret
AGGRESSIVE_TURRET = 3 //!< The object is an aggressive turret
};
//! The Combat Role Type for use with the AI system
enum eCombatRoleType : uint32_t {
MELEE = 0, //!< Used for melee attacks
RANGED = 1, //!< Used for range attacks
SUPPORT = 2 //!< Used for support
};
//! The kill types for the Die packet
enum eKillType : uint32_t {
VIOLENT,
SILENT
};
//! The various world states used throughout the server
enum eObjectWorldState {
WORLDSTATE_INWORLD, //!< Probably used when the object is in the world
WORLDSTATE_ATTACHED, //!< Probably used when the object is attached to another object
WORLDSTATE_INVENTORY //!< Probably used when the object is in an inventory
};
//! The trigger stats (???)
enum eTriggerStat {
INVALID_STAT, //!< ???
HEALTH, //!< Probably used for health
ARMOR, //!< Probably used for armor
IMAGINATION //!< Probably used for imagination
};
//! The trigger operations (???)
enum eTriggerOperator {
INVALID_OPER, //!< ???
EQUAL, //!< ???
NOT_EQUAL, //!< ???
GREATER, //!< ???
GREATER_EQUAL, //!< ???
LESS, //!< ???
LESS_EQUAL //!< ???
};
//! The various build types
enum eBuildType {
BUILD_NOWHERE, //!< Used if something can't be built anywhere
BUILD_IN_WORLD, //!< Used if something can be built in the world
BUILD_ON_PROPERTY //!< Used if something can be build on a property
};
//! Quickbuild fail reasons
enum eFailReason : uint32_t {
REASON_NOT_GIVEN,
REASON_OUT_OF_IMAGINATION,
REASON_CANCELED_EARLY,
REASON_BUILD_ENDED
};
//! Terminate interaction type
enum eTerminateType : uint32_t {
RANGE,
USER,
FROM_INTERACTION
};
//! The combat state
enum eCombatState {
IDLE, //!< The AI is in an idle state
AGGRO, //!< The AI is in an aggressive state
TETHER, //!< The AI is being redrawn back to tether point
SPAWN, //!< The AI is spawning
DEAD //!< The AI is dead
};
enum eControlSceme {
SCHEME_A,
SCHEME_D,
SCHEME_GAMEPAD,
SCHEME_E,
SCHEME_FPS,
SCHEME_DRIVING,
SCHEME_TAMING,
SCHEME_MODULAR_BUILD,
SCHEME_WEAR_A_ROBOT //== freecam?
};
enum eStunState {
PUSH,
POP
};
enum eNotifyType {
NOTIFY_TYPE_SUCCESS,
NOTIFY_TYPE_QUIT,
NOTIFY_TYPE_FAILED,
NOTIFY_TYPE_BEGIN,
NOTIFY_TYPE_READY,
NOTIFY_TYPE_NAMINGPET
};
enum eReplicaComponentType : int32_t {
COMPONENT_TYPE_CONTROLLABLE_PHYSICS = 1, //!< The ControllablePhysics Component
COMPONENT_TYPE_RENDER = 2, //!< The Render Component
COMPONENT_TYPE_SIMPLE_PHYSICS = 3, //!< The SimplePhysics Component
COMPONENT_TYPE_CHARACTER = 4, //!< The Character Component
COMPONENT_TYPE_SCRIPT = 5, //!< The Script Component
COMPONENT_TYPE_BOUNCER = 6, //!< The Bouncer Component
COMPONENT_TYPE_BUFF = 7, //!< The Buff Component
COMPONENT_TYPE_SKILL = 9, //!< The Skill Component
COMPONENT_TYPE_ITEM = 11, //!< The Item Component
COMPONENT_TYPE_VENDOR = 16, //!< The Vendor Component
COMPONENT_TYPE_INVENTORY = 17, //!< The Inventory Component
COMPONENT_TYPE_SHOOTING_GALLERY = 19, //!< The Shooting Gallery Component
COMPONENT_TYPE_RIGID_BODY_PHANTOM_PHYSICS = 20, //!< The RigidBodyPhantomPhysics Component
COMPONENT_TYPE_COLLECTIBLE = 23, //!< The Collectible Component
COMPONENT_TYPE_MOVING_PLATFORM = 25, //!< The MovingPlatform Component
COMPONENT_TYPE_PET = 26, //!< The Pet Component
COMPONENT_TYPE_VEHICLE_PHYSICS = 30, //!< The VehiclePhysics Component
COMPONENT_TYPE_MOVEMENT_AI = 31, //!< The MovementAI Component
COMPONENT_TYPE_PROPERTY = 36, //!< The Property Component
COMPONENT_TYPE_SCRIPTED_ACTIVITY = 39, //!< The ScriptedActivity Component
COMPONENT_TYPE_PHANTOM_PHYSICS = 40, //!< The PhantomPhysics Component
COMPONENT_TYPE_PROPERTY_ENTRANCE = 43, //!< The PhantomPhysics Component
COMPONENT_TYPE_PROPERTY_MANAGEMENT = 45, //!< The PropertyManagement Component
COMPONENT_TYPE_REBUILD = 48, //!< The Rebuild Component
COMPONENT_TYPE_SWITCH = 49, //!< The Switch Component
COMPONENT_TYPE_ZONE_CONTROL = 50, //!< The ZoneControl Component
COMPONENT_TYPE_PACKAGE = 53, //!< The Package Component
COMPONENT_TYPE_PLAYER_FLAG = 58, //!< The PlayerFlag Component
COMPONENT_TYPE_BASE_COMBAT_AI = 60, //!< The BaseCombatAI Component
COMPONENT_TYPE_MODULE_ASSEMBLY = 61, //!< The ModuleAssembly Component
COMPONENT_TYPE_PROPERTY_VENDOR = 65, //!< The PropertyVendor Component
COMPONENT_TYPE_ROCKET_LAUNCH = 67, //!< The RocketLaunch Component
COMPONENT_TYPE_RACING_CONTROL = 71, //!< The RacingControl Component
COMPONENT_TYPE_MISSION_OFFER = 73, //!< The MissionOffer Component
COMPONENT_TYPE_EXHIBIT = 75, //!< The Exhibit Component
COMPONENT_TYPE_RACING_STATS = 74, //!< The Exhibit Component
COMPONENT_TYPE_SOUND_TRIGGER = 77, //!< The Sound Trigger Component
COMPONENT_TYPE_PROXIMITY_MONITOR = 78, //!< The Proximity Monitor Component
COMPONENT_TYPE_MISSION = 84, //!< The Mission Component
COMPONENT_TYPE_ROCKET_LAUNCH_LUP = 97, //!< The LUP Launchpad Componen
COMPONENT_TYPE_RAIL_ACTIVATOR = 104,
COMPONENT_TYPE_POSSESSOR = 107, //!< The Component 107
COMPONENT_TYPE_POSSESSABLE = 108, //!< The Component 108
COMPONENT_TYPE_BUILD_BORDER = 114, //!< The Build Border Component
COMPONENT_TYPE_DESTROYABLE = 1000, //!< The Destroyable Component
COMPONENT_TYPE_MODEL = 5398484 //look man idk
};
/**
* Represents the different types of inventories an entity may have
*/
enum eInventoryType : uint32_t {
ITEMS = 0,
VAULT_ITEMS,
BRICKS,
TEMP_ITEMS = 4,
MODELS,
TEMP_MODELS,
BEHAVIORS,
PROPERTY_DEEDS,
VENDOR_BUYBACK = 11,
HIDDEN = 12, //Used for missional items
VAULT_MODELS = 14,
ITEM_SETS, //internal
INVALID // made up, for internal use!!!
};
enum eItemType : int32_t {
ITEM_TYPE_UNKNOWN = -1, //!< An unknown item type
ITEM_TYPE_BRICK = 1, //!< A brick
ITEM_TYPE_HAT = 2, //!< A hat / head item
ITEM_TYPE_HAIR = 3, //!< A hair item
ITEM_TYPE_NECK = 4, //!< A neck item
ITEM_TYPE_LEFT_HAND = 5, //!< A left handed item
ITEM_TYPE_RIGHT_HAND = 6, //!< A right handed item
ITEM_TYPE_LEGS = 7, //!< A pants item
ITEM_TYPE_LEFT_TRINKET = 8, //!< A left handled trinket item
ITEM_TYPE_RIGHT_TRINKET = 9, //!< A right handed trinket item
ITEM_TYPE_BEHAVIOR = 10, //!< A behavior
ITEM_TYPE_PROPERTY = 11, //!< A property
ITEM_TYPE_MODEL = 12, //!< A model
ITEM_TYPE_COLLECTIBLE = 13, //!< A collectible item
ITEM_TYPE_CONSUMABLE = 14, //!< A consumable item
ITEM_TYPE_CHEST = 15, //!< A chest item
ITEM_TYPE_EGG = 16, //!< An egg
ITEM_TYPE_PET_FOOD = 17, //!< A pet food item
ITEM_TYPE_QUEST_OBJECT = 18, //!< A quest item
ITEM_TYPE_PET_INVENTORY_ITEM = 19, //!< A pet inventory item
ITEM_TYPE_PACKAGE = 20, //!< A package
ITEM_TYPE_LOOT_MODEL = 21, //!< A loot model
ITEM_TYPE_VEHICLE = 22, //!< A vehicle
ITEM_TYPE_CURRENCY = 23 //!< Currency
};
enum eRebuildState : uint32_t {
REBUILD_OPEN,
REBUILD_COMPLETED = 2,
REBUILD_RESETTING = 4,
REBUILD_BUILDING,
REBUILD_INCOMPLETE
};
enum eGameActivities : uint32_t {
ACTIVITY_NONE,
ACTIVITY_QUICKBUILDING,
ACTIVITY_SHOOTING_GALLERY,
ACTIVITY_RACING,
ACTIVITY_PINBALL,
ACTIVITY_PET_TAMING
};
enum ePlayerFlags {
BTARR_TESTING = 0,
PLAYER_HAS_ENTERED_PET_RANCH = 1,
MINIMAP_UNLOCKED = 2,
ACTIVITY_REBUILDING_FAIL_TIME = 3,
ACTIVITY_REBUILDING_FAIL_RANGE = 4,
ACTIVITY_SHOOTING_GALLERY_HELP = 5,
HELP_WALKING_CONTROLS = 6,
FIRST_SMASHABLE = 7,
FIRST_IMAGINATION_PICKUP = 8,
FIRST_DAMAGE = 9,
FIRST_ITEM = 10,
FIRST_BRICK = 11,
FIRST_CONSUMABLE = 12,
FIRST_EQUIPPABLE = 13,
CHAT_HELP = 14,
FIRST_PET_TAMING_MINIGAME = 15,
FIRST_PET_ON_SWITCH = 16,
FIRST_PET_JUMPED_ON_SWITCH = 17,
FIRST_PET_FOUND_TREASURE = 18,
FIRST_PET_DUG_TREASURE = 19,
FIRST_PET_OWNER_ON_PET_BOUNCER = 20,
FIRST_PET_DESPAWN_NO_IMAGINATION = 21,
FIRST_PET_SELECTED_ENOUGH_BRICKS = 22,
FIRST_EMOTE_UNLOCKED = 23,
GF_PIRATE_REP = 24,
AG_BOB_CINEMATIC_EVENT = 25,
HELP_JUMPING_CONTROLS = 26,
HELP_DOUBLE_JUMP_CONTROLS = 27,
HELP_CAMERA_CONTROLS = 28,
HELP_ROTATE_CONTROLS = 29,
HELP_SMASH = 30,
MONUMENT_INTRO_MUSIC_PLAYED = 31,
BEGINNING_ZONE_SUMMARY_DISPLAYED = 32,
AG_FINISH_LINE_BUILT = 33,
AG_BOSS_AREA_FOUND = 34,
AG_LANDED_IN_BATTLEFIELD = 35,
GF_PLAYER_HAS_BEEN_TO_THE_RAVINE = 36,
MODULAR_BUILD_STARTED = 37,
MODULAR_BUILD_FINISHED_CLICK_BUTTON = 38,
THINKING_HAT_RECEIVED_GO_TO_MODULAR_BUILD_AREA = 39,
BUILD_AREA_ENTERED_MOD_NOT_ACTIVATED_PUT_ON_HAT = 40,
HAT_ON_INSIDE_OF_MOD_BUILD_EQUIP_A_MODULE_FROM_LEG = 41,
MODULE_EQUIPPED_PLACE_ON_GLOWING_BLUE_SPOT = 42,
FIRST_MODULE_PLACED_CORRECTLY_NOW_DO_THE_REST = 43,
ROCKET_COMPLETE_NOW_LAUNCH_FROM_PAD = 44,
JOINED_A_FACTION = 45,
VENTURE_FACTION = 46,
ASSEMBLY_FACTION = 47,
PARADOX_FACTION = 48,
SENTINEL_FACTION = 49,
LUP_WORLD_ACCESS = 50,
AG_FIRST_FLAG_COLLECTED = 51,
TOOLTIP_TALK_TO_SKYLAND_TO_GET_HAT = 52,
MODULAR_BUILD_PLAYER_PLACES_FIRST_MODEL_IN_SCRATCH = 53,
MODULAR_BUILD_FIRST_ARROW_DISPLAY_FOR_MODULE = 54,
AG_BEACON_QB,_SO_THE_PLAYER_CAN_ALWAYS_BUILD_THEM = 55,
GF_PET_DIG_FLAG_1 = 56,
GF_PET_DIG_FLAG_2 = 57,
GF_PET_DIG_FLAG_3 = 58,
SUPPRESS_SPACESHIP_CINEMATIC_FLYTHROUGH = 59,
GF_PLAYER_FALL_DEATH = 60,
GF_PLAYER_CAN_GET_FLAG_1 = 61,
GF_PLAYER_CAN_GET_FLAG_2 = 62,
GF_PLAYER_CAN_GET_FLAG_3 = 63,
ENTER_BBB_FROM_PROPERTY_EDIT_CONFIRMATION_DIALOG = 64,
AG_FIRST_COMBAT_COMPLETE = 65,
AG_COMPLETE_BOB_MISSION = 66,
NJ_GARMADON_CINEMATIC_SEEN = 125,
ELEPHANT_PET_3050 = 801,
CAT_PET_3054 = 802,
TRICERATOPS_PET_3195 = 803,
TERRIER_PET_3254 = 804,
SKUNK_PET_3261 = 805,
LION_PET_3520 = 806,
BUNNY_PET_3672 = 807,
CROCODILE_PET_3994 = 808,
DOBERMAN_PET_5635 = 809,
BUFFALO_PET_5636 = 810,
ROBOT_DOG_PET_5637 = 811,
EUROPEAN_DRAGON_PET_5639 = 812,
TORTOISE_PET_5640 = 813,
ASIAN_DRAGON_PET_5641 = 814,
MANTIS_PET_5642 = 815,
PANDA_PET_5643 = 816,
WARTHOG_PET_6720 = 817,
GOAT_PET_7638 = 818,
CRAB_PET_7694 = 819,
AG_SPACE_SHIP_BINOC_AT_LAUNCH = 1001,
AG_SPACE_SHIP_BINOC_AT_LAUNCH_PLATFORM = 1002,
AG_SPACE_SHIP_BINOC_ON_PLATFORM_TO_LEFT_OF_START = 1003,
AG_SPACE_SHIP_BINOC_ON_PLATFORM_TO_RIGHT_OF_START = 1004,
AG_SPACE_SHIP_BINOC_AT_BOB = 1005,
AG_BATTLE_BINOC_FOR_TRICERETOPS = 1101,
AG_BATTLE_BINOC_AT_PARADOX = 1102,
AG_BATTLE_BINOC_AT_MISSION_GIVER = 1103,
AG_BATTLE_BINOC_AT_BECK = 1104,
AG_MONUMENT_BINOC_INTRO = 1105,
AG_MONUMENT_BINOC_OUTRO = 1106,
AG_LAUNCH_BINOC_INTRO = 1107,
AG_LAUNCH_BINOC_BISON = 1108,
AG_LAUNCH_BINOC_SHARK = 1109,
NS_BINOC_CONCERT_TRANSITION = 1201,
NS_BINOC_RACE_PLACE_TRANSITION = 1202,
NS_BINOC_BRICK_ANNEX_TRANSITION = 1203,
NS_BINOC_GF_LAUNCH = 1204,
NS_BINOC_FV_LAUNCH = 1205,
NS_BINOC_BRICK_ANNEX_WATER = 1206,
NS_BINOC_AG_LAUNCH_AT_RACE_PLACE = 1207,
NS_BINOC_AG_LAUNCH_AT_BRICK_ANNEX = 1208,
NS_BINOC_AG_LAUNCH_AT_PLAZA = 1209,
NS_BINOC_TBA = 1210,
NS_FLAG_COLLECTABLE_1_BY_JONNY_THUNDER = 1211,
NS_FLAG_COLLECTABLE_2_UNDER_CONCERT_BRIDGE = 1212,
NS_FLAG_COLLECTABLE_3_BY_FV_LAUNCH = 1213,
NS_FLAG_COLLECTABLE_4_IN_PLAZA_BEHIND_BUILDING = 1214,
NS_FLAG_COLLECTABLE_5_BY_GF_LAUNCH = 1215,
NS_FLAG_COLLECTABLE_6_BY_DUCK_SG = 1216,
NS_FLAG_COLLECTABLE_7_BY_LUP_LAUNCH = 1217,
NS_FLAG_COLLECTABLE_8_BY_NT_LUANCH = 1218,
NS_FLAG_COLLECTABLE_9_BY_RACE_BUILD = 1219,
NS_FLAG_COLLECTABLE_10_ON_AG_LAUNCH_PATH = 1220,
PR_BINOC_AT_LAUNCH_PAD = 1251,
PR_BINOC_AT_BEGINNING_OF_ISLAND_B = 1252,
PR_BINOC_AT_FIRST_PET_BOUNCER = 1253,
PR_BINOC_ON_BY_CROWS_NEST = 1254,
PR_PET_DIG_AT_BEGINNING_OF_ISLAND_B = 1261,
PR_PET_DIG_AT_THE_LOCATION_OF_OLD_BOUNCE_BACK = 1262,
PR_PET_DIG_UNDER_QB_BRIDGE = 1263,
PR_PET_DIG_BACK_SIDE_BY_PARTNER_BOUNCE = 1264,
PR_PET_DIG_BY_LAUNCH_PAD = 1265,
PR_PET_DIG_BY_FIRST_PET_BOUNCER = 1266,
GF_BINOC_ON_LANDING_PAD = 1301,
GF_BINOC_AT_RAVINE_START = 1302,
GF_BINOC_ON_TOP_OF_RAVINE_HEAD = 1303,
GF_BINOC_AT_TURTLE_AREA = 1304,
GF_BINOC_IN_TUNNEL_TO_ELEPHANTS = 1305,
GF_BINOC_IN_ELEPHANTS_AREA = 1306,
GF_BINOC_IN_RACING_AREA = 1307,
GF_BINOC_IN_CROC_AREA = 1308,
GF_BINOC_IN_JAIL_AREA = 1309,
GF_BINOC_TELESCOPE_NEXT_TO_CAPTAIN_JACK = 1310,
NT_FACTION_SPY_DUKE = 1974,
NT_FACTION_SPY_OVERBUILD = 1976,
NT_FACTION_SPY_HAEL = 1977,
NJ_EARTH_SPINJITZU = 2030,
NJ_LIGHTNING_SPINJITZU = 2031,
NJ_ICE_SPINJITZU = 2032,
NJ_FIRE_SPINJITZU = 2033,
NJ_WU_SHOW_DAILY_CHEST = 2099
};
//======== FUNC ===========
template<typename T>
inline T const& clamp(const T& val, const T& low, const T& high) {
if (val < low) return low;
else if (val > high) return high;
return val;
}

View File

@@ -1,45 +1,71 @@
#include "dConfig.h"
#include <sstream>
#include "BinaryPathFinder.h"
#include "GeneralUtils.h"
dConfig::dConfig(const std::string& filepath) {
m_EmptyString = "";
std::ifstream in(filepath);
m_ConfigFilePath = filepath;
LoadConfig();
}
std::filesystem::path GetConfigDir() {
std::filesystem::path config_dir = BinaryPathFinder::GetBinaryDir();
if (const char* env_p = std::getenv("DLU_CONFIG_DIR")) {
config_dir /= env_p;
}
return config_dir;
}
const bool dConfig::Exists(const std::string& filepath) {
std::filesystem::path config_dir = GetConfigDir();
return std::filesystem::exists(config_dir / filepath);
}
void dConfig::LoadConfig() {
std::filesystem::path config_dir = GetConfigDir();
std::ifstream in(config_dir / m_ConfigFilePath);
if (!in.good()) return;
std::string line;
std::string line{};
while (std::getline(in, line)) {
if (line.length() > 0) {
if (line[0] != '#') ProcessLine(line);
}
if (!line.empty() && line.front() != '#') ProcessLine(line);
}
}
dConfig::~dConfig(void) {
std::ifstream sharedConfig(config_dir / "sharedconfig.ini", std::ios::in);
if (!sharedConfig.good()) return;
line.clear();
while (std::getline(sharedConfig, line)) {
if (!line.empty() && line.front() != '#') ProcessLine(line);
}
}
void dConfig::ReloadConfig() {
this->m_ConfigValues.clear();
LoadConfig();
}
const std::string& dConfig::GetValue(std::string key) {
for (size_t i = 0; i < m_Keys.size(); ++i) {
if (m_Keys[i] == key) return m_Values[i];
std::string upper_key(key);
std::transform(upper_key.begin(), upper_key.end(), upper_key.begin(), ::toupper);
if (const char* env_p = std::getenv(upper_key.c_str())) {
this->m_ConfigValues[key] = env_p;
}
return m_EmptyString;
return this->m_ConfigValues[key];
}
void dConfig::ProcessLine(const std::string& line) {
std::stringstream ss(line);
std::string segment;
std::vector<std::string> seglist;
while (std::getline(ss, segment, '=')) {
seglist.push_back(segment);
}
if (seglist.size() != 2) return;
auto splitLoc = line.find('=');
auto key = line.substr(0, splitLoc);
auto value = line.substr(splitLoc + 1);
//Make sure that on Linux, we remove special characters:
if (!seglist[1].empty() && seglist[1][seglist[1].size() - 1] == '\r')
seglist[1].erase(seglist[1].size() - 1);
if (!value.empty() && value.at(value.size() - 1) == '\r') value.erase(value.size() - 1);
m_Keys.push_back(seglist[0]);
m_Values.push_back(seglist[1]);
}
if (this->m_ConfigValues.find(key) != this->m_ConfigValues.end()) return;
this->m_ConfigValues.insert(std::make_pair(key, value));
}

View File

@@ -1,20 +1,38 @@
#pragma once
#include <fstream>
#include <map>
#include <string>
#include <vector>
class dConfig {
public:
dConfig(const std::string& filepath);
~dConfig(void);
/**
* Checks whether the specified filepath exists
*/
static const bool Exists(const std::string& filepath);
/**
* Gets the specified key from the config. Returns an empty string if the value is not found.
*
* @param key Key to find
* @return The keys value in the config
*/
const std::string& GetValue(std::string key);
/**
* Loads the config from a file
*/
void LoadConfig();
/**
* Reloads the config file to reset values
*/
void ReloadConfig();
private:
void ProcessLine(const std::string& line);
private:
std::vector<std::string> m_Keys;
std::vector<std::string> m_Values;
std::string m_EmptyString;
};
std::map<std::string, std::string> m_ConfigValues;
std::string m_ConfigFilePath;
};

View File

@@ -0,0 +1,29 @@
#ifndef __STRINGIFIEDENUM_H__
#define __STRINGIFIEDENUM_H__
#include <string>
#include "magic_enum.hpp"
namespace StringifiedEnum {
template<typename T>
const std::string_view ToString(const T e) {
static_assert(std::is_enum_v<T>, "Not an enum"); // Check type
constexpr auto sv = &magic_enum::enum_entries<T>();
const auto it = std::lower_bound(
sv->begin(), sv->end(), e,
[&](const std::pair<T, std::string_view>& lhs, const T rhs) { return lhs.first < rhs; }
);
std::string_view output;
if (it != sv->end() && it->first == e) {
output = it->second;
} else {
output = "UNKNOWN";
}
return output;
}
}
#endif // !__STRINGIFIEDENUM_H__

View File

@@ -0,0 +1,163 @@
#pragma once
#ifndef __DCOMMONVARS__H__
#define __DCOMMONVARS__H__
#include <cstdint>
#include <string>
#include <set>
#include "BitStream.h"
#include "eConnectionType.h"
#include "eClientMessageType.h"
#include "BitStreamUtils.h"
#pragma warning (disable:4251) //Disables SQL warnings
// These are the same define, but they mean two different things in different contexts
// so a different define to distinguish what calculation is happening will help clarity.
#define FRAMES_TO_MS(x) 1000 / x
#define MS_TO_FRAMES(x) 1000 / x
//=========== FRAME TIMINGS ===========
constexpr uint32_t highFramerate = 60;
constexpr uint32_t mediumFramerate = 30;
constexpr uint32_t lowFramerate = 15;
constexpr uint32_t highFrameDelta = FRAMES_TO_MS(highFramerate);
constexpr uint32_t mediumFrameDelta = FRAMES_TO_MS(mediumFramerate);
constexpr uint32_t lowFrameDelta = FRAMES_TO_MS(lowFramerate);
//========== MACROS ===========
#define HEADER_SIZE 8
#define CBITSTREAM RakNet::BitStream bitStream;
#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 CMSGHEADER BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GAME_MSG);
#define SEND_PACKET Game::server->Send(&bitStream, sysAddr, false);
#define SEND_PACKET_BROADCAST Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
//=========== TYPEDEFS ==========
typedef int32_t LOT; //!< A LOT
typedef int64_t LWOOBJID; //!< An object ID (should be unsigned actually but ok)
typedef int32_t TSkillID; //!< A skill ID
typedef uint32_t LWOCLONEID; //!< Used for Clone IDs
typedef uint16_t LWOMAPID; //!< Used for Map IDs
typedef uint16_t LWOINSTANCEID; //!< Used for Instance IDs
typedef uint32_t PROPERTYCLONELIST; //!< Used for Property Clone IDs
typedef uint32_t StripId;
const LWOOBJID LWOOBJID_EMPTY = 0; //!< An empty object ID
const LOT LOT_NULL = -1; //!< A null LOT
const int32_t LOOTTYPE_NONE = 0; //!< No loot type available
const float SECONDARY_PRIORITY = 1.0f; //!< Secondary Priority
const uint32_t INVENTORY_MAX = 9999999; //!< The Maximum Inventory Size
const uint32_t LWOCLONEID_INVALID = -1; //!< Invalid LWOCLONEID
const uint16_t LWOINSTANCEID_INVALID = -1; //!< Invalid LWOINSTANCEID
const uint16_t LWOMAPID_INVALID = -1; //!< Invalid LWOMAPID
const uint64_t LWOZONEID_INVALID = 0; //!< Invalid LWOZONEID
const float PI = 3.14159f;
//============ STRUCTS ==============
struct LWOSCENEID {
public:
LWOSCENEID() { m_sceneID = -1; m_layerID = 0; }
LWOSCENEID(int sceneID) { m_sceneID = sceneID; m_layerID = 0; }
LWOSCENEID(int sceneID, unsigned int layerID) { m_sceneID = sceneID; m_layerID = layerID; }
LWOSCENEID& operator=(const LWOSCENEID& rhs) { m_sceneID = rhs.m_sceneID; m_layerID = rhs.m_layerID; return *this; }
LWOSCENEID& operator=(const int rhs) { m_sceneID = rhs; m_layerID = 0; return *this; }
bool operator<(const LWOSCENEID& rhs) const { return (m_sceneID < rhs.m_sceneID || (m_sceneID == rhs.m_sceneID && m_layerID < rhs.m_layerID)); }
bool operator<(const int rhs) const { return m_sceneID < rhs; }
bool operator==(const LWOSCENEID& rhs) const { return (m_sceneID == rhs.m_sceneID && m_layerID == rhs.m_layerID); }
bool operator==(const int rhs) const { return m_sceneID == rhs; }
const int GetSceneID() const { return m_sceneID; }
const unsigned int GetLayerID() const { return m_layerID; }
void SetSceneID(const int sceneID) { m_sceneID = sceneID; }
void SetLayerID(const unsigned int layerID) { m_layerID = layerID; }
private:
int m_sceneID;
unsigned int m_layerID;
};
struct LWOZONEID {
public:
const LWOMAPID& GetMapID() const { return m_MapID; }
const LWOINSTANCEID& GetInstanceID() const { return m_InstanceID; }
const LWOCLONEID& GetCloneID() const { return m_CloneID; }
//In order: def constr, constr, assign op
LWOZONEID() { m_MapID = LWOMAPID_INVALID; m_InstanceID = LWOINSTANCEID_INVALID; m_CloneID = LWOCLONEID_INVALID; }
LWOZONEID(const LWOMAPID& mapID, const LWOINSTANCEID& instanceID, const LWOCLONEID& cloneID) { m_MapID = mapID; m_InstanceID = instanceID; m_CloneID = cloneID; }
LWOZONEID(const LWOZONEID& replacement) { *this = replacement; }
private:
LWOMAPID m_MapID; //1000 for VE, 1100 for AG, etc...
LWOINSTANCEID m_InstanceID; //Instances host the same world, but on a different dWorld process.
LWOCLONEID m_CloneID; //To differentiate between "your property" and "my property". Always 0 for non-prop worlds.
};
const LWOSCENEID LWOSCENEID_INVALID = -1;
struct LWONameValue {
uint32_t length = 0; //!< The length of the name
std::u16string name; //!< The name
LWONameValue(void) {}
LWONameValue(const std::u16string& name) {
this->name = name;
this->length = static_cast<uint32_t>(name.length());
}
~LWONameValue(void) {}
};
struct FriendData {
public:
bool isOnline = false;
bool isBestFriend = false;
bool isFTP = false;
LWOZONEID zoneID;
LWOOBJID friendID;
std::string friendName;
void Serialize(RakNet::BitStream& bitStream) const {
bitStream.Write<uint8_t>(isOnline);
bitStream.Write<uint8_t>(isBestFriend);
bitStream.Write<uint8_t>(isFTP);
bitStream.Write<uint32_t>(0); //???
bitStream.Write<uint8_t>(0); //???
bitStream.Write(zoneID.GetMapID());
bitStream.Write(zoneID.GetInstanceID());
bitStream.Write(zoneID.GetCloneID());
bitStream.Write(friendID);
uint32_t maxSize = 33;
uint32_t size = static_cast<uint32_t>(friendName.length());
uint32_t remSize = static_cast<uint32_t>(maxSize - size);
if (size > maxSize) size = maxSize;
for (uint32_t i = 0; i < size; ++i) {
bitStream.Write<uint16_t>(friendName[i]);
}
for (uint32_t j = 0; j < remSize; ++j) {
bitStream.Write<uint16_t>(0);
}
bitStream.Write<uint32_t>(0); //???
bitStream.Write<uint16_t>(0); //???
}
};
#endif //!__DCOMMONVARS__H__

View File

@@ -0,0 +1,29 @@
#pragma once
#if defined(_WIN32)
#define DARKFLAME_PLATFORM_WIN32
#elif defined(__APPLE__) && defined(__MACH__)
#include <TargetConditionals.h>
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
#define DARKFLAME_PLATFORM_IOS
#elif TARGET_OS_MAC
#define DARKFLAME_PLATFORM_MACOS
#else
#error unknown Apple operating system
#endif
#elif defined(__unix__)
#define DARKFLAME_PLATFORM_UNIX
#if defined(__ANDROID__)
#define DARKFLAME_PLATFORM_ANDROID
#elif defined(__linux__)
#define DARKFLAME_PLATFORM_LINUX
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#define DARKFLAME_PLATFORM_FREEBSD
#elif defined(__CYGWIN__)
#define DARKFLAME_PLATFORM_CYGWIN
#else
#error unknown unix operating system
#endif
#else
#error unknown operating system
#endif

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