Merge branch 'main' into cdclient-rework

This commit is contained in:
Wincent Holm 2022-10-29 21:52:08 +02:00
commit 633b87a5e7
963 changed files with 39754 additions and 41072 deletions

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

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

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

2
.gitattributes vendored
View File

@ -1 +1 @@
*.sh eol=lf * text=auto eol=lf

2
.gitignore vendored
View File

@ -120,3 +120,5 @@ thirdparty/zlib-1.2.11/
docker/__pycache__ docker/__pycache__
docker-compose.override.yml docker-compose.override.yml
!/tests/TestBitStreams/*.bin

View File

@ -42,6 +42,12 @@ set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT
# Echo the version # Echo the version
message(STATUS "Version: ${PROJECT_VERSION}") message(STATUS "Version: ${PROJECT_VERSION}")
# 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: # 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 misleading indentation as DL_LinkedList from RakNet has a weird indent.
@ -54,7 +60,7 @@ if(UNIX)
else() else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17 -O2 -Wuninitialized -D_GLIBCXX_USE_CXX11_ABI=0 -D_GLIBCXX_USE_CXX17_ABI=0 -static-libgcc -fPIC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17 -O2 -Wuninitialized -D_GLIBCXX_USE_CXX11_ABI=0 -D_GLIBCXX_USE_CXX17_ABI=0 -static-libgcc -fPIC")
endif() endif()
if (__dynamic) if (__dynamic AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -rdynamic") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -rdynamic")
endif() endif()
if (__ggdb) if (__ggdb)
@ -63,7 +69,7 @@ if(UNIX)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -O2 -fPIC") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -O2 -fPIC")
elseif(MSVC) elseif(MSVC)
# Skip warning for invalid conversion from size_t to uint32_t for all targets below for now # Skip warning for invalid conversion from size_t to uint32_t for all targets below for now
add_compile_options("/wd4267") add_compile_options("/wd4267" "/utf-8")
elseif(WIN32) elseif(WIN32)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS) add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
endif() endif()
@ -83,14 +89,15 @@ make_directory(${CMAKE_BINARY_DIR}/locale)
# Create a /logs directory # Create a /logs directory
make_directory(${CMAKE_BINARY_DIR}/logs) make_directory(${CMAKE_BINARY_DIR}/logs)
# Copy ini files on first build # Copy resource files on first build
set(INI_FILES "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini") set(RESOURCE_FILES "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini" "blacklist.dcf")
foreach(ini ${INI_FILES}) foreach(resource_file ${RESOURCE_FILES})
if (NOT EXISTS ${PROJECT_BINARY_DIR}/${ini}) if (NOT EXISTS ${PROJECT_BINARY_DIR}/${resource_file})
configure_file( configure_file(
${CMAKE_SOURCE_DIR}/resources/${ini} ${PROJECT_BINARY_DIR}/${ini} ${CMAKE_SOURCE_DIR}/resources/${resource_file} ${PROJECT_BINARY_DIR}/${resource_file}
COPYONLY COPYONLY
) )
message("Moved ${resource_file} to project binary directory")
endif() endif()
endforeach() endforeach()
@ -126,6 +133,8 @@ set(INCLUDED_DIRECTORIES
"dGame/dEntity" "dGame/dEntity"
"dGame/dUtilities" "dGame/dUtilities"
"dPhysics" "dPhysics"
"dNavigation"
"dNavigation/dTerrain"
"dZoneManager" "dZoneManager"
"dDatabase" "dDatabase"
"dDatabase/Tables" "dDatabase/Tables"
@ -134,8 +143,7 @@ set(INCLUDED_DIRECTORIES
"thirdparty/raknet/Source" "thirdparty/raknet/Source"
"thirdparty/tinyxml2" "thirdparty/tinyxml2"
"thirdparty/recastnavigation/Recast/Include" "thirdparty/recastnavigation"
"thirdparty/recastnavigation/Detour/Include"
"thirdparty/SQLite" "thirdparty/SQLite"
"thirdparty/cpplinq" "thirdparty/cpplinq"
) )
@ -152,7 +160,6 @@ elseif (UNIX)
set(INCLUDED_DIRECTORIES ${INCLUDED_DIRECTORIES} "thirdparty/libbcrypt/include/bcrypt") set(INCLUDED_DIRECTORIES ${INCLUDED_DIRECTORIES} "thirdparty/libbcrypt/include/bcrypt")
endif() endif()
include_directories(${ZLIB_INCLUDE_DIRS})
# Add binary directory as an include directory # Add binary directory as an include directory
include_directories(${PROJECT_BINARY_DIR}) include_directories(${PROJECT_BINARY_DIR})
@ -205,6 +212,7 @@ add_subdirectory(dNet)
add_subdirectory(dScripts) # Add for dGame to use add_subdirectory(dScripts) # Add for dGame to use
add_subdirectory(dGame) add_subdirectory(dGame)
add_subdirectory(dZoneManager) add_subdirectory(dZoneManager)
add_subdirectory(dNavigation)
add_subdirectory(dPhysics) add_subdirectory(dPhysics)
# Create a list of common libraries shared between all binaries # Create a list of common libraries shared between all binaries

View File

@ -118,6 +118,11 @@
"execution": { "execution": {
"jobs": 2 "jobs": 2
}, },
"filter": {
"exclude": {
"name": "((example)|(minigzip))+"
}
},
"output": { "output": {
"outputOnFailure": true "outputOnFailure": true
} }

View File

@ -1,6 +1,6 @@
PROJECT_VERSION_MAJOR=1 PROJECT_VERSION_MAJOR=1
PROJECT_VERSION_MINOR=0 PROJECT_VERSION_MINOR=0
PROJECT_VERSION_PATCH=3 PROJECT_VERSION_PATCH=4
# LICENSE # LICENSE
LICENSE=AGPL-3.0 LICENSE=AGPL-3.0
# The network version. # The network version.
@ -8,7 +8,7 @@ LICENSE=AGPL-3.0
# 171022 - Unmodded client # 171022 - Unmodded client
NET_VERSION=171022 NET_VERSION=171022
# Debugging # Debugging
# __dynamic=1 __dynamic=1
# Set __dynamic to 1 to enable the -rdynamic flag for the linker, yielding some symbols in crashlogs. # Set __dynamic to 1 to enable the -rdynamic flag for the linker, yielding some symbols in crashlogs.
# __ggdb=1 # __ggdb=1
# Set __ggdb to 1 to enable the -ggdb flag for the linker, including more debug info. # Set __ggdb to 1 to enable the -ggdb flag for the linker, including more debug info.

View File

@ -123,6 +123,15 @@ added, which produced InvalidScript errors.
Check out a compiled list of development resources and tools [here](https://lu-dev.net/). 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 ## 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. 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.

View File

@ -25,8 +25,7 @@
**NOTE #4**: Make sure to run the following in the repo root directory after cloning so submodules are also downloaded. **NOTE #4**: Make sure to run the following in the repo root directory after cloning so submodules are also downloaded.
``` ```
git submodule init git submodule update --init --recursive
git submodule update
``` ```
**NOTE #5**: If DarkflameSetup fails due to not having cdclient.fdb, rename CDClient.fdb (in the same folder) to cdclient.fdb **NOTE #5**: If DarkflameSetup fails due to not having cdclient.fdb, rename CDClient.fdb (in the same folder) to cdclient.fdb

View File

@ -27,11 +27,11 @@ Darkflame Universe is a server emulator and does not distribute any LEGO® Unive
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. 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.
### Prerequisites ### Prerequisites
**Clone the repository** #### Clone the repository
```bash ```bash
git clone --recursive https://github.com/DarkflameUniverse/DarkflameServer git clone --recursive https://github.com/DarkflameUniverse/DarkflameServer
``` ```
**Python** #### Python
Some tools utilized to streamline the setup process require Python 3, make sure you have it installed. Some tools utilized to streamline the setup process require Python 3, make sure you have it installed.
@ -42,12 +42,17 @@ This was done make sure that older and incomplete clients wouldn't produce false
If you're using a DLU client you'll have to go into the "CMakeVariables.txt" file and change the NET_VERSION variable to 171023 to match the modified client's version number. If you're using a DLU client you'll have to go into the "CMakeVariables.txt" file and change the NET_VERSION variable to 171023 to match the modified client's version number.
### Using Docker
Refer to [Docker.md](/Docker.md).
For Windows, refer to [Docker_Windows.md](/Docker_Windows.md).
### Linux builds ### Linux builds
Make sure packages like `gcc`, `cmake`, 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`. Make sure packages like `gcc`, `cmake`, 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`.
CMake must be version 3.14 or higher! CMake must be version 3.14 or higher!
**Build the repository** #### Build the repository
You can either run `build.sh` when in the root folder of the repository: You can either run `build.sh` when in the root folder of the repository:
@ -65,8 +70,8 @@ cd build
# Run CMake to generate make files # Run CMake to generate make files
cmake .. 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` # To build utilizing multiple cores, append `-j` and the amount of cores to utilize, for example `cmake --build . --config Release -j8'
make cmake --build . --config Release
``` ```
### MacOS builds ### MacOS builds
@ -88,7 +93,7 @@ cmake --build . --config Release
### Windows builds (native) ### 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/). Currently on native Windows the server will only work in Release mode. 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/). Currently on native Windows the server will only work in Release mode.
**Build the repository** #### Build the repository
```batch ```batch
:: Create the build directory :: Create the build directory
mkdir build mkdir build
@ -100,7 +105,7 @@ cmake ..
:: Run CMake with build flag to build :: Run CMake with build flag to build
cmake --build . --config Release cmake --build . --config Release
``` ```
**Windows for ARM** has not been tested but should build by doing the following #### Windows for ARM has not been tested but should build by doing the following
```batch ```batch
:: Create the build directory :: Create the build directory
mkdir build mkdir build
@ -116,13 +121,13 @@ cmake --build . --config Release
### Windows builds (WSL) ### 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. 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:** #### Open the Command Prompt application with Administrator permissions and run the following:
```bash ```bash
# Installing Windows Subsystem for Linux # Installing Windows Subsystem for Linux
wsl --install wsl --install
``` ```
**Open the Ubuntu application and run the following:** #### Open the Ubuntu application and run the following:
```bash ```bash
# Make sure the install is up to date # Make sure the install is up to date
apt update && apt upgrade apt update && apt upgrade
@ -154,7 +159,7 @@ now follow the build section for your system
### Resources ### Resources
**LEGO® Universe 1.10.64** #### 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. 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.
@ -177,20 +182,20 @@ shasum -a 256 <file>
certutil -hashfile <file> SHA256 certutil -hashfile <file> SHA256
``` ```
**Unpacking the client** #### Unpacking the client
* Clone lcdr's utilities repository [here](https://github.com/lcdr/utils) * 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 * Use `pkextractor.pyw` to unpack the client files if they are not already unpacked
**Setup resource directory** #### Setup resource directory
* In the `build` directory create a `res` directory if it does not already exist. * 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`, `names`, and `maps` in your client `res` directory to the server `build/res` directory * Copy over or create symlinks from `macros`, `BrickModels`, `chatplus_en_us.txt`, `names`, 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` * Unzip the navmeshes [here](./resources/navmeshes.zip) and place them in `build/res/maps/navmeshes`
**Setup locale** #### Setup locale
* In the `build` directory create a `locale` directory if it does not already exist * 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 * Copy over or create symlinks from `locale.xml` in your client `locale` directory to the `build/locale` directory
**Client database** #### 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` * 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` * 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 * Run each SQL file in the order at which they appear [here](migrations/cdserver/) on the SQLite database
@ -199,14 +204,18 @@ certutil -hashfile <file> SHA256
Darkflame Universe utilizes a MySQL/MariaDB database for account and character information. 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. 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
* Use the command `./MasterServer -m` to automatically run them.
**Configuration** * All that you need to do is create a database to connect to. As long as the server can connect to the database, the schema will always be kept up to date when you start the server.
#### Configuration
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. 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.
**Verify** #### Migrations
The database is automatically setup and migrated to what it should look like for the latest commit whenever you start the server.
#### Verify
Your build directory should now look like this: Your build directory should now look like this:
* AuthServer * AuthServer
@ -417,10 +426,11 @@ Here is a summary of the commands available in-game. All commands are prefixed b
</tbody> </tbody>
</table> </table>
## Credits # Credits
## Active Contributors ## Active Contributors
* [EmosewaMC](https://github.com/EmosewaMC) * [EmosewaMC](https://github.com/EmosewaMC)
* [Jettford](https://github.com/Jettford) * [Jettford](https://github.com/Jettford)
* [Aaron K.](https://github.com/aronwk-aaron)
## DLU Team ## DLU Team
* [DarwinAnim8or](https://github.com/DarwinAnim8or) * [DarwinAnim8or](https://github.com/DarwinAnim8or)
@ -429,10 +439,6 @@ Here is a summary of the commands available in-game. All commands are prefixed b
* [averysumner](https://github.com/codeshaunted) * [averysumner](https://github.com/codeshaunted)
* [Jon002](https://github.com/jaller200) * [Jon002](https://github.com/jaller200)
* [Jonny](https://github.com/cuzitsjonny) * [Jonny](https://github.com/cuzitsjonny)
* TheMachine
* Matthew
* [Raine](https://github.com/Rainebannister)
* Bricknave
### Research and tools ### Research and tools
* [lcdr](https://github.com/lcdr) * [lcdr](https://github.com/lcdr)
@ -444,11 +450,14 @@ Here is a summary of the commands available in-game. All commands are prefixed b
### Former contributors ### Former contributors
* TheMachine * TheMachine
* Matthew * Matthew
* Raine * [Raine](https://github.com/Rainebannister)
* Bricknave * Bricknave
### Special thanks ### Logo
* Cole Peterson (BlasterBuilder)
## Special thanks
* humanoid24 * humanoid24
* pwjones1969 * pwjones1969
* BlasterBuilder for the logo * [Simon](https://github.com/SimonNitzsche)
* ALL OF THE NETDEVIL AND LEGO TEAMS! * ALL OF THE NETDEVIL AND LEGO TEAMS!

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

View File

@ -5,5 +5,6 @@ cd build
# Run cmake to generate make files # Run cmake to generate make files
cmake .. 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` # To build utilizing multiple cores, append `-j` and the amount of cores to utilize, for example `cmake --build . --config Release -j8'
make cmake --build . --config Release

View File

@ -37,9 +37,9 @@ int main(int argc, char** argv) {
//Create all the objects we need to run our service: //Create all the objects we need to run our service:
Game::logger = SetupLogger(); Game::logger = SetupLogger();
if (!Game::logger) return 0; if (!Game::logger) return 0;
Game::logger->Log("AuthServer", "Starting Auth server...\n"); Game::logger->Log("AuthServer", "Starting Auth server...");
Game::logger->Log("AuthServer", "Version: %i.%i\n", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR); Game::logger->Log("AuthServer", "Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
Game::logger->Log("AuthServer", "Compiled on: %s\n", __TIMESTAMP__); Game::logger->Log("AuthServer", "Compiled on: %s", __TIMESTAMP__);
//Read our config: //Read our config:
dConfig config("authconfig.ini"); dConfig config("authconfig.ini");
@ -56,7 +56,7 @@ int main(int argc, char** argv) {
try { try {
Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password); Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password);
} catch (sql::SQLException& ex) { } catch (sql::SQLException& ex) {
Game::logger->Log("AuthServer", "Got an error while connecting to the database: %s\n", ex.what()); Game::logger->Log("AuthServer", "Got an error while connecting to the database: %s", ex.what());
Database::Destroy("AuthServer"); Database::Destroy("AuthServer");
delete Game::server; delete Game::server;
delete Game::logger; delete Game::logger;
@ -98,8 +98,7 @@ int main(int argc, char** argv) {
if (framesSinceMasterDisconnect >= 30) if (framesSinceMasterDisconnect >= 30)
break; //Exit our loop, shut down. break; //Exit our loop, shut down.
} } else framesSinceMasterDisconnect = 0;
else framesSinceMasterDisconnect = 0;
//In world we'd update our other systems here. //In world we'd update our other systems here.
@ -134,8 +133,7 @@ int main(int argc, char** argv) {
delete stmt; delete stmt;
framesSinceLastSQLPing = 0; framesSinceLastSQLPing = 0;
} } else framesSinceLastSQLPing++;
else framesSinceLastSQLPing++;
//Sleep our thread since auth can afford to. //Sleep our thread since auth can afford to.
t += std::chrono::milliseconds(mediumFramerate); //Auth can run at a lower "fps" t += std::chrono::milliseconds(mediumFramerate); //Auth can run at a lower "fps"

View File

@ -8,8 +8,9 @@
#include <regex> #include <regex>
#include "dCommonVars.h" #include "dCommonVars.h"
#include "Database.h"
#include "dLogger.h" #include "dLogger.h"
#include "dConfig.h"
#include "Database.h"
#include "Game.h" #include "Game.h"
using namespace dChatFilterDCF; using namespace dChatFilterDCF;
@ -18,12 +19,15 @@ dChatFilter::dChatFilter(const std::string& filepath, bool dontGenerateDCF) {
m_DontGenerateDCF = dontGenerateDCF; m_DontGenerateDCF = dontGenerateDCF;
if (!BinaryIO::DoesFileExist(filepath + ".dcf") || m_DontGenerateDCF) { if (!BinaryIO::DoesFileExist(filepath + ".dcf") || m_DontGenerateDCF) {
ReadWordlistPlaintext(filepath + ".txt"); ReadWordlistPlaintext(filepath + ".txt", true);
if (!m_DontGenerateDCF) ExportWordlistToDCF(filepath + ".dcf"); if (!m_DontGenerateDCF) ExportWordlistToDCF(filepath + ".dcf", true);
} else if (!ReadWordlistDCF(filepath + ".dcf", true)) {
ReadWordlistPlaintext(filepath + ".txt", true);
ExportWordlistToDCF(filepath + ".dcf", true);
} }
else if (!ReadWordlistDCF(filepath + ".dcf")) {
ReadWordlistPlaintext(filepath + ".txt"); if (BinaryIO::DoesFileExist("blacklist.dcf")) {
ExportWordlistToDCF(filepath + ".dcf"); ReadWordlistDCF("blacklist.dcf", false);
} }
//Read player names that are ok as well: //Read player names that are ok as well:
@ -32,29 +36,31 @@ dChatFilter::dChatFilter(const std::string& filepath, bool dontGenerateDCF) {
while (res->next()) { while (res->next()) {
std::string line = res->getString(1).c_str(); std::string line = res->getString(1).c_str();
std::transform(line.begin(), line.end(), line.begin(), ::tolower); //Transform to lowercase std::transform(line.begin(), line.end(), line.begin(), ::tolower); //Transform to lowercase
m_Words.push_back(CalculateHash(line)); m_ApprovedWords.push_back(CalculateHash(line));
} }
delete res; delete res;
delete stmt; delete stmt;
} }
dChatFilter::~dChatFilter() { 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); std::ifstream file(filepath);
if (file) { if (file) {
std::string line; std::string line;
while (std::getline(file, line)) { while (std::getline(file, line)) {
line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
std::transform(line.begin(), line.end(), line.begin(), ::tolower); //Transform to lowercase 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));
} }
} }
} }
bool dChatFilter::ReadWordlistDCF(const std::string& filepath) { bool dChatFilter::ReadWordlistDCF(const std::string& filepath, bool whiteList) {
std::ifstream file(filepath, std::ios::binary); std::ifstream file(filepath, std::ios::binary);
if (file) { if (file) {
fileHeader hdr; fileHeader hdr;
@ -67,17 +73,18 @@ bool dChatFilter::ReadWordlistDCF(const std::string& filepath) {
if (hdr.formatVersion == formatVersion) { if (hdr.formatVersion == formatVersion) {
size_t wordsToRead = 0; size_t wordsToRead = 0;
BinaryIO::BinaryRead(file, wordsToRead); BinaryIO::BinaryRead(file, wordsToRead);
m_Words.reserve(wordsToRead); if (whiteList) m_ApprovedWords.reserve(wordsToRead);
else m_DeniedWords.reserve(wordsToRead);
size_t word = 0; size_t word = 0;
for (size_t i = 0; i < wordsToRead; ++i) { for (size_t i = 0; i < wordsToRead; ++i) {
BinaryIO::BinaryRead(file, word); BinaryIO::BinaryRead(file, word);
m_Words.push_back(word); if (whiteList) m_ApprovedWords.push_back(word);
else m_DeniedWords.push_back(word);
} }
return true; return true;
} } else {
else {
file.close(); file.close();
return false; return false;
} }
@ -86,14 +93,14 @@ bool dChatFilter::ReadWordlistDCF(const std::string& filepath) {
return false; return false;
} }
void dChatFilter::ExportWordlistToDCF(const std::string& filepath) { void dChatFilter::ExportWordlistToDCF(const std::string& filepath, bool whiteList) {
std::ofstream file(filepath, std::ios::binary | std::ios_base::out); std::ofstream file(filepath, std::ios::binary | std::ios_base::out);
if (file) { if (file) {
BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::header)); BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::header));
BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::formatVersion)); 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); BinaryIO::BinaryWrite(file, word);
} }
@ -101,31 +108,45 @@ void dChatFilter::ExportWordlistToDCF(const std::string& filepath) {
} }
} }
bool dChatFilter::IsSentenceOkay(const std::string& message, int gmLevel) { std::vector<std::pair<uint8_t, uint8_t>> dChatFilter::IsSentenceOkay(const std::string& message, int gmLevel, bool whiteList) {
if (gmLevel > GAME_MASTER_LEVEL_FORUM_MODERATOR) return true; //If anything but a forum mod, return true. if (gmLevel > GAME_MASTER_LEVEL_FORUM_MODERATOR) return { }; //If anything but a forum mod, return true.
if (message.empty()) return true; if (message.empty()) return { };
if (!whiteList && m_DeniedWords.empty()) return { { 0, message.length() } };
std::stringstream sMessage(message); std::stringstream sMessage(message);
std::string segment; std::string segment;
std::regex reg("(!*|\\?*|\\;*|\\.*|\\,*)"); 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, ' ')) { while (std::getline(sMessage, segment, ' ')) {
std::string originalSegment = segment;
std::transform(segment.begin(), segment.end(), segment.begin(), ::tolower); //Transform to lowercase std::transform(segment.begin(), segment.end(), segment.begin(), ::tolower); //Transform to lowercase
segment = std::regex_replace(segment, reg, ""); segment = std::regex_replace(segment, reg, "");
size_t hash = CalculateHash(segment); size_t hash = CalculateHash(segment);
if (std::find(m_UserUnapprovedWordCache.begin(), m_UserUnapprovedWordCache.end(), hash) != m_UserUnapprovedWordCache.end()) { if (std::find(m_UserUnapprovedWordCache.begin(), m_UserUnapprovedWordCache.end(), hash) != m_UserUnapprovedWordCache.end() && whiteList) {
return false; 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); m_UserUnapprovedWordCache.push_back(hash);
return false; listOfBadSegments.emplace_back(position, originalSegment.length());
}
} }
return true; 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 += segment.length() + 1;
}
return listOfBadSegments;
} }
size_t dChatFilter::CalculateHash(const std::string& word) { size_t dChatFilter::CalculateHash(const std::string& word) {
@ -135,7 +156,3 @@ size_t dChatFilter::CalculateHash(const std::string& word) {
return value; return value;
} }
bool dChatFilter::IsInWordlist(size_t word) {
return std::find(m_Words.begin(), m_Words.end(), word) != m_Words.end();
}

View File

@ -20,17 +20,17 @@ public:
dChatFilter(const std::string& filepath, bool dontGenerateDCF); dChatFilter(const std::string& filepath, bool dontGenerateDCF);
~dChatFilter(); ~dChatFilter();
void ReadWordlistPlaintext(const std::string & filepath); void ReadWordlistPlaintext(const std::string& filepath, bool whiteList);
bool ReadWordlistDCF(const std::string & filepath); bool ReadWordlistDCF(const std::string& filepath, bool whiteList);
void ExportWordlistToDCF(const std::string & filepath); void ExportWordlistToDCF(const std::string& filepath, bool whiteList);
bool IsSentenceOkay(const std::string& message, int gmLevel); std::vector<std::pair<uint8_t, uint8_t>> IsSentenceOkay(const std::string& message, int gmLevel, bool whiteList = true);
private: private:
bool m_DontGenerateDCF; 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; std::vector<size_t> m_UserUnapprovedWordCache;
//Private functions: //Private functions:
size_t CalculateHash(const std::string& word); size_t CalculateHash(const std::string& word);
bool IsInWordlist(size_t word);
}; };

View File

@ -33,9 +33,10 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
"WHEN friend_id = ? THEN player_id " "WHEN friend_id = ? THEN player_id "
"END AS requested_player, best_friend FROM friends) AS fr " "END AS requested_player, best_friend FROM friends) AS fr "
"JOIN charinfo AS ci ON ci.id = fr.requested_player " "JOIN charinfo AS ci ON ci.id = fr.requested_player "
"WHERE fr.requested_player IS NOT NULL;")); "WHERE fr.requested_player IS NOT NULL AND fr.requested_player != ?;"));
stmt->setUInt(1, static_cast<uint32_t>(playerID)); stmt->setUInt(1, static_cast<uint32_t>(playerID));
stmt->setUInt(2, static_cast<uint32_t>(playerID)); stmt->setUInt(2, static_cast<uint32_t>(playerID));
stmt->setUInt(3, static_cast<uint32_t>(playerID));
std::vector<FriendData> friends; std::vector<FriendData> friends;
@ -60,8 +61,7 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
//Since this friend is online, we need to update them on the fact that we've just logged in: //Since this friend is online, we need to update them on the fact that we've just logged in:
SendFriendUpdate(fr, player, 1, fd.isBestFriend); SendFriendUpdate(fr, player, 1, fd.isBestFriend);
} } else {
else {
fd.isOnline = false; fd.isOnline = false;
fd.zoneID = LWOZONEID(); fd.zoneID = LWOZONEID();
} }
@ -114,6 +114,10 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
inStream.Read(isBestFriendRequest); inStream.Read(isBestFriendRequest);
auto requestor = playerContainer.GetPlayerData(requestorPlayerID); auto requestor = playerContainer.GetPlayerData(requestorPlayerID);
if (requestor->playerName == playerName) {
SendFriendResponse(requestor, requestor, AddFriendResponseType::MYTHRAN);
return;
};
std::unique_ptr<PlayerData> requestee(playerContainer.GetPlayerData(playerName)); std::unique_ptr<PlayerData> requestee(playerContainer.GetPlayerData(playerName));
// Check if player is online first // Check if player is online first
@ -371,8 +375,7 @@ void ChatPacketHandler::HandleRemoveFriend(Packet* packet) {
SendRemoveFriend(goonB, goonAName, true); SendRemoveFriend(goonB, goonAName, true);
} }
void ChatPacketHandler::HandleChatMessage(Packet* packet) void ChatPacketHandler::HandleChatMessage(Packet* packet) {
{
CINSTREAM; CINSTREAM;
LWOOBJID playerID = LWOOBJID_EMPTY; LWOOBJID playerID = LWOOBJID_EMPTY;
inStream.Read(playerID); inStream.Read(playerID);
@ -393,7 +396,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet)
std::string message = PacketUtils::ReadString(0x66, packet, true); std::string message = PacketUtils::ReadString(0x66, packet, true);
Game::logger->Log("ChatPacketHandler", "Got a message from (%s) [%d]: %s\n", senderName.c_str(), channel, message.c_str()); Game::logger->Log("ChatPacketHandler", "Got a message from (%s) [%d]: %s", senderName.c_str(), channel, message.c_str());
if (channel != 8) return; if (channel != 8) return;
@ -401,8 +404,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet)
if (team == nullptr) return; if (team == nullptr) return;
for (const auto memberId : team->memberIDs) for (const auto memberId : team->memberIDs) {
{
auto* otherMember = playerContainer.GetPlayerData(memberId); auto* otherMember = playerContainer.GetPlayerData(memberId);
if (otherMember == nullptr) return; if (otherMember == nullptr) return;
@ -493,8 +495,7 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
} }
} }
void ChatPacketHandler::HandleTeamInvite(Packet* packet) void ChatPacketHandler::HandleTeamInvite(Packet* packet) {
{
CINSTREAM; CINSTREAM;
LWOOBJID playerID; LWOOBJID playerID;
inStream.Read(playerID); inStream.Read(playerID);
@ -503,44 +504,39 @@ void ChatPacketHandler::HandleTeamInvite(Packet* packet)
auto* player = playerContainer.GetPlayerData(playerID); auto* player = playerContainer.GetPlayerData(playerID);
if (player == nullptr) if (player == nullptr) {
{
return; return;
} }
auto* team = playerContainer.GetTeam(playerID); auto* team = playerContainer.GetTeam(playerID);
if (team == nullptr) if (team == nullptr) {
{
team = playerContainer.CreateTeam(playerID); team = playerContainer.CreateTeam(playerID);
} }
auto* other = playerContainer.GetPlayerData(invitedPlayer); auto* other = playerContainer.GetPlayerData(invitedPlayer);
if (other == nullptr) if (other == nullptr) {
{
return; return;
} }
if (playerContainer.GetTeam(other->playerID) != nullptr) if (playerContainer.GetTeam(other->playerID) != nullptr) {
{
return; return;
} }
if (team->memberIDs.size() > 3) { if (team->memberIDs.size() > 3) {
// no more teams greater than 4 // no more teams greater than 4
Game::logger->Log("ChatPacketHandler", "Someone tried to invite a 5th player to a team\n"); Game::logger->Log("ChatPacketHandler", "Someone tried to invite a 5th player to a team");
return; return;
} }
SendTeamInvite(other, player); SendTeamInvite(other, player);
Game::logger->Log("ChatPacketHandler", "Got team invite: %llu -> %s\n", playerID, invitedPlayer.c_str()); Game::logger->Log("ChatPacketHandler", "Got team invite: %llu -> %s", playerID, invitedPlayer.c_str());
} }
void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet) void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet) {
{
CINSTREAM; CINSTREAM;
LWOOBJID playerID = LWOOBJID_EMPTY; LWOOBJID playerID = LWOOBJID_EMPTY;
inStream.Read(playerID); inStream.Read(playerID);
@ -552,33 +548,29 @@ void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet)
LWOOBJID leaderID = LWOOBJID_EMPTY; LWOOBJID leaderID = LWOOBJID_EMPTY;
inStream.Read(leaderID); inStream.Read(leaderID);
Game::logger->Log("ChatPacketHandler", "Accepted invite: %llu -> %llu (%d)\n", playerID, leaderID, declined); Game::logger->Log("ChatPacketHandler", "Accepted invite: %llu -> %llu (%d)", playerID, leaderID, declined);
if (declined) if (declined) {
{
return; return;
} }
auto* team = playerContainer.GetTeam(leaderID); auto* team = playerContainer.GetTeam(leaderID);
if (team == nullptr) if (team == nullptr) {
{ Game::logger->Log("ChatPacketHandler", "Failed to find team for leader (%llu)", leaderID);
Game::logger->Log("ChatPacketHandler", "Failed to find team for leader (%llu)\n", leaderID);
team = playerContainer.GetTeam(playerID); team = playerContainer.GetTeam(playerID);
} }
if (team == nullptr) if (team == nullptr) {
{ Game::logger->Log("ChatPacketHandler", "Failed to find team for player (%llu)", playerID);
Game::logger->Log("ChatPacketHandler", "Failed to find team for player (%llu)\n", playerID);
return; return;
} }
playerContainer.AddMember(team, playerID); playerContainer.AddMember(team, playerID);
} }
void ChatPacketHandler::HandleTeamLeave(Packet* packet) void ChatPacketHandler::HandleTeamLeave(Packet* packet) {
{
CINSTREAM; CINSTREAM;
LWOOBJID playerID = LWOOBJID_EMPTY; LWOOBJID playerID = LWOOBJID_EMPTY;
inStream.Read(playerID); inStream.Read(playerID);
@ -588,16 +580,14 @@ void ChatPacketHandler::HandleTeamLeave(Packet* packet)
auto* team = playerContainer.GetTeam(playerID); auto* team = playerContainer.GetTeam(playerID);
Game::logger->Log("ChatPacketHandler", "(%llu) leaving team\n", playerID); Game::logger->Log("ChatPacketHandler", "(%llu) leaving team", playerID);
if (team != nullptr) if (team != nullptr) {
{
playerContainer.RemoveMember(team, playerID, false, false, true); playerContainer.RemoveMember(team, playerID, false, false, true);
} }
} }
void ChatPacketHandler::HandleTeamKick(Packet* packet) void ChatPacketHandler::HandleTeamKick(Packet* packet) {
{
CINSTREAM; CINSTREAM;
LWOOBJID playerID = LWOOBJID_EMPTY; LWOOBJID playerID = LWOOBJID_EMPTY;
inStream.Read(playerID); inStream.Read(playerID);
@ -605,35 +595,30 @@ void ChatPacketHandler::HandleTeamKick(Packet* packet)
std::string kickedPlayer = PacketUtils::ReadString(0x14, packet, true); std::string kickedPlayer = PacketUtils::ReadString(0x14, packet, true);
Game::logger->Log("ChatPacketHandler", "(%llu) kicking (%s) from team\n", playerID, kickedPlayer.c_str()); Game::logger->Log("ChatPacketHandler", "(%llu) kicking (%s) from team", playerID, kickedPlayer.c_str());
auto* kicked = playerContainer.GetPlayerData(kickedPlayer); auto* kicked = playerContainer.GetPlayerData(kickedPlayer);
LWOOBJID kickedId = LWOOBJID_EMPTY; LWOOBJID kickedId = LWOOBJID_EMPTY;
if (kicked != nullptr) if (kicked != nullptr) {
{
kickedId = kicked->playerID; kickedId = kicked->playerID;
} } else {
else kickedId = playerContainer.GetId(GeneralUtils::UTF8ToUTF16(kickedPlayer));
{
kickedId = playerContainer.GetId(GeneralUtils::ASCIIToUTF16(kickedPlayer));
} }
if (kickedId == LWOOBJID_EMPTY) return; if (kickedId == LWOOBJID_EMPTY) return;
auto* team = playerContainer.GetTeam(playerID); auto* team = playerContainer.GetTeam(playerID);
if (team != nullptr) if (team != nullptr) {
{
if (team->leaderID != playerID || team->leaderID == kickedId) return; if (team->leaderID != playerID || team->leaderID == kickedId) return;
playerContainer.RemoveMember(team, kickedId, false, true, false); playerContainer.RemoveMember(team, kickedId, false, true, false);
} }
} }
void ChatPacketHandler::HandleTeamPromote(Packet* packet) void ChatPacketHandler::HandleTeamPromote(Packet* packet) {
{
CINSTREAM; CINSTREAM;
LWOOBJID playerID = LWOOBJID_EMPTY; LWOOBJID playerID = LWOOBJID_EMPTY;
inStream.Read(playerID); inStream.Read(playerID);
@ -641,7 +626,7 @@ void ChatPacketHandler::HandleTeamPromote(Packet* packet)
std::string promotedPlayer = PacketUtils::ReadString(0x14, packet, true); std::string promotedPlayer = PacketUtils::ReadString(0x14, packet, true);
Game::logger->Log("ChatPacketHandler", "(%llu) promoting (%s) to team leader\n", playerID, promotedPlayer.c_str()); Game::logger->Log("ChatPacketHandler", "(%llu) promoting (%s) to team leader", playerID, promotedPlayer.c_str());
auto* promoted = playerContainer.GetPlayerData(promotedPlayer); auto* promoted = playerContainer.GetPlayerData(promotedPlayer);
@ -649,16 +634,14 @@ void ChatPacketHandler::HandleTeamPromote(Packet* packet)
auto* team = playerContainer.GetTeam(playerID); auto* team = playerContainer.GetTeam(playerID);
if (team != nullptr) if (team != nullptr) {
{
if (team->leaderID != playerID) return; if (team->leaderID != playerID) return;
playerContainer.PromoteMember(team, promoted->playerID); playerContainer.PromoteMember(team, promoted->playerID);
} }
} }
void ChatPacketHandler::HandleTeamLootOption(Packet* packet) void ChatPacketHandler::HandleTeamLootOption(Packet* packet) {
{
CINSTREAM; CINSTREAM;
LWOOBJID playerID = LWOOBJID_EMPTY; LWOOBJID playerID = LWOOBJID_EMPTY;
inStream.Read(playerID); inStream.Read(playerID);
@ -671,8 +654,7 @@ void ChatPacketHandler::HandleTeamLootOption(Packet* packet)
auto* team = playerContainer.GetTeam(playerID); auto* team = playerContainer.GetTeam(playerID);
if (team != nullptr) if (team != nullptr) {
{
if (team->leaderID != playerID) return; if (team->leaderID != playerID) return;
team->lootFlag = option; team->lootFlag = option;
@ -683,8 +665,7 @@ void ChatPacketHandler::HandleTeamLootOption(Packet* packet)
} }
} }
void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
{
CINSTREAM; CINSTREAM;
LWOOBJID playerID = LWOOBJID_EMPTY; LWOOBJID playerID = LWOOBJID_EMPTY;
inStream.Read(playerID); inStream.Read(playerID);
@ -693,45 +674,37 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet)
auto* team = playerContainer.GetTeam(playerID); auto* team = playerContainer.GetTeam(playerID);
auto* data = playerContainer.GetPlayerData(playerID); auto* data = playerContainer.GetPlayerData(playerID);
if (team != nullptr && data != nullptr) if (team != nullptr && data != nullptr) {
{ if (team->local && data->zoneID.GetMapID() != team->zoneId.GetMapID() && data->zoneID.GetCloneID() != team->zoneId.GetCloneID()) {
if (team->local && data->zoneID.GetMapID() != team->zoneId.GetMapID() && data->zoneID.GetCloneID() != team->zoneId.GetCloneID())
{
playerContainer.RemoveMember(team, playerID, false, false, true, true); playerContainer.RemoveMember(team, playerID, false, false, true, true);
return; return;
} }
if (team->memberIDs.size() <= 1 && !team->local) if (team->memberIDs.size() <= 1 && !team->local) {
{
playerContainer.DisbandTeam(team); playerContainer.DisbandTeam(team);
return; return;
} }
if (!team->local) if (!team->local) {
{
ChatPacketHandler::SendTeamSetLeader(data, team->leaderID); ChatPacketHandler::SendTeamSetLeader(data, team->leaderID);
} } else {
else
{
ChatPacketHandler::SendTeamSetLeader(data, LWOOBJID_EMPTY); ChatPacketHandler::SendTeamSetLeader(data, LWOOBJID_EMPTY);
} }
playerContainer.TeamStatusUpdate(team); playerContainer.TeamStatusUpdate(team);
const auto leaderName = GeneralUtils::ASCIIToUTF16(std::string(data->playerName.c_str())); const auto leaderName = GeneralUtils::UTF8ToUTF16(data->playerName);
for (const auto memberId : team->memberIDs) for (const auto memberId : team->memberIDs) {
{
auto* otherMember = playerContainer.GetPlayerData(memberId); auto* otherMember = playerContainer.GetPlayerData(memberId);
if (memberId == playerID) continue; if (memberId == playerID) continue;
const auto memberName = playerContainer.GetName(memberId); const auto memberName = playerContainer.GetName(memberId);
if (otherMember != nullptr) if (otherMember != nullptr) {
{
ChatPacketHandler::SendTeamSetOffWorldFlag(otherMember, data->playerID, data->zoneID); ChatPacketHandler::SendTeamSetOffWorldFlag(otherMember, data->playerID, data->zoneID);
} }
ChatPacketHandler::SendTeamAddPlayer(data, false, team->local, false, memberId, memberName, otherMember != nullptr ? otherMember->zoneID : LWOZONEID(0, 0, 0)); ChatPacketHandler::SendTeamAddPlayer(data, false, team->local, false, memberId, memberName, otherMember != nullptr ? otherMember->zoneID : LWOZONEID(0, 0, 0));
@ -741,8 +714,7 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet)
} }
} }
void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender) void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender) {
{
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER); PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver->playerID);
@ -757,14 +729,13 @@ void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender)
SEND_PACKET; SEND_PACKET;
} }
void ChatPacketHandler::SendTeamInviteConfirm(PlayerData* receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName) void ChatPacketHandler::SendTeamInviteConfirm(PlayerData* receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName) {
{
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER); PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver->playerID);
//portion that will get routed: //portion that will get routed:
CMSGHEADER CMSGHEADER;
bitStream.Write(receiver->playerID); bitStream.Write(receiver->playerID);
bitStream.Write(GAME_MSG::GAME_MSG_TEAM_INVITE_CONFIRM); bitStream.Write(GAME_MSG::GAME_MSG_TEAM_INVITE_CONFIRM);
@ -777,8 +748,7 @@ void ChatPacketHandler::SendTeamInviteConfirm(PlayerData* receiver, bool bLeader
bitStream.Write(ucNumOfOtherPlayers); bitStream.Write(ucNumOfOtherPlayers);
bitStream.Write(ucResponseCode); bitStream.Write(ucResponseCode);
bitStream.Write(static_cast<uint32_t>(wsLeaderName.size())); bitStream.Write(static_cast<uint32_t>(wsLeaderName.size()));
for (const auto character : wsLeaderName) for (const auto character : wsLeaderName) {
{
bitStream.Write(character); bitStream.Write(character);
} }
@ -786,14 +756,13 @@ void ChatPacketHandler::SendTeamInviteConfirm(PlayerData* receiver, bool bLeader
SEND_PACKET; SEND_PACKET;
} }
void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName) void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName) {
{
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER); PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver->playerID);
//portion that will get routed: //portion that will get routed:
CMSGHEADER CMSGHEADER;
bitStream.Write(receiver->playerID); bitStream.Write(receiver->playerID);
bitStream.Write(GAME_MSG::GAME_MSG_TEAM_GET_STATUS_RESPONSE); bitStream.Write(GAME_MSG::GAME_MSG_TEAM_GET_STATUS_RESPONSE);
@ -804,8 +773,7 @@ void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderI
bitStream.Write(ucLootFlag); bitStream.Write(ucLootFlag);
bitStream.Write(ucNumOfOtherPlayers); bitStream.Write(ucNumOfOtherPlayers);
bitStream.Write(static_cast<uint32_t>(wsLeaderName.size())); bitStream.Write(static_cast<uint32_t>(wsLeaderName.size()));
for (const auto character : wsLeaderName) for (const auto character : wsLeaderName) {
{
bitStream.Write(character); bitStream.Write(character);
} }
@ -813,14 +781,13 @@ void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderI
SEND_PACKET; SEND_PACKET;
} }
void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64PlayerID) void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64PlayerID) {
{
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER); PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver->playerID);
//portion that will get routed: //portion that will get routed:
CMSGHEADER CMSGHEADER;
bitStream.Write(receiver->playerID); bitStream.Write(receiver->playerID);
bitStream.Write(GAME_MSG::GAME_MSG_TEAM_SET_LEADER); bitStream.Write(GAME_MSG::GAME_MSG_TEAM_SET_LEADER);
@ -831,14 +798,13 @@ void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64Play
SEND_PACKET; SEND_PACKET;
} }
void ChatPacketHandler::SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID) void ChatPacketHandler::SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID) {
{
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER); PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver->playerID);
//portion that will get routed: //portion that will get routed:
CMSGHEADER CMSGHEADER;
bitStream.Write(receiver->playerID); bitStream.Write(receiver->playerID);
bitStream.Write(GAME_MSG::GAME_MSG_TEAM_ADD_PLAYER); bitStream.Write(GAME_MSG::GAME_MSG_TEAM_ADD_PLAYER);
@ -848,13 +814,11 @@ void ChatPacketHandler::SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTria
bitStream.Write(bNoLootOnDeath); bitStream.Write(bNoLootOnDeath);
bitStream.Write(i64PlayerID); bitStream.Write(i64PlayerID);
bitStream.Write(static_cast<uint32_t>(wsPlayerName.size())); bitStream.Write(static_cast<uint32_t>(wsPlayerName.size()));
for (const auto character : wsPlayerName) for (const auto character : wsPlayerName) {
{
bitStream.Write(character); bitStream.Write(character);
} }
bitStream.Write1(); bitStream.Write1();
if (receiver->zoneID.GetCloneID() == zoneID.GetCloneID()) if (receiver->zoneID.GetCloneID() == zoneID.GetCloneID()) {
{
zoneID = LWOZONEID(zoneID.GetMapID(), zoneID.GetInstanceID(), 0); zoneID = LWOZONEID(zoneID.GetMapID(), zoneID.GetInstanceID(), 0);
} }
bitStream.Write(zoneID); bitStream.Write(zoneID);
@ -863,14 +827,13 @@ void ChatPacketHandler::SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTria
SEND_PACKET; SEND_PACKET;
} }
void ChatPacketHandler::SendTeamRemovePlayer(PlayerData* receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName) void ChatPacketHandler::SendTeamRemovePlayer(PlayerData* receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName) {
{
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER); PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver->playerID);
//portion that will get routed: //portion that will get routed:
CMSGHEADER CMSGHEADER;
bitStream.Write(receiver->playerID); bitStream.Write(receiver->playerID);
bitStream.Write(GAME_MSG::GAME_MSG_TEAM_REMOVE_PLAYER); bitStream.Write(GAME_MSG::GAME_MSG_TEAM_REMOVE_PLAYER);
@ -882,8 +845,7 @@ void ChatPacketHandler::SendTeamRemovePlayer(PlayerData* receiver, bool bDisband
bitStream.Write(i64LeaderID); bitStream.Write(i64LeaderID);
bitStream.Write(i64PlayerID); bitStream.Write(i64PlayerID);
bitStream.Write(static_cast<uint32_t>(wsPlayerName.size())); bitStream.Write(static_cast<uint32_t>(wsPlayerName.size()));
for (const auto character : wsPlayerName) for (const auto character : wsPlayerName) {
{
bitStream.Write(character); bitStream.Write(character);
} }
@ -891,21 +853,19 @@ void ChatPacketHandler::SendTeamRemovePlayer(PlayerData* receiver, bool bDisband
SEND_PACKET; SEND_PACKET;
} }
void ChatPacketHandler::SendTeamSetOffWorldFlag(PlayerData* receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID) void ChatPacketHandler::SendTeamSetOffWorldFlag(PlayerData* receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID) {
{
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER); PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver->playerID);
//portion that will get routed: //portion that will get routed:
CMSGHEADER CMSGHEADER;
bitStream.Write(receiver->playerID); bitStream.Write(receiver->playerID);
bitStream.Write(GAME_MSG::GAME_MSG_TEAM_SET_OFF_WORLD_FLAG); bitStream.Write(GAME_MSG::GAME_MSG_TEAM_SET_OFF_WORLD_FLAG);
bitStream.Write(i64PlayerID); bitStream.Write(i64PlayerID);
if (receiver->zoneID.GetCloneID() == zoneID.GetCloneID()) if (receiver->zoneID.GetCloneID() == zoneID.GetCloneID()) {
{
zoneID = LWOZONEID(zoneID.GetMapID(), zoneID.GetInstanceID(), 0); zoneID = LWOZONEID(zoneID.GetMapID(), zoneID.GetInstanceID(), 0);
} }
bitStream.Write(zoneID); bitStream.Write(zoneID);
@ -943,12 +903,9 @@ void ChatPacketHandler::SendFriendUpdate(PlayerData* friendData, PlayerData* pla
bitStream.Write(playerData->zoneID.GetMapID()); bitStream.Write(playerData->zoneID.GetMapID());
bitStream.Write(playerData->zoneID.GetInstanceID()); bitStream.Write(playerData->zoneID.GetInstanceID());
if (playerData->zoneID.GetCloneID() == friendData->zoneID.GetCloneID()) if (playerData->zoneID.GetCloneID() == friendData->zoneID.GetCloneID()) {
{
bitStream.Write(0); bitStream.Write(0);
} } else {
else
{
bitStream.Write(playerData->zoneID.GetCloneID()); bitStream.Write(playerData->zoneID.GetCloneID());
} }

View File

@ -40,9 +40,9 @@ int main(int argc, char** argv) {
//Create all the objects we need to run our service: //Create all the objects we need to run our service:
Game::logger = SetupLogger(); Game::logger = SetupLogger();
if (!Game::logger) return 0; if (!Game::logger) return 0;
Game::logger->Log("ChatServer", "Starting Chat server...\n"); Game::logger->Log("ChatServer", "Starting Chat server...");
Game::logger->Log("ChatServer", "Version: %i.%i\n", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR); Game::logger->Log("ChatServer", "Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
Game::logger->Log("ChatServer", "Compiled on: %s\n", __TIMESTAMP__); Game::logger->Log("ChatServer", "Compiled on: %s", __TIMESTAMP__);
//Read our config: //Read our config:
dConfig config("chatconfig.ini"); dConfig config("chatconfig.ini");
@ -58,9 +58,8 @@ int main(int argc, char** argv) {
try { try {
Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password); Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password);
} } catch (sql::SQLException& ex) {
catch (sql::SQLException& ex) { Game::logger->Log("ChatServer", "Got an error while connecting to the database: %s", ex.what());
Game::logger->Log("ChatServer", "Got an error while connecting to the database: %s\n", ex.what());
Database::Destroy("ChatServer"); Database::Destroy("ChatServer");
delete Game::server; delete Game::server;
delete Game::logger; delete Game::logger;
@ -104,8 +103,7 @@ int main(int argc, char** argv) {
if (framesSinceMasterDisconnect >= 30) if (framesSinceMasterDisconnect >= 30)
break; //Exit our loop, shut down. break; //Exit our loop, shut down.
} } else framesSinceMasterDisconnect = 0;
else framesSinceMasterDisconnect = 0;
//In world we'd update our other systems here. //In world we'd update our other systems here.
@ -122,8 +120,7 @@ int main(int argc, char** argv) {
if (framesSinceLastFlush >= 900) { if (framesSinceLastFlush >= 900) {
Game::logger->Flush(); Game::logger->Flush();
framesSinceLastFlush = 0; framesSinceLastFlush = 0;
} } else framesSinceLastFlush++;
else framesSinceLastFlush++;
//Every 10 min we ping our sql server to keep it alive hopefully: //Every 10 min we ping our sql server to keep it alive hopefully:
if (framesSinceLastSQLPing >= 40000) { if (framesSinceLastSQLPing >= 40000) {
@ -141,8 +138,7 @@ int main(int argc, char** argv) {
delete stmt; delete stmt;
framesSinceLastSQLPing = 0; framesSinceLastSQLPing = 0;
} } else framesSinceLastSQLPing++;
else framesSinceLastSQLPing++;
//Sleep our thread since auth can afford to. //Sleep our thread since auth can afford to.
t += std::chrono::milliseconds(mediumFramerate); //Chat can run at a lower "fps" t += std::chrono::milliseconds(mediumFramerate); //Chat can run at a lower "fps"
@ -172,11 +168,11 @@ dLogger * SetupLogger() {
void HandlePacket(Packet* packet) { void HandlePacket(Packet* packet) {
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) { if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
Game::logger->Log("ChatServer", "A server has disconnected, erasing their connected players from the list.\n"); Game::logger->Log("ChatServer", "A server has disconnected, erasing their connected players from the list.");
} }
if (packet->data[0] == ID_NEW_INCOMING_CONNECTION) { if (packet->data[0] == ID_NEW_INCOMING_CONNECTION) {
Game::logger->Log("ChatServer", "A server is connecting, awaiting user list.\n"); Game::logger->Log("ChatServer", "A server is connecting, awaiting user list.");
} }
if (packet->data[1] == CHAT_INTERNAL) { if (packet->data[1] == CHAT_INTERNAL) {
@ -205,7 +201,7 @@ void HandlePacket(Packet* packet) {
} }
default: default:
Game::logger->Log("ChatServer", "Unknown CHAT_INTERNAL id: %i\n", int(packet->data[3])); Game::logger->Log("ChatServer", "Unknown CHAT_INTERNAL id: %i", int(packet->data[3]));
} }
} }
@ -216,7 +212,7 @@ void HandlePacket(Packet* packet) {
break; break;
case MSG_CHAT_GET_IGNORE_LIST: case MSG_CHAT_GET_IGNORE_LIST:
Game::logger->Log("ChatServer", "Asked for ignore list, but is unimplemented right now.\n"); Game::logger->Log("ChatServer", "Asked for ignore list, but is unimplemented right now.");
break; break;
case MSG_CHAT_TEAM_GET_STATUS: case MSG_CHAT_TEAM_GET_STATUS:
@ -274,19 +270,19 @@ void HandlePacket(Packet* packet) {
break; break;
default: default:
Game::logger->Log("ChatServer", "Unknown CHAT id: %i\n", int(packet->data[3])); Game::logger->Log("ChatServer", "Unknown CHAT id: %i", int(packet->data[3]));
} }
} }
if (packet->data[1] == WORLD) { if (packet->data[1] == WORLD) {
switch (packet->data[3]) { switch (packet->data[3]) {
case MSG_WORLD_CLIENT_ROUTE_PACKET: { case MSG_WORLD_CLIENT_ROUTE_PACKET: {
printf("routing packet from world\n"); Game::logger->Log("ChatServer", "Routing packet from world");
break; break;
} }
default: default:
Game::logger->Log("ChatServer", "Unknown World id: %i\n", int(packet->data[3])); Game::logger->Log("ChatServer", "Unknown World id: %i", int(packet->data[3]));
} }
} }
} }

View File

@ -35,10 +35,10 @@ void PlayerContainer::InsertPlayer(Packet* packet) {
inStream.Read(data->muteExpire); inStream.Read(data->muteExpire);
data->sysAddr = packet->systemAddress; data->sysAddr = packet->systemAddress;
mNames[data->playerID] = GeneralUtils::ASCIIToUTF16(std::string(data->playerName.c_str())); mNames[data->playerID] = GeneralUtils::UTF8ToUTF16(data->playerName);
mPlayers.insert(std::make_pair(data->playerID, data)); mPlayers.insert(std::make_pair(data->playerID, data));
Game::logger->Log("PlayerContainer", "Added user: %s (%llu), zone: %i\n", data->playerName.c_str(), data->playerID, data->zoneID.GetMapID()); Game::logger->Log("PlayerContainer", "Added user: %s (%llu), zone: %i", data->playerName.c_str(), data->playerID, data->zoneID.GetMapID());
auto* insertLog = Database::CreatePreppedStmt("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);"); auto* insertLog = Database::CreatePreppedStmt("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);");
@ -70,12 +70,10 @@ void PlayerContainer::RemovePlayer(Packet* packet) {
auto* team = GetTeam(playerID); auto* team = GetTeam(playerID);
if (team != nullptr) if (team != nullptr) {
{ const auto memberName = GeneralUtils::UTF8ToUTF16(std::string(player->playerName.c_str()));
const auto memberName = GeneralUtils::ASCIIToUTF16(std::string(player->playerName.c_str()));
for (const auto memberId : team->memberIDs) for (const auto memberId : team->memberIDs) {
{
auto* otherMember = GetPlayerData(memberId); auto* otherMember = GetPlayerData(memberId);
if (otherMember == nullptr) continue; if (otherMember == nullptr) continue;
@ -84,7 +82,7 @@ void PlayerContainer::RemovePlayer(Packet* packet) {
} }
} }
Game::logger->Log("PlayerContainer", "Removed user: %llu\n", playerID); Game::logger->Log("PlayerContainer", "Removed user: %llu", playerID);
mPlayers.erase(playerID); mPlayers.erase(playerID);
auto* insertLog = Database::CreatePreppedStmt("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);"); auto* insertLog = Database::CreatePreppedStmt("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);");
@ -97,8 +95,7 @@ void PlayerContainer::RemovePlayer(Packet* packet) {
insertLog->executeUpdate(); insertLog->executeUpdate();
} }
void PlayerContainer::MuteUpdate(Packet* packet) void PlayerContainer::MuteUpdate(Packet* packet) {
{
CINSTREAM; CINSTREAM;
LWOOBJID playerID; LWOOBJID playerID;
inStream.Read(playerID); //skip header inStream.Read(playerID); //skip header
@ -108,9 +105,8 @@ void PlayerContainer::MuteUpdate(Packet* packet)
auto* player = this->GetPlayerData(playerID); auto* player = this->GetPlayerData(playerID);
if (player == nullptr) if (player == nullptr) {
{ Game::logger->Log("PlayerContainer", "Failed to find user: %llu", playerID);
Game::logger->Log("PlayerContainer", "Failed to find user: %llu\n", playerID);
return; return;
} }
@ -120,8 +116,7 @@ void PlayerContainer::MuteUpdate(Packet* packet)
BroadcastMuteUpdate(playerID, expire); BroadcastMuteUpdate(playerID, expire);
} }
void PlayerContainer::CreateTeamServer(Packet* packet) void PlayerContainer::CreateTeamServer(Packet* packet) {
{
CINSTREAM; CINSTREAM;
LWOOBJID playerID; LWOOBJID playerID;
inStream.Read(playerID); //skip header inStream.Read(playerID); //skip header
@ -133,8 +128,7 @@ void PlayerContainer::CreateTeamServer(Packet* packet)
members.reserve(membersSize); members.reserve(membersSize);
for (size_t i = 0; i < membersSize; i++) for (size_t i = 0; i < membersSize; i++) {
{
LWOOBJID member; LWOOBJID member;
inStream.Read(member); inStream.Read(member);
members.push_back(member); members.push_back(member);
@ -146,16 +140,14 @@ void PlayerContainer::CreateTeamServer(Packet* packet)
auto* team = CreateLocalTeam(members); auto* team = CreateLocalTeam(members);
if (team != nullptr) if (team != nullptr) {
{
team->zoneId = zoneId; team->zoneId = zoneId;
} }
UpdateTeamsOnWorld(team, false); UpdateTeamsOnWorld(team, false);
} }
void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time) void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time) {
{
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_MUTE_UPDATE); PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_MUTE_UPDATE);
@ -165,30 +157,23 @@ void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time)
Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true); Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
} }
TeamData* PlayerContainer::CreateLocalTeam(std::vector<LWOOBJID> members) TeamData* PlayerContainer::CreateLocalTeam(std::vector<LWOOBJID> members) {
{ if (members.empty()) {
if (members.empty())
{
return nullptr; return nullptr;
} }
TeamData* newTeam = nullptr; TeamData* newTeam = nullptr;
for (const auto member : members) for (const auto member : members) {
{
auto* team = GetTeam(member); auto* team = GetTeam(member);
if (team != nullptr) if (team != nullptr) {
{
RemoveMember(team, member, false, false, true); RemoveMember(team, member, false, false, true);
} }
if (newTeam == nullptr) if (newTeam == nullptr) {
{
newTeam = CreateTeam(member, true); newTeam = CreateTeam(member, true);
} } else {
else
{
AddMember(newTeam, member); AddMember(newTeam, member);
} }
} }
@ -200,8 +185,7 @@ TeamData* PlayerContainer::CreateLocalTeam(std::vector<LWOOBJID> members)
return newTeam; return newTeam;
} }
TeamData* PlayerContainer::CreateTeam(LWOOBJID leader, bool local) TeamData* PlayerContainer::CreateTeam(LWOOBJID leader, bool local) {
{
auto* team = new TeamData(); auto* team = new TeamData();
team->teamID = ++mTeamIDCounter; team->teamID = ++mTeamIDCounter;
@ -215,10 +199,8 @@ TeamData* PlayerContainer::CreateTeam(LWOOBJID leader, bool local)
return team; return team;
} }
TeamData* PlayerContainer::GetTeam(LWOOBJID playerID) TeamData* PlayerContainer::GetTeam(LWOOBJID playerID) {
{ for (auto* team : mTeams) {
for (auto* team : mTeams)
{
if (std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID) == team->memberIDs.end()) continue; if (std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID) == team->memberIDs.end()) continue;
return team; return team;
@ -227,8 +209,7 @@ TeamData* PlayerContainer::GetTeam(LWOOBJID playerID)
return nullptr; return nullptr;
} }
void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID) void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID) {
{
const auto index = std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID); const auto index = std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID);
if (index != team->memberIDs.end()) return; if (index != team->memberIDs.end()) return;
@ -240,24 +221,20 @@ void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID)
if (leader == nullptr || member == nullptr) return; if (leader == nullptr || member == nullptr) return;
const auto leaderName = GeneralUtils::ASCIIToUTF16(std::string(leader->playerName.c_str())); const auto leaderName = GeneralUtils::UTF8ToUTF16(leader->playerName);
const auto memberName = GeneralUtils::ASCIIToUTF16(std::string(member->playerName.c_str())); const auto memberName = GeneralUtils::UTF8ToUTF16(member->playerName);
ChatPacketHandler::SendTeamInviteConfirm(member, false, leader->playerID, leader->zoneID, team->lootFlag, 0, 0, leaderName); ChatPacketHandler::SendTeamInviteConfirm(member, false, leader->playerID, leader->zoneID, team->lootFlag, 0, 0, leaderName);
if (!team->local) if (!team->local) {
{
ChatPacketHandler::SendTeamSetLeader(member, leader->playerID); ChatPacketHandler::SendTeamSetLeader(member, leader->playerID);
} } else {
else
{
ChatPacketHandler::SendTeamSetLeader(member, LWOOBJID_EMPTY); ChatPacketHandler::SendTeamSetLeader(member, LWOOBJID_EMPTY);
} }
UpdateTeamsOnWorld(team, false); UpdateTeamsOnWorld(team, false);
for (const auto memberId : team->memberIDs) for (const auto memberId : team->memberIDs) {
{
auto* otherMember = GetPlayerData(memberId); auto* otherMember = GetPlayerData(memberId);
if (otherMember == member) continue; if (otherMember == member) continue;
@ -266,32 +243,27 @@ void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID)
ChatPacketHandler::SendTeamAddPlayer(member, false, team->local, false, memberId, otherMemberName, otherMember != nullptr ? otherMember->zoneID : LWOZONEID(0, 0, 0)); ChatPacketHandler::SendTeamAddPlayer(member, false, team->local, false, memberId, otherMemberName, otherMember != nullptr ? otherMember->zoneID : LWOZONEID(0, 0, 0));
if (otherMember != nullptr) if (otherMember != nullptr) {
{
ChatPacketHandler::SendTeamAddPlayer(otherMember, false, team->local, false, member->playerID, memberName, member->zoneID); 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); const auto index = std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID);
if (index == team->memberIDs.end()) return; if (index == team->memberIDs.end()) return;
auto* member = GetPlayerData(playerID); auto* member = GetPlayerData(playerID);
if (member != nullptr && !silent) if (member != nullptr && !silent) {
{
ChatPacketHandler::SendTeamSetLeader(member, LWOOBJID_EMPTY); ChatPacketHandler::SendTeamSetLeader(member, LWOOBJID_EMPTY);
} }
const auto memberName = GetName(playerID); const auto memberName = GetName(playerID);
for (const auto memberId : team->memberIDs) for (const auto memberId : team->memberIDs) {
{ if (silent && memberId == playerID) {
if (silent && memberId == playerID)
{
continue; continue;
} }
@ -306,25 +278,19 @@ void PlayerContainer::RemoveMember(TeamData* team, LWOOBJID playerID, bool disba
UpdateTeamsOnWorld(team, false); UpdateTeamsOnWorld(team, false);
if (team->memberIDs.size() <= 1) if (team->memberIDs.size() <= 1) {
{
DisbandTeam(team); DisbandTeam(team);
} } else {
else if (playerID == team->leaderID) {
{
if (playerID == team->leaderID)
{
PromoteMember(team, team->memberIDs[0]); PromoteMember(team, team->memberIDs[0]);
} }
} }
} }
void PlayerContainer::PromoteMember(TeamData* team, LWOOBJID newLeader) void PlayerContainer::PromoteMember(TeamData* team, LWOOBJID newLeader) {
{
team->leaderID = newLeader; team->leaderID = newLeader;
for (const auto memberId : team->memberIDs) for (const auto memberId : team->memberIDs) {
{
auto* otherMember = GetPlayerData(memberId); auto* otherMember = GetPlayerData(memberId);
if (otherMember == nullptr) continue; if (otherMember == nullptr) continue;
@ -333,19 +299,17 @@ void PlayerContainer::PromoteMember(TeamData* team, LWOOBJID newLeader)
} }
} }
void PlayerContainer::DisbandTeam(TeamData* team) void PlayerContainer::DisbandTeam(TeamData* team) {
{
const auto index = std::find(mTeams.begin(), mTeams.end(), team); const auto index = std::find(mTeams.begin(), mTeams.end(), team);
if (index == mTeams.end()) return; if (index == mTeams.end()) return;
for (const auto memberId : team->memberIDs) for (const auto memberId : team->memberIDs) {
{
auto* otherMember = GetPlayerData(memberId); auto* otherMember = GetPlayerData(memberId);
if (otherMember == nullptr) continue; if (otherMember == nullptr) continue;
const auto memberName = GeneralUtils::ASCIIToUTF16(std::string(otherMember->playerName.c_str())); const auto memberName = GeneralUtils::UTF8ToUTF16(otherMember->playerName);
ChatPacketHandler::SendTeamSetLeader(otherMember, LWOOBJID_EMPTY); 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);
@ -358,8 +322,7 @@ void PlayerContainer::DisbandTeam(TeamData* team)
delete team; delete team;
} }
void PlayerContainer::TeamStatusUpdate(TeamData* team) void PlayerContainer::TeamStatusUpdate(TeamData* team) {
{
const auto index = std::find(mTeams.begin(), mTeams.end(), team); const auto index = std::find(mTeams.begin(), mTeams.end(), team);
if (index == mTeams.end()) return; if (index == mTeams.end()) return;
@ -368,16 +331,14 @@ void PlayerContainer::TeamStatusUpdate(TeamData* team)
if (leader == nullptr) return; if (leader == nullptr) return;
const auto leaderName = GeneralUtils::ASCIIToUTF16(std::string(leader->playerName.c_str())); const auto leaderName = GeneralUtils::UTF8ToUTF16(leader->playerName);
for (const auto memberId : team->memberIDs) for (const auto memberId : team->memberIDs) {
{
auto* otherMember = GetPlayerData(memberId); auto* otherMember = GetPlayerData(memberId);
if (otherMember == nullptr) continue; if (otherMember == nullptr) continue;
if (!team->local) if (!team->local) {
{
ChatPacketHandler::SendTeamStatus(otherMember, team->leaderID, leader->zoneID, team->lootFlag, 0, leaderName); ChatPacketHandler::SendTeamStatus(otherMember, team->leaderID, leader->zoneID, team->lootFlag, 0, leaderName);
} }
} }
@ -385,20 +346,17 @@ void PlayerContainer::TeamStatusUpdate(TeamData* team)
UpdateTeamsOnWorld(team, false); UpdateTeamsOnWorld(team, false);
} }
void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) {
{
CBITSTREAM; CBITSTREAM;
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_TEAM_UPDATE); PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_TEAM_UPDATE);
bitStream.Write(team->teamID); bitStream.Write(team->teamID);
bitStream.Write(deleteTeam); bitStream.Write(deleteTeam);
if (!deleteTeam) if (!deleteTeam) {
{
bitStream.Write(team->lootFlag); bitStream.Write(team->lootFlag);
bitStream.Write(static_cast<char>(team->memberIDs.size())); bitStream.Write(static_cast<char>(team->memberIDs.size()));
for (const auto memberID : team->memberIDs) for (const auto memberID : team->memberIDs) {
{
bitStream.Write(memberID); bitStream.Write(memberID);
} }
} }
@ -406,8 +364,7 @@ void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam)
Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true); Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
} }
std::u16string PlayerContainer::GetName(LWOOBJID playerID) std::u16string PlayerContainer::GetName(LWOOBJID playerID) {
{
const auto& pair = mNames.find(playerID); const auto& pair = mNames.find(playerID);
if (pair == mNames.end()) return u""; if (pair == mNames.end()) return u"";
@ -415,12 +372,9 @@ std::u16string PlayerContainer::GetName(LWOOBJID playerID)
return pair->second; return pair->second;
} }
LWOOBJID PlayerContainer::GetId(const std::u16string& playerName) LWOOBJID PlayerContainer::GetId(const std::u16string& playerName) {
{ for (const auto& pair : mNames) {
for (const auto& pair : mNames) if (pair.second == playerName) {
{
if (pair.second == playerName)
{
return pair.first; return pair.first;
} }
} }
@ -428,7 +382,6 @@ LWOOBJID PlayerContainer::GetId(const std::u16string& playerName)
return LWOOBJID_EMPTY; return LWOOBJID_EMPTY;
} }
bool PlayerContainer::GetIsMuted(PlayerData* data) bool PlayerContainer::GetIsMuted(PlayerData* data) {
{
return data->muteExpire == 1 || data->muteExpire > time(NULL); return data->muteExpire == 1 || data->muteExpire > time(NULL);
} }

160
dCommon/AMFDeserialize.cpp Normal file
View File

@ -0,0 +1,160 @@
#include "AMFDeserialize.h"
#include "AMFFormat.h"
/**
* AMF3 Reference document https://rtmp.veriskope.com/pdf/amf3-file-format-spec.pdf
* AMF3 Deserializer written by EmosewaMC
*/
AMFValue* AMFDeserialize::Read(RakNet::BitStream* inStream) {
if (!inStream) return nullptr;
AMFValue* returnValue = nullptr;
// Read in the value type from the bitStream
int8_t marker;
inStream->Read(marker);
// Based on the typing, create the value associated with that and return the base value class
switch (marker) {
case AMFValueType::AMFUndefined: {
returnValue = new AMFUndefinedValue();
break;
}
case AMFValueType::AMFNull: {
returnValue = new AMFNullValue();
break;
}
case AMFValueType::AMFFalse: {
returnValue = new AMFFalseValue();
break;
}
case AMFValueType::AMFTrue: {
returnValue = new AMFTrueValue();
break;
}
case AMFValueType::AMFInteger: {
returnValue = ReadAmfInteger(inStream);
break;
}
case AMFValueType::AMFDouble: {
returnValue = ReadAmfDouble(inStream);
break;
}
case AMFValueType::AMFString: {
returnValue = ReadAmfString(inStream);
break;
}
case AMFValueType::AMFArray: {
returnValue = ReadAmfArray(inStream);
break;
}
// TODO We do not need these values, but if someone wants to implement them
// then please do so and add the corresponding unit tests.
case AMFValueType::AMFXMLDoc:
case AMFValueType::AMFDate:
case AMFValueType::AMFObject:
case AMFValueType::AMFXML:
case AMFValueType::AMFByteArray:
case AMFValueType::AMFVectorInt:
case AMFValueType::AMFVectorUInt:
case AMFValueType::AMFVectorDouble:
case AMFValueType::AMFVectorObject:
case AMFValueType::AMFDictionary: {
throw static_cast<AMFValueType>(marker);
break;
}
default:
throw static_cast<AMFValueType>(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;
}
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[length];
}
}
AMFValue* AMFDeserialize::ReadAmfDouble(RakNet::BitStream* inStream) {
auto doubleValue = new AMFDoubleValue();
double value;
inStream->Read<double>(value);
doubleValue->SetDoubleValue(value);
return doubleValue;
}
AMFValue* AMFDeserialize::ReadAmfArray(RakNet::BitStream* inStream) {
auto arrayValue = new AMFArrayValue();
// Read size of dense array
auto sizeOfDenseArray = (ReadU29(inStream) >> 1);
// Then read Key'd portion
while (true) {
auto key = ReadString(inStream);
// No more values when we encounter an empty string
if (key.size() == 0) break;
arrayValue->InsertValue(key, Read(inStream));
}
// Finally read dense portion
for (uint32_t i = 0; i < sizeOfDenseArray; i++) {
arrayValue->PushBackValue(Read(inStream));
}
return arrayValue;
}
AMFValue* AMFDeserialize::ReadAmfString(RakNet::BitStream* inStream) {
auto stringValue = new AMFStringValue();
stringValue->SetStringValue(ReadString(inStream));
return stringValue;
}
AMFValue* AMFDeserialize::ReadAmfInteger(RakNet::BitStream* inStream) {
auto integerValue = new AMFIntegerValue();
integerValue->SetIntegerValue(ReadU29(inStream));
return integerValue;
}

71
dCommon/AMFDeserialize.h Normal file
View File

@ -0,0 +1,71 @@
#pragma once
#include "BitStream.h"
#include <vector>
#include <string>
class AMFValue;
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.
*/
AMFValue* 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
*/
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
*/
AMFValue* 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
*/
AMFValue* 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
*/
AMFValue* 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
*/
AMFValue* ReadAmfInteger(RakNet::BitStream* inStream);
/**
* List of strings read so far saved to be read by reference.
*/
std::vector<std::string> accessedElements;
};

View File

@ -108,6 +108,14 @@ _AMFArrayList_::iterator AMFArrayValue::GetDenseIteratorEnd() {
return this->dense.end(); return this->dense.end();
} }
AMFArrayValue::~AMFArrayValue() {
for (auto valueToDelete : GetDenseArray()) {
if (valueToDelete) delete valueToDelete;
}
for (auto valueToDelete : GetAssociativeMap()) {
if (valueToDelete.second) delete valueToDelete.second;
}
}
// AMFObject Constructor // AMFObject Constructor
AMFObjectValue::AMFObjectValue(std::vector<std::pair<std::string, AMFValueType>> traits) { AMFObjectValue::AMFObjectValue(std::vector<std::pair<std::string, AMFValueType>> traits) {
@ -155,3 +163,9 @@ _AMFObjectTraits_::iterator AMFObjectValue::GetTraitsIteratorEnd() {
uint32_t AMFObjectValue::GetTraitArrayCount() { uint32_t AMFObjectValue::GetTraitArrayCount() {
return (uint32_t)this->traits.size(); return (uint32_t)this->traits.size();
} }
AMFObjectValue::~AMFObjectValue() {
for (auto valueToDelete = GetTraitsIteratorBegin(); valueToDelete != GetTraitsIteratorEnd(); valueToDelete++) {
if (valueToDelete->second.second) delete valueToDelete->second.second;
}
}

View File

@ -59,6 +59,7 @@ public:
\return The AMF value type \return The AMF value type
*/ */
virtual AMFValueType GetValueType() = 0; virtual AMFValueType GetValueType() = 0;
virtual ~AMFValue() {};
}; };
//! A typedef for a pointer to an AMF value //! A typedef for a pointer to an AMF value
@ -233,6 +234,7 @@ public:
}; };
//! The array value AMF type //! The array value AMF type
// This object will manage it's own memory map and list. Do not delete its values.
class AMFArrayValue : public AMFValue { class AMFArrayValue : public AMFValue {
private: private:
_AMFArrayMap_ associative; //!< The array map (associative part) _AMFArrayMap_ associative; //!< The array map (associative part)
@ -245,6 +247,7 @@ private:
AMFValueType GetValueType() { return AMFArray; } AMFValueType GetValueType() { return AMFArray; }
public: public:
~AMFArrayValue() override;
//! Inserts an item into the array map for a specific key //! Inserts an item into the array map for a specific key
/*! /*!
\param key The key to set \param key The key to set
@ -308,6 +311,18 @@ public:
\return Where the iterator ends \return Where the iterator ends
*/ */
_AMFArrayList_::iterator GetDenseIteratorEnd(); _AMFArrayList_::iterator GetDenseIteratorEnd();
//! Returns the associative map
/*!
\return The associative map
*/
_AMFArrayMap_ GetAssociativeMap() { return this->associative; };
//! Returns the dense array
/*!
\return The dense array
*/
_AMFArrayList_ GetDenseArray() { return this->dense; };
}; };
//! The anonymous object value AMF type //! The anonymous object value AMF type
@ -320,6 +335,7 @@ private:
\return The AMF value type \return The AMF value type
*/ */
AMFValueType GetValueType() { return AMFObject; } AMFValueType GetValueType() { return AMFObject; }
~AMFObjectValue() override;
public: public:
//! Constructor //! Constructor

View File

@ -37,6 +37,12 @@ void RakNet::BitStream::Write<AMFValue*>(AMFValue* value) {
break; break;
} }
case AMFDouble: {
AMFDoubleValue* v = (AMFDoubleValue*)value;
this->Write(*v);
break;
}
case AMFString: { case AMFString: {
AMFStringValue* v = (AMFStringValue*)value; AMFStringValue* v = (AMFStringValue*)value;
this->Write(*v); this->Write(*v);
@ -56,15 +62,17 @@ void RakNet::BitStream::Write<AMFValue*>(AMFValue* value) {
} }
case AMFArray: { case AMFArray: {
AMFArrayValue* v = (AMFArrayValue*)value; this->Write((AMFArrayValue*)value);
this->Write(*v);
break; break;
} }
} }
} }
} }
// A private function to write an value to a RakNet::BitStream /**
* 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) { void WriteUInt29(RakNet::BitStream* bs, uint32_t v) {
unsigned char b4 = (unsigned char)v; unsigned char b4 = (unsigned char)v;
if (v < 0x00200000) { if (v < 0x00200000) {
@ -102,79 +110,50 @@ void WriteUInt29(RakNet::BitStream* bs, uint32_t v) {
bs->Write(b4); bs->Write(b4);
} }
// Writes a flag number to a RakNet::BitStream /**
* 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) { void WriteFlagNumber(RakNet::BitStream* bs, uint32_t v) {
v = (v << 1) | 0x01; v = (v << 1) | 0x01;
WriteUInt29(bs, v); WriteUInt29(bs, v);
} }
// Writes an AMFString to a RakNet::BitStream /**
* 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) { void WriteAMFString(RakNet::BitStream* bs, const std::string& str) {
WriteFlagNumber(bs, (uint32_t)str.size()); WriteFlagNumber(bs, (uint32_t)str.size());
bs->Write(str.c_str(), (uint32_t)str.size()); bs->Write(str.c_str(), (uint32_t)str.size());
} }
// Writes an AMF U16 to a RakNet::BitStream /**
* 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) { void WriteAMFU16(RakNet::BitStream* bs, uint16_t value) {
unsigned char b2; bs->Write(value);
b2 = (unsigned char)value;
value = value >> 8;
bs->Write((unsigned char)value);
bs->Write(b2);
} }
// Writes an AMF U32 to RakNet::BitStream /**
* 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) { void WriteAMFU32(RakNet::BitStream* bs, uint32_t value) {
unsigned char b2; bs->Write(value);
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 /**
* 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) { void WriteAMFU64(RakNet::BitStream* bs, uint64_t value) {
unsigned char b2; bs->Write(value);
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);
} }
@ -243,13 +222,13 @@ void RakNet::BitStream::Write<AMFDateValue>(AMFDateValue value) {
// Writes an AMFArrayValue to BitStream // Writes an AMFArrayValue to BitStream
template<> template<>
void RakNet::BitStream::Write<AMFArrayValue>(AMFArrayValue value) { void RakNet::BitStream::Write<AMFArrayValue*>(AMFArrayValue* value) {
this->Write(AMFArray); this->Write(AMFArray);
uint32_t denseSize = value.GetDenseValueSize(); uint32_t denseSize = value->GetDenseValueSize();
WriteFlagNumber(this, denseSize); WriteFlagNumber(this, denseSize);
_AMFArrayMap_::iterator it = value.GetAssociativeIteratorValueBegin(); _AMFArrayMap_::iterator it = value->GetAssociativeIteratorValueBegin();
_AMFArrayMap_::iterator end = value.GetAssociativeIteratorValueEnd(); _AMFArrayMap_::iterator end = value->GetAssociativeIteratorValueEnd();
while (it != end) { while (it != end) {
WriteAMFString(this, it->first); WriteAMFString(this, it->first);
@ -260,8 +239,8 @@ void RakNet::BitStream::Write<AMFArrayValue>(AMFArrayValue value) {
this->Write(AMFNull); this->Write(AMFNull);
if (denseSize > 0) { if (denseSize > 0) {
_AMFArrayList_::iterator it2 = value.GetDenseIteratorBegin(); _AMFArrayList_::iterator it2 = value->GetDenseIteratorBegin();
_AMFArrayList_::iterator end2 = value.GetDenseIteratorEnd(); _AMFArrayList_::iterator end2 = value->GetDenseIteratorEnd();
while (it2 != end2) { while (it2 != end2) {
this->Write(*it2); this->Write(*it2);

View File

@ -7,7 +7,7 @@
#include <BitStream.h> #include <BitStream.h>
/*! /*!
\file AMFBitStream.hpp \file AMFFormat_BitStream.h
\brief A class that implements native writing of AMF values to RakNet::BitStream \brief A class that implements native writing of AMF values to RakNet::BitStream
*/ */
@ -88,5 +88,5 @@ namespace RakNet {
\param value The value to write \param value The value to write
*/ */
template <> template <>
void RakNet::BitStream::Write<AMFArrayValue>(AMFArrayValue value); void RakNet::BitStream::Write<AMFArrayValue*>(AMFArrayValue* value);
} } // namespace RakNet

180
dCommon/BrickByBrickFix.cpp Normal file
View File

@ -0,0 +1,180 @@
#include "BrickByBrickFix.h"
#include <memory>
#include <iostream>
#include <sstream>
#include "tinyxml2.h"
#include "Database.h"
#include "Game.h"
#include "ZCompression.h"
#include "dLogger.h"
//! Forward declarations
std::unique_ptr<sql::ResultSet> GetModelsFromDatabase();
void WriteSd0Magic(char* input, uint32_t chunkSize);
bool CheckSd0Magic(sql::Blob* 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 = GetModelsFromDatabase();
bool previousCommitValue = Database::GetAutoCommit();
Database::SetAutoCommit(false);
while (modelsToTruncate->next()) {
std::unique_ptr<sql::PreparedStatement> ugcModelToDelete(Database::CreatePreppedStmt("DELETE FROM ugc WHERE ugc.id = ?;"));
std::unique_ptr<sql::PreparedStatement> pcModelToDelete(Database::CreatePreppedStmt("DELETE FROM properties_contents WHERE ugc_id = ?;"));
std::string completeUncompressedModel{};
uint32_t chunkCount{};
uint64_t modelId = modelsToTruncate->getInt(1);
std::unique_ptr<sql::Blob> modelAsSd0(modelsToTruncate->getBlob(2));
// Check that header is sd0 by checking for the sd0 magic.
if (CheckSd0Magic(modelAsSd0.get())) {
while (true) {
uint32_t chunkSize{};
modelAsSd0->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 (!modelAsSd0->good()) break;
std::unique_ptr<uint8_t[]> compressedChunk(new uint8_t[chunkSize]);
for (uint32_t i = 0; i < chunkSize; i++) {
compressedChunk[i] = modelAsSd0->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[MAX_SD0_CHUNK_SIZE]);
int32_t err{};
int32_t actualUncompressedSize = ZCompression::Decompress(
compressedChunk.get(), chunkSize, uncompressedChunk.get(), MAX_SD0_CHUNK_SIZE, err);
if (actualUncompressedSize != -1) {
uint32_t previousSize = completeUncompressedModel.size();
completeUncompressedModel.append((char*)uncompressedChunk.get());
completeUncompressedModel.resize(previousSize + actualUncompressedSize);
} else {
Game::logger->Log("BrickByBrickFix", "Failed to inflate chunk %i for model %llu. Error: %i", chunkCount, modelId, err);
break;
}
chunkCount++;
}
std::unique_ptr<tinyxml2::XMLDocument> document = std::make_unique<tinyxml2::XMLDocument>();
if (!document) {
Game::logger->Log("BrickByBrickFix", "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
) {
Game::logger->Log("BrickByBrickFix",
"Brick-by-brick model %llu will be deleted!", modelId);
ugcModelToDelete->setInt64(1, modelsToTruncate->getInt64(1));
pcModelToDelete->setInt64(1, modelsToTruncate->getInt64(1));
ugcModelToDelete->execute();
pcModelToDelete->execute();
modelsTruncated++;
}
}
} else {
Game::logger->Log("BrickByBrickFix",
"Brick-by-brick model %llu will be deleted!", modelId);
ugcModelToDelete->setInt64(1, modelsToTruncate->getInt64(1));
pcModelToDelete->setInt64(1, modelsToTruncate->getInt64(1));
ugcModelToDelete->execute();
pcModelToDelete->execute();
modelsTruncated++;
}
}
Database::Commit();
Database::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 = GetModelsFromDatabase();
auto previousAutoCommitState = Database::GetAutoCommit();
Database::SetAutoCommit(false);
std::unique_ptr<sql::PreparedStatement> insertionStatement(Database::CreatePreppedStmt("UPDATE ugc SET lxfml = ? WHERE id = ?;"));
while (modelsToUpdate->next()) {
int64_t modelId = modelsToUpdate->getInt64(1);
std::unique_ptr<sql::Blob> oldLxfml(modelsToUpdate->getBlob(2));
// Check if the stored blob starts with zlib magic (0x78 0xDA - best compression of zlib)
// If it does, convert it to sd0.
if (oldLxfml->get() == 0x78 && oldLxfml->get() == 0xDA) {
// Get and save size of zlib compressed chunk.
oldLxfml->seekg(0, std::ios::end);
uint32_t oldLxfmlSize = static_cast<uint32_t>(oldLxfml->tellg());
oldLxfml->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] = oldLxfml->get();
}
std::string outputString(sd0ConvertedModel.get(), oldLxfmlSizeWithHeader);
std::istringstream outputStringStream(outputString);
insertionStatement->setBlob(1, static_cast<std::istream*>(&outputStringStream));
insertionStatement->setInt64(2, modelId);
try {
insertionStatement->executeUpdate();
Game::logger->Log("BrickByBrickFix", "Updated model %i to sd0", modelId);
updatedModels++;
} catch (sql::SQLException exception) {
Game::logger->Log(
"BrickByBrickFix",
"Failed to update model %i. This model should be inspected manually to see why."
"The database error is %s", modelId, exception.what());
}
}
}
Database::Commit();
Database::SetAutoCommit(previousAutoCommitState);
return updatedModels;
}
std::unique_ptr<sql::ResultSet> GetModelsFromDatabase() {
std::unique_ptr<sql::PreparedStatement> modelsRawDataQuery(Database::CreatePreppedStmt("SELECT id, lxfml FROM ugc;"));
return std::unique_ptr<sql::ResultSet>(modelsRawDataQuery->executeQuery());
}
/**
* @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(sql::Blob* streamToCheck) {
return streamToCheck->get() == 's' && streamToCheck->get() == 'd' && streamToCheck->get() == '0' && streamToCheck->get() == 0x01 && streamToCheck->get() == 0xFF;
}

26
dCommon/BrickByBrickFix.h Normal file
View File

@ -0,0 +1,26 @@
#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();
/**
* @brief Max size of an inflated sd0 zlib chunk
*
*/
constexpr uint32_t MAX_SD0_CHUNK_SIZE = 1024 * 256;
};

View File

@ -1,4 +1,5 @@
set(DCOMMON_SOURCES "AMFFormat.cpp" set(DCOMMON_SOURCES "AMFFormat.cpp"
"AMFDeserialize.cpp"
"AMFFormat_BitStream.cpp" "AMFFormat_BitStream.cpp"
"BinaryIO.cpp" "BinaryIO.cpp"
"dConfig.cpp" "dConfig.cpp"
@ -12,15 +13,43 @@ set(DCOMMON_SOURCES "AMFFormat.cpp"
"NiQuaternion.cpp" "NiQuaternion.cpp"
"SHA512.cpp" "SHA512.cpp"
"Type.cpp" "Type.cpp"
"ZCompression.cpp") "ZCompression.cpp"
"BrickByBrickFix.cpp"
)
include_directories(${PROJECT_SOURCE_DIR}/dCommon/) include_directories(${PROJECT_SOURCE_DIR}/dCommon/)
add_library(dCommon STATIC ${DCOMMON_SOURCES}) add_library(dCommon STATIC ${DCOMMON_SOURCES})
target_link_libraries(dCommon libbcrypt) target_link_libraries(dCommon bcrypt dDatabase tinyxml2)
if (UNIX) if (UNIX)
find_package(ZLIB REQUIRED) find_package(ZLIB REQUIRED)
target_link_libraries(dCommon ZLIB::ZLIB) 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 () endif ()
target_link_libraries(dCommon ZLIB::ZLIB)

View File

@ -142,12 +142,12 @@ void CatchUnhandled(int sig) {
demangled = demangle(functionName.c_str()); demangled = demangle(functionName.c_str());
if (demangled.empty()) { if (demangled.empty()) {
printf("[%02d] %s\n", i, demangled.c_str()); printf("[%02zu] %s\n", i, demangled.c_str());
} else { } else {
printf("[%02d] %s\n", i, functionName.c_str()); printf("[%02zu] %s\n", i, functionName.c_str());
} }
} else { } else {
printf("[%02d] %s\n", i, functionName.c_str()); printf("[%02zu] %s\n", i, functionName.c_str());
} }
} }
#else #else
@ -171,9 +171,6 @@ void CatchUnhandled(int sig) {
ErrorCallback, ErrorCallback,
nullptr); nullptr);
// Print error code
printf("Error code: %d\n", sig);
struct bt_ctx ctx = { state, 0 }; struct bt_ctx ctx = { state, 0 };
Bt(state); Bt(state);

View File

@ -6,7 +6,7 @@
#include <algorithm> #include <algorithm>
template <typename T> template <typename T>
inline size_t MinSize(size_t size, const std::basic_string<T>& string) { inline size_t MinSize(size_t size, const std::basic_string_view<T>& string) {
if (size == size_t(-1) || size > string.size()) { if (size == size_t(-1) || size > string.size()) {
return string.size(); return string.size();
} else { } else {
@ -24,7 +24,7 @@ inline bool IsTrailSurrogate(char16_t c) {
inline void PushUTF8CodePoint(std::string& ret, char32_t cp) { inline void PushUTF8CodePoint(std::string& ret, char32_t cp) {
if (cp <= 0x007F) { if (cp <= 0x007F) {
ret.push_back(cp); ret.push_back(static_cast<uint8_t>(cp));
} else if (cp <= 0x07FF) { } else if (cp <= 0x07FF) {
ret.push_back(0xC0 | (cp >> 6)); ret.push_back(0xC0 | (cp >> 6));
ret.push_back(0x80 | (cp & 0x3F)); ret.push_back(0x80 | (cp & 0x3F));
@ -42,16 +42,123 @@ inline void PushUTF8CodePoint(std::string& ret, char32_t cp) {
} }
} }
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();
const uint8_t* bytes = (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 //! Converts an std::string (ASCII) to UCS-2 / UTF-16
std::u16string GeneralUtils::ASCIIToUTF16(const std::string& string, size_t size) { std::u16string GeneralUtils::ASCIIToUTF16(const std::string_view& string, size_t size) {
size_t newSize = MinSize(size, string); size_t newSize = MinSize(size, string);
std::u16string ret; std::u16string ret;
ret.reserve(newSize); ret.reserve(newSize);
for (size_t i = 0; i < newSize; i++) { for (size_t i = 0; i < newSize; i++) {
char c = string[i]; char c = string[i];
assert(c > 0 && c <= 127); // Note: both 7-bit ascii characters and REPLACEMENT_CHARACTER fit in one char16_t
ret.push_back(static_cast<char16_t>(c)); ret.push_back((c > 0 && c <= 127) ? static_cast<char16_t>(c) : REPLACEMENT_CHARACTER);
} }
return ret; return ret;
@ -59,7 +166,7 @@ std::u16string GeneralUtils::ASCIIToUTF16(const std::string& string, size_t size
//! Converts a (potentially-ill-formed) UTF-16 string to UTF-8 //! Converts a (potentially-ill-formed) UTF-16 string to UTF-8
//! See: <http://simonsapin.github.io/wtf-8/#decoding-ill-formed-utf-16> //! See: <http://simonsapin.github.io/wtf-8/#decoding-ill-formed-utf-16>
std::string GeneralUtils::UTF16ToWTF8(const std::u16string& string, size_t size) { std::string GeneralUtils::UTF16ToWTF8(const std::u16string_view& string, size_t size) {
size_t newSize = MinSize(size, string); size_t newSize = MinSize(size, string);
std::string ret; std::string ret;
ret.reserve(newSize); ret.reserve(newSize);
@ -114,8 +221,7 @@ bool GeneralUtils::ReplaceInString(std::string& str, const std::string& from, co
return true; return true;
} }
std::vector<std::wstring> GeneralUtils::SplitString(std::wstring& str, wchar_t delimiter) std::vector<std::wstring> GeneralUtils::SplitString(std::wstring& str, wchar_t delimiter) {
{
std::vector<std::wstring> vector = std::vector<std::wstring>(); std::vector<std::wstring> vector = std::vector<std::wstring>();
std::wstring current; std::wstring current;
@ -132,8 +238,7 @@ std::vector<std::wstring> GeneralUtils::SplitString(std::wstring& str, wchar_t d
return vector; return vector;
} }
std::vector<std::u16string> GeneralUtils::SplitString(std::u16string& str, char16_t delimiter) std::vector<std::u16string> GeneralUtils::SplitString(std::u16string& str, char16_t delimiter) {
{
std::vector<std::u16string> vector = std::vector<std::u16string>(); std::vector<std::u16string> vector = std::vector<std::u16string>();
std::u16string current; std::u16string current;
@ -150,22 +255,17 @@ std::vector<std::u16string> GeneralUtils::SplitString(std::u16string& str, char1
return vector; 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::vector<std::string> vector = std::vector<std::string>();
std::string current = ""; 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]; char c = str[i];
if (c == delimiter) if (c == delimiter) {
{
vector.push_back(current); vector.push_back(current);
current = ""; current = "";
} } else {
else
{
current += c; current += c;
} }
} }
@ -193,8 +293,7 @@ std::u16string GeneralUtils::ReadWString(RakNet::BitStream *inStream) {
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <Windows.h> #include <Windows.h>
std::vector<std::string> GeneralUtils::GetFileNamesFromFolder(const std::string& folder) std::vector<std::string> GeneralUtils::GetFileNamesFromFolder(const std::string& folder) {
{
std::vector<std::string> names; std::vector<std::string> names;
std::string search_path = folder + "/*.*"; std::string search_path = folder + "/*.*";
WIN32_FIND_DATA fd; WIN32_FIND_DATA fd;

View File

@ -26,7 +26,18 @@ namespace GeneralUtils {
\param size A size to trim the string to. Default is -1 (No trimming) \param size A size to trim the string to. Default is -1 (No trimming)
\return An UTF-16 representation of the string \return An UTF-16 representation of the string
*/ */
std::u16string ASCIIToUTF16(const std::string& string, size_t size = -1); std::u16string ASCIIToUTF16(const std::string_view& 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);
//! Internal, do not use
bool _NextUTF8Char(std::string_view& slice, uint32_t& out);
//! Converts a UTF-16 string to a UTF-8 string //! Converts a UTF-16 string to a UTF-8 string
/*! /*!
@ -34,7 +45,7 @@ namespace GeneralUtils {
\param size A size to trim the string to. Default is -1 (No trimming) \param size A size to trim the string to. Default is -1 (No trimming)
\return An UTF-8 representation of the string \return An UTF-8 representation of the string
*/ */
std::string UTF16ToWTF8(const std::u16string& string, size_t size = -1); std::string UTF16ToWTF8(const std::u16string_view& string, size_t size = -1);
/** /**
* Compares two basic strings but does so ignoring case sensitivity * Compares two basic strings but does so ignoring case sensitivity
@ -109,8 +120,7 @@ namespace GeneralUtils {
if constexpr (std::is_integral_v<T>) { // constexpr only necessary on first statement if constexpr (std::is_integral_v<T>) { // constexpr only necessary on first statement
std::uniform_int_distribution<T> distribution(min, max); std::uniform_int_distribution<T> distribution(min, max);
return distribution(Game::randomEngine); return distribution(Game::randomEngine);
} } else if (std::is_floating_point_v<T>) {
else if (std::is_floating_point_v<T>) {
std::uniform_real_distribution<T> distribution(min, max); std::uniform_real_distribution<T> distribution(min, max);
return distribution(Game::randomEngine); return distribution(Game::randomEngine);
} }
@ -134,78 +144,64 @@ namespace GeneralUtils {
T Parse(const char* value); T Parse(const char* value);
template <> template <>
inline int32_t Parse(const char* value) inline int32_t Parse(const char* value) {
{
return std::stoi(value); return std::stoi(value);
} }
template <> template <>
inline int64_t Parse(const char* value) inline int64_t Parse(const char* value) {
{
return std::stoll(value); return std::stoll(value);
} }
template <> template <>
inline float Parse(const char* value) inline float Parse(const char* value) {
{
return std::stof(value); return std::stof(value);
} }
template <> template <>
inline double Parse(const char* value) inline double Parse(const char* value) {
{
return std::stod(value); return std::stod(value);
} }
template <> template <>
inline uint32_t Parse(const char* value) inline uint32_t Parse(const char* value) {
{
return std::stoul(value); return std::stoul(value);
} }
template <> template <>
inline uint64_t Parse(const char* value) inline uint64_t Parse(const char* value) {
{
return std::stoull(value); return std::stoull(value);
} }
template <typename T> template <typename T>
bool TryParse(const char* value, T& dst) bool TryParse(const char* value, T& dst) {
{ try {
try
{
dst = Parse<T>(value); dst = Parse<T>(value);
return true; return true;
} } catch (...) {
catch (...)
{
return false; return false;
} }
} }
template <typename T> template <typename T>
T Parse(const std::string& value) T Parse(const std::string& value) {
{
return Parse<T>(value.c_str()); return Parse<T>(value.c_str());
} }
template <typename T> template <typename T>
bool TryParse(const std::string& value, T& dst) bool TryParse(const std::string& value, T& dst) {
{
return TryParse<T>(value.c_str(), dst); return TryParse<T>(value.c_str(), dst);
} }
template<typename T> template<typename T>
std::u16string to_u16string(T value) std::u16string to_u16string(T value) {
{
return GeneralUtils::ASCIIToUTF16(std::to_string(value)); return GeneralUtils::ASCIIToUTF16(std::to_string(value));
} }
// From boost::hash_combine // From boost::hash_combine
template <class T> template <class T>
void hash_combine(std::size_t& s, const T& v) void hash_combine(std::size_t& s, const T& v) {
{
std::hash<T> h; std::hash<T> h;
s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2); s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2);
} }

View File

@ -49,7 +49,7 @@ LDFBaseData * LDFBaseData::DataFromString(const std::string& format) {
switch (type) { switch (type) {
case LDF_TYPE_UTF_16: { case LDF_TYPE_UTF_16: {
std::u16string data = GeneralUtils::ASCIIToUTF16(dataArray[1]); std::u16string data = GeneralUtils::UTF8ToUTF16(dataArray[1]);
return new LDFData<std::u16string>(key, data); return new LDFData<std::u16string>(key, data);
} }
@ -72,16 +72,11 @@ LDFBaseData * LDFBaseData::DataFromString(const std::string& format) {
{ {
uint32_t data; uint32_t data;
if (dataArray[1] == "true") if (dataArray[1] == "true") {
{
data = 1; data = 1;
} } else if (dataArray[1] == "false") {
else if (dataArray[1] == "false")
{
data = 0; data = 0;
} } else {
else
{
data = static_cast<uint32_t>(stoul(dataArray[1])); data = static_cast<uint32_t>(stoul(dataArray[1]));
} }
@ -91,16 +86,11 @@ LDFBaseData * LDFBaseData::DataFromString(const std::string& format) {
case LDF_TYPE_BOOLEAN: { case LDF_TYPE_BOOLEAN: {
bool data; bool data;
if (dataArray[1] == "true") if (dataArray[1] == "true") {
{
data = true; data = true;
} } else if (dataArray[1] == "false") {
else if (dataArray[1] == "false")
{
data = false; data = false;
} } else {
else
{
data = static_cast<bool>(stoi(dataArray[1])); data = static_cast<bool>(stoi(dataArray[1]));
} }

View File

@ -100,16 +100,14 @@ inline void MD5::II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4
////////////////////////////////////////////// //////////////////////////////////////////////
// default ctor, just initailize // default ctor, just initailize
MD5::MD5() MD5::MD5() {
{
init(); init();
} }
////////////////////////////////////////////// //////////////////////////////////////////////
// nifty shortcut ctor, compute MD5 for string and finalize it right away // nifty shortcut ctor, compute MD5 for string and finalize it right away
MD5::MD5(const std::string &text) MD5::MD5(const std::string& text) {
{
init(); init();
update(text.c_str(), text.length()); update(text.c_str(), text.length());
finalize(); finalize();
@ -117,8 +115,7 @@ MD5::MD5(const std::string &text)
////////////////////////////// //////////////////////////////
void MD5::init() void MD5::init() {
{
finalized = false; finalized = false;
count[0] = 0; count[0] = 0;
@ -134,8 +131,7 @@ void MD5::init()
////////////////////////////// //////////////////////////////
// decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4. // 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) void MD5::decode(uint4 output[], const uint1 input[], size_type len) {
{
for (unsigned int i = 0, j = 0; j < len; i++, j += 4) for (unsigned int i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((uint4)input[j]) | (((uint4)input[j + 1]) << 8) | output[i] = ((uint4)input[j]) | (((uint4)input[j + 1]) << 8) |
(((uint4)input[j + 2]) << 16) | (((uint4)input[j + 3]) << 24); (((uint4)input[j + 2]) << 16) | (((uint4)input[j + 3]) << 24);
@ -145,8 +141,7 @@ void MD5::decode(uint4 output[], const uint1 input[], size_type len)
// encodes input (uint4) into output (unsigned char). Assumes len is // encodes input (uint4) into output (unsigned char). Assumes len is
// a multiple of 4. // a multiple of 4.
void MD5::encode(uint1 output[], const uint4 input[], size_type len) void MD5::encode(uint1 output[], const uint4 input[], size_type len) {
{
for (size_type i = 0, j = 0; j < len; i++, j += 4) { for (size_type i = 0, j = 0; j < len; i++, j += 4) {
output[j] = input[i] & 0xff; output[j] = input[i] & 0xff;
output[j + 1] = (input[i] >> 8) & 0xff; output[j + 1] = (input[i] >> 8) & 0xff;
@ -158,8 +153,7 @@ void MD5::encode(uint1 output[], const uint4 input[], size_type len)
////////////////////////////// //////////////////////////////
// apply MD5 algo on a block // apply MD5 algo on a block
void MD5::transform(const uint1 block[blocksize]) void MD5::transform(const uint1 block[blocksize]) {
{
uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
decode(x, block, blocksize); decode(x, block, blocksize);
@ -248,8 +242,7 @@ void MD5::transform(const uint1 block[blocksize])
// MD5 block update operation. Continues an MD5 message-digest // MD5 block update operation. Continues an MD5 message-digest
// operation, processing another message block // operation, processing another message block
void MD5::update(const unsigned char input[], size_type length) void MD5::update(const unsigned char input[], size_type length) {
{
// compute number of bytes mod 64 // compute number of bytes mod 64
size_type index = count[0] / 8 % blocksize; size_type index = count[0] / 8 % blocksize;
@ -264,8 +257,7 @@ void MD5::update(const unsigned char input[], size_type length)
size_type i; size_type i;
// transform as many times as possible. // transform as many times as possible.
if (length >= firstpart) if (length >= firstpart) {
{
// fill buffer first, transform // fill buffer first, transform
memcpy(&buffer[index], input, firstpart); memcpy(&buffer[index], input, firstpart);
transform(buffer); transform(buffer);
@ -275,8 +267,7 @@ void MD5::update(const unsigned char input[], size_type length)
transform(&input[i]); transform(&input[i]);
index = 0; index = 0;
} } else
else
i = 0; i = 0;
// buffer remaining input // buffer remaining input
@ -286,8 +277,7 @@ void MD5::update(const unsigned char input[], size_type length)
////////////////////////////// //////////////////////////////
// for convenience provide a verson with signed char // for convenience provide a verson with signed char
void MD5::update(const char input[], size_type length) void MD5::update(const char input[], size_type length) {
{
update((const unsigned char*)input, length); update((const unsigned char*)input, length);
} }
@ -295,8 +285,7 @@ void MD5::update(const char input[], size_type length)
// MD5 finalization. Ends an MD5 message-digest operation, writing the // MD5 finalization. Ends an MD5 message-digest operation, writing the
// the message digest and zeroizing the context. // the message digest and zeroizing the context.
MD5& MD5::finalize() MD5& MD5::finalize() {
{
static unsigned char padding[64] = { 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, 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, 0, 0, 0, 0,
@ -332,8 +321,7 @@ MD5& MD5::finalize()
////////////////////////////// //////////////////////////////
// return hex representation of digest as string // return hex representation of digest as string
std::string MD5::hexdigest() const std::string MD5::hexdigest() const {
{
if (!finalized) if (!finalized)
return ""; return "";
@ -347,15 +335,13 @@ std::string MD5::hexdigest() const
////////////////////////////// //////////////////////////////
std::ostream& operator<<(std::ostream& out, MD5 md5) std::ostream& operator<<(std::ostream& out, MD5 md5) {
{
return out << md5.hexdigest(); return out << md5.hexdigest();
} }
////////////////////////////// //////////////////////////////
std::string md5(const std::string str) std::string md5(const std::string str) {
{
MD5 md5 = MD5(str); MD5 md5 = MD5(str);
return md5.hexdigest(); return md5.hexdigest();

View File

@ -16,55 +16,44 @@ std::vector<MetricVariable> Metrics::m_Variables = {
MetricVariable::Frame, MetricVariable::Frame,
}; };
void Metrics::AddMeasurement(MetricVariable variable, int64_t value) void Metrics::AddMeasurement(MetricVariable variable, int64_t value) {
{
const auto& iter = m_Metrics.find(variable); const auto& iter = m_Metrics.find(variable);
Metric* metric; Metric* metric;
if (iter == m_Metrics.end()) if (iter == m_Metrics.end()) {
{
metric = new Metric(); metric = new Metric();
m_Metrics[variable] = metric; m_Metrics[variable] = metric;
} } else {
else
{
metric = iter->second; metric = iter->second;
} }
AddMeasurement(metric, value); AddMeasurement(metric, value);
} }
void Metrics::AddMeasurement(Metric* metric, int64_t value) void Metrics::AddMeasurement(Metric* metric, int64_t value) {
{
const auto index = metric->measurementIndex; const auto index = metric->measurementIndex;
metric->measurements[index] = value; metric->measurements[index] = value;
if (metric->max == -1 || value > metric->max) if (metric->max == -1 || value > metric->max) {
{
metric->max = value; metric->max = value;
} } else if (metric->min == -1 || metric->min > value) {
else if (metric->min == -1 || metric->min > value)
{
metric->min = value; metric->min = value;
} }
if (metric->measurementSize < MAX_MEASURMENT_POINTS) if (metric->measurementSize < MAX_MEASURMENT_POINTS) {
{
metric->measurementSize++; metric->measurementSize++;
} }
metric->measurementIndex = (index + 1) % MAX_MEASURMENT_POINTS; metric->measurementIndex = (index + 1) % MAX_MEASURMENT_POINTS;
} }
const Metric* Metrics::GetMetric(MetricVariable variable) const Metric* Metrics::GetMetric(MetricVariable variable) {
{
const auto& iter = m_Metrics.find(variable); const auto& iter = m_Metrics.find(variable);
if (iter == m_Metrics.end()) if (iter == m_Metrics.end()) {
{
return nullptr; return nullptr;
} }
@ -72,8 +61,7 @@ const Metric* Metrics::GetMetric(MetricVariable variable)
int64_t average = 0; int64_t average = 0;
for (size_t i = 0; i < metric->measurementSize; i++) for (size_t i = 0; i < metric->measurementSize; i++) {
{
average += metric->measurements[i]; average += metric->measurements[i];
} }
@ -84,34 +72,28 @@ const Metric* Metrics::GetMetric(MetricVariable variable)
return metric; return metric;
} }
void Metrics::StartMeasurement(MetricVariable variable) void Metrics::StartMeasurement(MetricVariable variable) {
{
const auto& iter = m_Metrics.find(variable); const auto& iter = m_Metrics.find(variable);
Metric* metric; Metric* metric;
if (iter == m_Metrics.end()) if (iter == m_Metrics.end()) {
{
metric = new Metric(); metric = new Metric();
m_Metrics[variable] = metric; m_Metrics[variable] = metric;
} } else {
else
{
metric = iter->second; metric = iter->second;
} }
metric->activeMeasurement = std::chrono::high_resolution_clock::now(); metric->activeMeasurement = std::chrono::high_resolution_clock::now();
} }
void Metrics::EndMeasurement(MetricVariable variable) void Metrics::EndMeasurement(MetricVariable variable) {
{
const auto end = std::chrono::high_resolution_clock::now(); 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()) if (iter == m_Metrics.end()) {
{
return; return;
} }
@ -124,15 +106,12 @@ void Metrics::EndMeasurement(MetricVariable variable)
AddMeasurement(metric, nanoseconds); AddMeasurement(metric, nanoseconds);
} }
float Metrics::ToMiliseconds(int64_t nanoseconds) float Metrics::ToMiliseconds(int64_t nanoseconds) {
{
return (float)nanoseconds / 1e6; return (float)nanoseconds / 1e6;
} }
std::string Metrics::MetricVariableToString(MetricVariable variable) std::string Metrics::MetricVariableToString(MetricVariable variable) {
{ switch (variable) {
switch (variable)
{
case MetricVariable::GameLoop: case MetricVariable::GameLoop:
return "GameLoop"; return "GameLoop";
case MetricVariable::PacketHandling: case MetricVariable::PacketHandling:
@ -159,15 +138,12 @@ std::string Metrics::MetricVariableToString(MetricVariable variable)
} }
} }
const std::vector<MetricVariable>& Metrics::GetAllMetrics() const std::vector<MetricVariable>& Metrics::GetAllMetrics() {
{
return m_Variables; return m_Variables;
} }
void Metrics::Clear() void Metrics::Clear() {
{ for (const auto& pair : m_Metrics) {
for (const auto& pair : m_Metrics)
{
delete pair.second; delete pair.second;
} }
@ -212,8 +188,7 @@ void Metrics::Clear()
* memory use) measured in bytes, or zero if the value cannot be * memory use) measured in bytes, or zero if the value cannot be
* determined on this OS. * determined on this OS.
*/ */
size_t Metrics::GetPeakRSS() size_t Metrics::GetPeakRSS() {
{
#if defined(_WIN32) #if defined(_WIN32)
/* Windows -------------------------------------------------- */ /* Windows -------------------------------------------------- */
PROCESS_MEMORY_COUNTERS info; PROCESS_MEMORY_COUNTERS info;
@ -226,8 +201,7 @@ size_t Metrics::GetPeakRSS()
int fd = -1; int fd = -1;
if ((fd = open("/proc/self/psinfo", O_RDONLY)) == -1) if ((fd = open("/proc/self/psinfo", O_RDONLY)) == -1)
return (size_t)0L; /* Can't open? */ return (size_t)0L; /* Can't open? */
if ( read( fd, &psinfo, sizeof(psinfo) ) != sizeof(psinfo) ) if (read(fd, &psinfo, sizeof(psinfo)) != sizeof(psinfo)) {
{
close(fd); close(fd);
return (size_t)0L; /* Can't read? */ return (size_t)0L; /* Can't read? */
} }
@ -255,8 +229,7 @@ size_t Metrics::GetPeakRSS()
* Returns the current resident set size (physical memory use) measured * Returns the current resident set size (physical memory use) measured
* in bytes, or zero if the value cannot be determined on this OS. * in bytes, or zero if the value cannot be determined on this OS.
*/ */
size_t Metrics::GetCurrentRSS() size_t Metrics::GetCurrentRSS() {
{
#if defined(_WIN32) #if defined(_WIN32)
/* Windows -------------------------------------------------- */ /* Windows -------------------------------------------------- */
PROCESS_MEMORY_COUNTERS info; PROCESS_MEMORY_COUNTERS info;
@ -278,8 +251,7 @@ size_t Metrics::GetCurrentRSS()
FILE* fp = NULL; FILE* fp = NULL;
if ((fp = fopen("/proc/self/statm", "r")) == NULL) if ((fp = fopen("/proc/self/statm", "r")) == NULL)
return (size_t)0L; /* Can't open? */ return (size_t)0L; /* Can't open? */
if ( fscanf( fp, "%*s%ld", &rss ) != 1 ) if (fscanf(fp, "%*s%ld", &rss) != 1) {
{
fclose(fp); fclose(fp);
return (size_t)0L; /* Can't read? */ return (size_t)0L; /* Can't read? */
} }
@ -293,8 +265,7 @@ size_t Metrics::GetCurrentRSS()
} }
size_t Metrics::GetProcessID() size_t Metrics::GetProcessID() {
{
#if defined(_WIN32) #if defined(_WIN32)
return GetCurrentProcessId(); return GetCurrentProcessId();
#else #else

View File

@ -175,8 +175,7 @@ bool NiPoint3::IsWithinSpehere(const NiPoint3& sphereCenter, float radius) {
return (diffVec.SquaredLength() <= (radius * radius)); return (diffVec.SquaredLength() <= (radius * radius));
} }
NiPoint3 NiPoint3::ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, const NiPoint3& p) NiPoint3 NiPoint3::ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, const NiPoint3& p) {
{
if (a == b) return a; if (a == b) return a;
const auto pa = p - a; const auto pa = p - a;
@ -191,16 +190,14 @@ NiPoint3 NiPoint3::ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, cons
return a + ab * t; return a + ab * t;
} }
float NiPoint3::Angle(const NiPoint3& a, const NiPoint3& b) float NiPoint3::Angle(const NiPoint3& a, const NiPoint3& b) {
{
const auto dot = a.DotProduct(b); const auto dot = a.DotProduct(b);
const auto lenA = a.SquaredLength(); const auto lenA = a.SquaredLength();
const auto lenB = a.SquaredLength(); const auto lenB = a.SquaredLength();
return acos(dot / sqrt(lenA * lenB)); return acos(dot / sqrt(lenA * lenB));
} }
float NiPoint3::Distance(const NiPoint3& a, const NiPoint3& b) float NiPoint3::Distance(const NiPoint3& a, const NiPoint3& b) {
{
const auto dx = a.x - b.x; const auto dx = a.x - b.x;
const auto dy = a.y - b.y; const auto dy = a.y - b.y;
const auto dz = a.z - b.z; const auto dz = a.z - b.z;
@ -208,8 +205,7 @@ float NiPoint3::Distance(const NiPoint3& a, const NiPoint3& b)
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) float NiPoint3::DistanceSquared(const NiPoint3& a, const NiPoint3& b) {
{
const auto dx = a.x - b.x; const auto dx = a.x - b.x;
const auto dy = a.y - b.y; const auto dy = a.y - b.y;
const auto dz = a.z - b.z; const auto dz = a.z - b.z;
@ -217,8 +213,7 @@ float NiPoint3::DistanceSquared(const NiPoint3& a, const NiPoint3& b)
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) NiPoint3 NiPoint3::MoveTowards(const NiPoint3& current, const NiPoint3& target, float maxDistanceDelta) {
{
float dx = target.x - current.x; float dx = target.x - current.x;
float dy = target.y - current.y; float dy = target.y - current.y;
float dz = target.z - current.z; float dz = target.z - current.z;

View File

@ -99,8 +99,7 @@ Vector3 NiQuaternion::GetEulerAngles() const {
if (std::abs(sinp) >= 1) { if (std::abs(sinp) >= 1) {
angles.y = std::copysign(3.14 / 2, sinp); // use 90 degrees if out of range angles.y = std::copysign(3.14 / 2, sinp); // use 90 degrees if out of range
} } else {
else {
angles.y = std::asin(sinp); angles.y = std::asin(sinp);
} }
@ -149,8 +148,7 @@ NiQuaternion NiQuaternion::LookAt(const NiPoint3& sourcePoint, const NiPoint3& d
return NiQuaternion::CreateFromAxisAngle(vecA, rotAngle); return NiQuaternion::CreateFromAxisAngle(vecA, rotAngle);
} }
NiQuaternion NiQuaternion::LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint) NiQuaternion NiQuaternion::LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint) {
{
NiPoint3 forwardVector = NiPoint3(destPoint - sourcePoint).Unitize(); NiPoint3 forwardVector = NiPoint3(destPoint - sourcePoint).Unitize();
NiPoint3 posZ = NiPoint3::UNIT_Z; NiPoint3 posZ = NiPoint3::UNIT_Z;
@ -179,8 +177,7 @@ NiQuaternion NiQuaternion::CreateFromAxisAngle(const Vector3& axis, float angle)
return q; return q;
} }
NiQuaternion NiQuaternion::FromEulerAngles(const NiPoint3& eulerAngles) NiQuaternion NiQuaternion::FromEulerAngles(const NiPoint3& eulerAngles) {
{
// Abbreviations for the various angular functions // Abbreviations for the various angular functions
float cy = cos(eulerAngles.z * 0.5); float cy = cos(eulerAngles.z * 0.5);
float sy = sin(eulerAngles.z * 0.5); float sy = sin(eulerAngles.z * 0.5);

View File

@ -45,8 +45,7 @@ const unsigned long long SHA512::sha512_k[80] = //ULL = uint64
0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL }; 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL };
void SHA512::transform(const unsigned char *message, unsigned int block_nb) void SHA512::transform(const unsigned char* message, unsigned int block_nb) {
{
uint64 w[80]; uint64 w[80];
uint64 wv[8]; uint64 wv[8];
uint64 t1, t2; uint64 t1, t2;
@ -83,8 +82,7 @@ void SHA512::transform(const unsigned char *message, unsigned int block_nb)
} }
} }
void SHA512::init() void SHA512::init() {
{
m_h[0] = 0x6a09e667f3bcc908ULL; m_h[0] = 0x6a09e667f3bcc908ULL;
m_h[1] = 0xbb67ae8584caa73bULL; m_h[1] = 0xbb67ae8584caa73bULL;
m_h[2] = 0x3c6ef372fe94f82bULL; m_h[2] = 0x3c6ef372fe94f82bULL;
@ -97,8 +95,7 @@ void SHA512::init()
m_tot_len = 0; m_tot_len = 0;
} }
void SHA512::update(const unsigned char *message, unsigned int len) void SHA512::update(const unsigned char* message, unsigned int len) {
{
unsigned int block_nb; unsigned int block_nb;
unsigned int new_len, rem_len, tmp_len; unsigned int new_len, rem_len, tmp_len;
const unsigned char* shifted_message; const unsigned char* shifted_message;
@ -120,8 +117,7 @@ void SHA512::update(const unsigned char *message, unsigned int len)
m_tot_len += (block_nb + 1) << 7; m_tot_len += (block_nb + 1) << 7;
} }
void SHA512::final(unsigned char *digest) void SHA512::final(unsigned char* digest) {
{
unsigned int block_nb; unsigned int block_nb;
unsigned int pm_len; unsigned int pm_len;
unsigned int len_b; unsigned int len_b;
@ -139,8 +135,7 @@ void SHA512::final(unsigned char *digest)
} }
} }
std::string sha512(std::string input) std::string sha512(std::string input) {
{
unsigned char digest[SHA512::DIGEST_SIZE]; unsigned char digest[SHA512::DIGEST_SIZE];
memset(digest, 0, SHA512::DIGEST_SIZE); memset(digest, 0, SHA512::DIGEST_SIZE);
class SHA512 ctx; class SHA512 ctx;

View File

@ -1,19 +1,14 @@
#include "ZCompression.h" #include "ZCompression.h"
#ifndef _WIN32
#include <zlib.h> #include <zlib.h>
namespace ZCompression namespace ZCompression {
{ int32_t GetMaxCompressedLength(int32_t nLenSrc) {
int32_t GetMaxCompressedLength(int32_t nLenSrc)
{
int32_t n16kBlocks = (nLenSrc + 16383) / 16384; // round up any fraction of a block int32_t n16kBlocks = (nLenSrc + 16383) / 16384; // round up any fraction of a block
return (nLenSrc + 6 + (n16kBlocks * 5)); return (nLenSrc + 6 + (n16kBlocks * 5));
} }
int32_t Compress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst) int32_t Compress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst) {
{
z_stream zInfo = { 0 }; z_stream zInfo = { 0 };
zInfo.total_in = zInfo.avail_in = nLenSrc; zInfo.total_in = zInfo.avail_in = nLenSrc;
zInfo.total_out = zInfo.avail_out = nLenDst; zInfo.total_out = zInfo.avail_out = nLenDst;
@ -30,11 +25,9 @@ namespace ZCompression
} }
deflateEnd(&zInfo); // zlib function deflateEnd(&zInfo); // zlib function
return(nRet); return(nRet);
} }
int32_t Decompress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst, int32_t& nErr) 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 // Get the size of the decompressed data
z_stream zInfo = { 0 }; z_stream zInfo = { 0 };
zInfo.total_in = zInfo.avail_in = nLenSrc; zInfo.total_in = zInfo.avail_in = nLenSrc;
@ -52,26 +45,6 @@ namespace ZCompression
} }
inflateEnd(&zInfo); // zlib function inflateEnd(&zInfo); // zlib function
return(nRet); 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
*/
} }
} }
#endif

View File

@ -1,13 +1,8 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include "dPlatforms.h" namespace ZCompression {
#ifndef DARKFLAME_PLATFORM_WIN32
namespace ZCompression
{
int32_t GetMaxCompressedLength(int32_t nLenSrc); int32_t GetMaxCompressedLength(int32_t nLenSrc);
int32_t Compress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst); int32_t Compress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst);
@ -15,4 +10,3 @@ namespace ZCompression
int32_t Decompress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst, int32_t& nErr); int32_t Decompress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst, int32_t& nErr);
} }
#endif

View File

@ -387,6 +387,7 @@ enum eReplicaComponentType : int32_t {
COMPONENT_TYPE_PROPERTY = 36, //!< The Property Component COMPONENT_TYPE_PROPERTY = 36, //!< The Property Component
COMPONENT_TYPE_SCRIPTED_ACTIVITY = 39, //!< The ScriptedActivity Component COMPONENT_TYPE_SCRIPTED_ACTIVITY = 39, //!< The ScriptedActivity Component
COMPONENT_TYPE_PHANTOM_PHYSICS = 40, //!< The PhantomPhysics Component COMPONENT_TYPE_PHANTOM_PHYSICS = 40, //!< The PhantomPhysics Component
COMPONENT_TYPE_MODEL = 42, //!< The Model Component
COMPONENT_TYPE_PROPERTY_ENTRANCE = 43, //!< The PhantomPhysics Component COMPONENT_TYPE_PROPERTY_ENTRANCE = 43, //!< The PhantomPhysics Component
COMPONENT_TYPE_PROPERTY_MANAGEMENT = 45, //!< The PropertyManagement Component COMPONENT_TYPE_PROPERTY_MANAGEMENT = 45, //!< The PropertyManagement Component
COMPONENT_TYPE_REBUILD = 48, //!< The Rebuild Component COMPONENT_TYPE_REBUILD = 48, //!< The Rebuild Component
@ -401,18 +402,18 @@ enum eReplicaComponentType : int32_t {
COMPONENT_TYPE_RACING_CONTROL = 71, //!< The RacingControl Component COMPONENT_TYPE_RACING_CONTROL = 71, //!< The RacingControl Component
COMPONENT_TYPE_MISSION_OFFER = 73, //!< The MissionOffer Component COMPONENT_TYPE_MISSION_OFFER = 73, //!< The MissionOffer Component
COMPONENT_TYPE_EXHIBIT = 75, //!< The Exhibit Component COMPONENT_TYPE_EXHIBIT = 75, //!< The Exhibit Component
COMPONENT_TYPE_RACING_STATS = 74, //!< The Exhibit Component COMPONENT_TYPE_RACING_STATS = 74, //!< The Racing Stats Component
COMPONENT_TYPE_SOUND_TRIGGER = 77, //!< The Sound Trigger Component COMPONENT_TYPE_SOUND_TRIGGER = 77, //!< The Sound Trigger Component
COMPONENT_TYPE_PROXIMITY_MONITOR = 78, //!< The Proximity Monitor Component COMPONENT_TYPE_PROXIMITY_MONITOR = 78, //!< The Proximity Monitor Component
COMPONENT_TYPE_MISSION = 84, //!< The Mission Component COMPONENT_TYPE_MISSION = 84, //!< The Mission Component
COMPONENT_TYPE_ROCKET_LAUNCH_LUP = 97, //!< The LUP Launchpad Componen COMPONENT_TYPE_ROCKET_LAUNCH_LUP = 97, //!< The LUP Launchpad Componen
COMPONENT_TYPE_RAIL_ACTIVATOR = 104, COMPONENT_TYPE_RAIL_ACTIVATOR = 104, //!< The Rail Activator Component
COMPONENT_TYPE_PLAYER_FORCED_MOVEMENT = 106, //!< The Player Forced Movement Component
COMPONENT_TYPE_POSSESSABLE = 108, //!< The Possessable Component COMPONENT_TYPE_POSSESSABLE = 108, //!< The Possessable Component
COMPONENT_TYPE_LEVEL_PROGRESSION = 109, //!< The Level Progression Component
COMPONENT_TYPE_POSSESSOR = 110, //!< The Possessor Component COMPONENT_TYPE_POSSESSOR = 110, //!< The Possessor Component
COMPONENT_TYPE_BUILD_BORDER = 114, //!< The Build Border Component COMPONENT_TYPE_BUILD_BORDER = 114, //!< The Build Border Component
COMPONENT_TYPE_DESTROYABLE = 1000, //!< The Destroyable Component COMPONENT_TYPE_DESTROYABLE = 1000, //!< The Destroyable Component
COMPONENT_TYPE_MODEL = 5398484 //look man idk
}; };
enum class UseItemResponse : uint32_t { enum class UseItemResponse : uint32_t {
@ -541,7 +542,7 @@ enum ePlayerFlags {
TOOLTIP_TALK_TO_SKYLAND_TO_GET_HAT = 52, TOOLTIP_TALK_TO_SKYLAND_TO_GET_HAT = 52,
MODULAR_BUILD_PLAYER_PLACES_FIRST_MODEL_IN_SCRATCH = 53, MODULAR_BUILD_PLAYER_PLACES_FIRST_MODEL_IN_SCRATCH = 53,
MODULAR_BUILD_FIRST_ARROW_DISPLAY_FOR_MODULE = 54, MODULAR_BUILD_FIRST_ARROW_DISPLAY_FOR_MODULE = 54,
AG_BEACON_QB,_SO_THE_PLAYER_CAN_ALWAYS_BUILD_THEM = 55, AG_BEACON_QB_SO_THE_PLAYER_CAN_ALWAYS_BUILD_THEM = 55,
GF_PET_DIG_FLAG_1 = 56, GF_PET_DIG_FLAG_1 = 56,
GF_PET_DIG_FLAG_2 = 57, GF_PET_DIG_FLAG_2 = 57,
GF_PET_DIG_FLAG_3 = 58, GF_PET_DIG_FLAG_3 = 58,
@ -627,6 +628,7 @@ enum ePlayerFlags {
GF_BINOC_IN_CROC_AREA = 1308, GF_BINOC_IN_CROC_AREA = 1308,
GF_BINOC_IN_JAIL_AREA = 1309, GF_BINOC_IN_JAIL_AREA = 1309,
GF_BINOC_TELESCOPE_NEXT_TO_CAPTAIN_JACK = 1310, GF_BINOC_TELESCOPE_NEXT_TO_CAPTAIN_JACK = 1310,
NT_PLINTH_REBUILD = 1919,
NT_FACTION_SPY_DUKE = 1974, NT_FACTION_SPY_DUKE = 1974,
NT_FACTION_SPY_OVERBUILD = 1976, NT_FACTION_SPY_OVERBUILD = 1976,
NT_FACTION_SPY_HAEL = 1977, NT_FACTION_SPY_HAEL = 1977,

View File

@ -33,7 +33,7 @@ void dLogger::vLog(const char* format, va_list args) {
char timeStr[70]; char timeStr[70];
strftime(timeStr, sizeof(timeStr), "%d-%m-%y %H:%M:%S", &time); strftime(timeStr, sizeof(timeStr), "%d-%m-%y %H:%M:%S", &time);
char message[2048]; char message[2048];
vsprintf_s(message, format, args); vsnprintf(message, 2048, format, args);
if (m_logToConsole) std::cout << "[" << timeStr << "] " << message; if (m_logToConsole) std::cout << "[" << timeStr << "] " << message;
mFile << "[" << timeStr << "] " << message; mFile << "[" << timeStr << "] " << message;
@ -43,7 +43,7 @@ void dLogger::vLog(const char* format, va_list args) {
char timeStr[70]; char timeStr[70];
strftime(timeStr, sizeof(timeStr), "%d-%m-%y %H:%M:%S", time); strftime(timeStr, sizeof(timeStr), "%d-%m-%y %H:%M:%S", time);
char message[2048]; char message[2048];
vsprintf(message, format, args); vsnprintf(message, 2048, format, args);
if (m_logToConsole) { if (m_logToConsole) {
fputs("[", stdout); fputs("[", stdout);
@ -76,7 +76,7 @@ void dLogger::LogBasic(const std::string & message) {
void dLogger::Log(const char* className, const char* format, ...) { void dLogger::Log(const char* className, const char* format, ...) {
va_list args; va_list args;
std::string log = "[" + std::string(className) + "] " + std::string(format); std::string log = "[" + std::string(className) + "] " + std::string(format) + "\n";
va_start(args, format); va_start(args, format);
vLog(log.c_str(), args); vLog(log.c_str(), args);
va_end(args); va_end(args);

View File

@ -0,0 +1,14 @@
#pragma once
#ifndef __EUNEQUIPPABLEACTIVETYPE__H__
#define __EUNEQUIPPABLEACTIVETYPE__H__
#include <cstdint>
enum class eUnequippableActiveType : int32_t {
INVALID = -1,
PET = 0,
MOUNT
};
#endif //!__EUNEQUIPPABLEACTIVETYPE__H__

View File

@ -93,6 +93,4 @@ public:
return nullptr; return nullptr;
} }
void LoadHost();
}; };

View File

@ -43,8 +43,8 @@ void Database::Destroy(std::string source, bool log) {
if (!con) return; if (!con) return;
if (log) { if (log) {
if (source != "") Game::logger->Log("Database", "Destroying MySQL connection from %s!\n", source.c_str()); if (source != "") Game::logger->Log("Database", "Destroying MySQL connection from %s!", source.c_str());
else Game::logger->Log("Database", "Destroying MySQL connection!\n"); else Game::logger->Log("Database", "Destroying MySQL connection!");
} }
con->close(); con->close();
@ -63,17 +63,16 @@ sql::PreparedStatement* Database::CreatePreppedStmt(const std::string& query) {
if (!con) { if (!con) {
Connect(); Connect();
Game::logger->Log("Database", "Trying to reconnect to MySQL\n"); Game::logger->Log("Database", "Trying to reconnect to MySQL");
} }
if (!con->isValid() || con->isClosed()) if (!con->isValid() || con->isClosed()) {
{
delete con; delete con;
con = nullptr; con = nullptr;
Connect(); Connect();
Game::logger->Log("Database", "Trying to reconnect to MySQL from invalid or closed connection\n"); Game::logger->Log("Database", "Trying to reconnect to MySQL from invalid or closed connection");
} }
auto* stmt = con->prepareStatement(str); auto* stmt = con->prepareStatement(str);
@ -84,3 +83,15 @@ sql::PreparedStatement* Database::CreatePreppedStmt(const std::string& query) {
void Database::Commit() { void Database::Commit() {
Database::con->commit(); Database::con->commit();
} }
bool Database::GetAutoCommit() {
// TODO This should not just access a pointer. A future PR should update this
// to check for null and throw an error if the connection is not valid.
return con->getAutoCommit();
}
void Database::SetAutoCommit(bool value) {
// TODO This should not just access a pointer. A future PR should update this
// to check for null and throw an error if the connection is not valid.
Database::con->setAutoCommit(value);
}

View File

@ -23,6 +23,8 @@ public:
static sql::Statement* CreateStmt(); static sql::Statement* CreateStmt();
static sql::PreparedStatement* CreatePreppedStmt(const std::string& query); static sql::PreparedStatement* CreatePreppedStmt(const std::string& query);
static void Commit(); static void Commit();
static bool GetAutoCommit();
static void SetAutoCommit(bool value);
static std::string GetDatabase() { return database; } static std::string GetDatabase() { return database; }
static sql::Properties GetProperties() { return props; } static sql::Properties GetProperties() { return props; }

View File

@ -1,5 +1,6 @@
#include "MigrationRunner.h" #include "MigrationRunner.h"
#include "BrickByBrickFix.h"
#include "GeneralUtils.h" #include "GeneralUtils.h"
#include <fstream> #include <fstream>
@ -7,13 +8,13 @@
#include <thread> #include <thread>
void MigrationRunner::RunMigrations() { void MigrationRunner::RunMigrations() {
auto stmt = Database::CreatePreppedStmt("CREATE TABLE IF NOT EXISTS migration_history (name TEXT NOT NULL, date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP());"); auto* stmt = Database::CreatePreppedStmt("CREATE TABLE IF NOT EXISTS migration_history (name TEXT NOT NULL, date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP());");
stmt->executeQuery(); stmt->execute();
delete stmt; delete stmt;
sql::SQLString finalSQL = ""; sql::SQLString finalSQL = "";
Migration checkMigration{}; Migration checkMigration{};
bool runSd0Migrations = false;
for (const auto& entry : GeneralUtils::GetFileNamesFromFolder("./migrations/")) { for (const auto& entry : GeneralUtils::GetFileNamesFromFolder("./migrations/")) {
auto migration = LoadMigration(entry); auto migration = LoadMigration(entry);
@ -25,16 +26,18 @@ void MigrationRunner::RunMigrations() {
stmt = Database::CreatePreppedStmt("SELECT name FROM migration_history WHERE name = ?;"); stmt = Database::CreatePreppedStmt("SELECT name FROM migration_history WHERE name = ?;");
stmt->setString(1, migration.name); stmt->setString(1, migration.name);
auto res = stmt->executeQuery(); auto* res = stmt->executeQuery();
bool doExit = res->next(); bool doExit = res->next();
delete res; delete res;
delete stmt; delete stmt;
if (doExit) continue; if (doExit) continue;
Game::logger->Log("MigrationRunner", "Running migration: " + migration.name + "\n"); Game::logger->Log("MigrationRunner", "Running migration: %s", migration.name.c_str());
if (migration.name == "5_brick_model_sd0.sql") {
runSd0Migrations = true;
} else {
finalSQL.append(migration.data); finalSQL.append(migration.data);
finalSQL.append('\n'); }
stmt = Database::CreatePreppedStmt("INSERT INTO migration_history (name) VALUES (?);"); stmt = Database::CreatePreppedStmt("INSERT INTO migration_history (name) VALUES (?);");
stmt->setString(1, entry); stmt->setString(1, entry);
@ -42,16 +45,31 @@ void MigrationRunner::RunMigrations() {
delete stmt; delete stmt;
} }
if (finalSQL.empty() && !runSd0Migrations) {
Game::logger->Log("MigrationRunner", "Server database is up to date.");
return;
}
if (!finalSQL.empty()) { if (!finalSQL.empty()) {
auto migration = GeneralUtils::SplitString(static_cast<std::string>(finalSQL), ';');
std::unique_ptr<sql::Statement> simpleStatement(Database::CreateStmt());
for (auto& query : migration) {
try { try {
auto simpleStatement = Database::CreateStmt(); if (query.empty()) continue;
simpleStatement->execute(finalSQL); simpleStatement->execute(query);
delete simpleStatement; } catch (sql::SQLException& e) {
Game::logger->Log("MigrationRunner", "Encountered error running migration: %s", e.what());
} }
catch (sql::SQLException e) {
Game::logger->Log("MigrationRunner", std::string("Encountered error running migration: ") + e.what() + "\n");
} }
} }
// Do this last on the off chance none of the other migrations have been run yet.
if (runSd0Migrations) {
uint32_t numberOfUpdatedModels = BrickByBrickFix::UpdateBrickByBrickModelsToSd0();
Game::logger->Log("MasterServer", "%i models were updated from zlib to sd0.", numberOfUpdatedModels);
uint32_t numberOfTruncatedModels = BrickByBrickFix::TruncateBrokenBrickByBrickXml();
Game::logger->Log("MasterServer", "%i models were truncated from the database.", numberOfTruncatedModels);
}
} }
Migration MigrationRunner::LoadMigration(std::string path) { Migration MigrationRunner::LoadMigration(std::string path) {
@ -59,8 +77,6 @@ Migration MigrationRunner::LoadMigration(std::string path) {
std::ifstream file("./migrations/" + path); std::ifstream file("./migrations/" + path);
if (file.is_open()) { if (file.is_open()) {
std::hash<std::string> hash;
std::string line; std::string line;
std::string total = ""; std::string total = "";

View File

@ -31,6 +31,18 @@ public:
//! Destructor //! Destructor
~CDComponentsRegistryTable(void); ~CDComponentsRegistryTable(void);
//! Returns the table's name
/*!
\return The table name
*/
std::string GetName(void) const override;
//! Constructor
CDComponentsRegistryTable(void);
//! Destructor
~CDComponentsRegistryTable(void);
//! Returns the table's name //! Returns the table's name
/*! /*!
\return The table name \return The table name

View File

@ -52,12 +52,9 @@ std::vector<CDFeatureGating> CDFeatureGatingTable::Query(std::function<bool(CDFe
return data; return data;
} }
bool CDFeatureGatingTable::FeatureUnlocked(const std::string& feature) const bool CDFeatureGatingTable::FeatureUnlocked(const std::string& feature) const {
{ for (const auto& entry : entries) {
for (const auto& entry : entries) if (entry.featureName == feature) {
{
if (entry.featureName == feature)
{
return true; return true;
} }
} }

View File

@ -45,7 +45,7 @@ CDItemComponentTable::CDItemComponentTable(void) {
entry.offsetGroupID = tableData.getIntField(19, -1); entry.offsetGroupID = tableData.getIntField(19, -1);
entry.buildTypes = tableData.getIntField(20, -1); entry.buildTypes = tableData.getIntField(20, -1);
entry.reqPrecondition = tableData.getStringField(21, ""); entry.reqPrecondition = tableData.getStringField(21, "");
entry.animationFlag = tableData.getIntField(22, -1); entry.animationFlag = tableData.getIntField(22, 0);
entry.equipEffects = tableData.getIntField(23, -1); entry.equipEffects = tableData.getIntField(23, -1);
entry.readyForQA = tableData.getIntField(24, -1) == 1 ? true : false; entry.readyForQA = tableData.getIntField(24, -1) == 1 ? true : false;
entry.itemRating = tableData.getIntField(25, -1); entry.itemRating = tableData.getIntField(25, -1);
@ -123,7 +123,7 @@ const CDItemComponent & CDItemComponentTable::GetItemComponentByID(unsigned int
entry.offsetGroupID = tableData.getIntField(19, -1); entry.offsetGroupID = tableData.getIntField(19, -1);
entry.buildTypes = tableData.getIntField(20, -1); entry.buildTypes = tableData.getIntField(20, -1);
entry.reqPrecondition = tableData.getStringField(21, ""); entry.reqPrecondition = tableData.getStringField(21, "");
entry.animationFlag = tableData.getIntField(22, -1); entry.animationFlag = tableData.getIntField(22, 0);
entry.equipEffects = tableData.getIntField(23, -1); entry.equipEffects = tableData.getIntField(23, -1);
entry.readyForQA = tableData.getIntField(24, -1) == 1 ? true : false; entry.readyForQA = tableData.getIntField(24, -1) == 1 ? true : false;
entry.itemRating = tableData.getIntField(25, -1); entry.itemRating = tableData.getIntField(25, -1);

View File

@ -55,8 +55,7 @@ std::vector<CDItemSetSkills> CDItemSetSkillsTable::GetEntries(void) const {
return this->entries; return this->entries;
} }
std::vector<CDItemSetSkills> CDItemSetSkillsTable::GetBySkillID(unsigned int SkillSetID) std::vector<CDItemSetSkills> CDItemSetSkillsTable::GetBySkillID(unsigned int SkillSetID) {
{
std::vector<CDItemSetSkills> toReturn; std::vector<CDItemSetSkills> toReturn;
for (CDItemSetSkills entry : this->entries) { for (CDItemSetSkills entry : this->entries) {

View File

@ -60,14 +60,11 @@ std::vector<CDMissionTasks> CDMissionTasksTable::Query(std::function<bool(CDMiss
return data; return data;
} }
std::vector<CDMissionTasks*> CDMissionTasksTable::GetByMissionID(uint32_t missionID) std::vector<CDMissionTasks*> CDMissionTasksTable::GetByMissionID(uint32_t missionID) {
{
std::vector<CDMissionTasks*> tasks; std::vector<CDMissionTasks*> tasks;
for (auto& entry : this->entries) for (auto& entry : this->entries) {
{ if (entry.id == missionID) {
if (entry.id == missionID)
{
CDMissionTasks* task = const_cast<CDMissionTasks*>(&entry); CDMissionTasks* task = const_cast<CDMissionTasks*>(&entry);
tasks.push_back(task); tasks.push_back(task);

View File

@ -108,12 +108,9 @@ const std::vector<CDMissions>& CDMissionsTable::GetEntries(void) const {
return this->entries; return this->entries;
} }
const CDMissions* CDMissionsTable::GetPtrByMissionID(uint32_t missionID) const const CDMissions* CDMissionsTable::GetPtrByMissionID(uint32_t missionID) const {
{ for (const auto& entry : entries) {
for (const auto& entry : entries) if (entry.id == missionID) {
{
if (entry.id == missionID)
{
return const_cast<CDMissions*>(&entry); return const_cast<CDMissions*>(&entry);
} }
} }
@ -121,12 +118,9 @@ const CDMissions* CDMissionsTable::GetPtrByMissionID(uint32_t missionID) const
return &Default; return &Default;
} }
const CDMissions& CDMissionsTable::GetByMissionID(uint32_t missionID, bool& found) const const CDMissions& CDMissionsTable::GetByMissionID(uint32_t missionID, bool& found) const {
{ for (const auto& entry : entries) {
for (const auto& entry : entries) if (entry.id == missionID) {
{
if (entry.id == missionID)
{
found = true; found = true;
return entry; return entry;

View File

@ -8,23 +8,12 @@ CDRailActivatorComponentTable::CDRailActivatorComponentTable() {
entry.id = tableData.getIntField(0); entry.id = tableData.getIntField(0);
std::string startAnimation(tableData.getStringField(1, "")); entry.startAnimation = GeneralUtils::ASCIIToUTF16(tableData.getStringField(1, ""));
entry.startAnimation = GeneralUtils::ASCIIToUTF16(startAnimation); entry.loopAnimation = GeneralUtils::ASCIIToUTF16(tableData.getStringField(2, ""));
entry.stopAnimation = GeneralUtils::ASCIIToUTF16(tableData.getStringField(3, ""));
std::string loopAnimation(tableData.getStringField(2, "")); entry.startSound = GeneralUtils::ASCIIToUTF16(tableData.getStringField(4, ""));
entry.loopAnimation = GeneralUtils::ASCIIToUTF16(loopAnimation); entry.loopSound = GeneralUtils::ASCIIToUTF16(tableData.getStringField(5, ""));
entry.stopSound = GeneralUtils::ASCIIToUTF16(tableData.getStringField(6, ""));
std::string stopAnimation(tableData.getStringField(3, ""));
entry.stopAnimation = GeneralUtils::ASCIIToUTF16(stopAnimation);
std::string startSound(tableData.getStringField(4, ""));
entry.startSound = GeneralUtils::ASCIIToUTF16(startSound);
std::string loopSound(tableData.getStringField(5, ""));
entry.loopSound = GeneralUtils::ASCIIToUTF16(loopSound);
std::string stopSound(tableData.getStringField(6, ""));
entry.stopSound = GeneralUtils::ASCIIToUTF16(stopSound);
std::string loopEffectString(tableData.getStringField(7, "")); std::string loopEffectString(tableData.getStringField(7, ""));
entry.loopEffectID = EffectPairFromString(loopEffectString); entry.loopEffectID = EffectPairFromString(loopEffectString);

View File

@ -15,23 +15,19 @@ struct CDRarityTable {
unsigned int rarity; unsigned int rarity;
unsigned int RarityTableIndex; unsigned int RarityTableIndex;
friend bool operator> (const CDRarityTable& c1, const CDRarityTable& c2) friend bool operator> (const CDRarityTable& c1, const CDRarityTable& c2) {
{
return c1.rarity > c2.rarity; return c1.rarity > c2.rarity;
} }
friend bool operator>= (const CDRarityTable& c1, const CDRarityTable& c2) friend bool operator>= (const CDRarityTable& c1, const CDRarityTable& c2) {
{
return c1.rarity >= c2.rarity; return c1.rarity >= c2.rarity;
} }
friend bool operator< (const CDRarityTable& c1, const CDRarityTable& c2) friend bool operator< (const CDRarityTable& c1, const CDRarityTable& c2) {
{
return c1.rarity < c2.rarity; return c1.rarity < c2.rarity;
} }
friend bool operator<= (const CDRarityTable& c1, const CDRarityTable& c2) friend bool operator<= (const CDRarityTable& c1, const CDRarityTable& c2) {
{
return c1.rarity <= c2.rarity; return c1.rarity <= c2.rarity;
} }
}; };

View File

@ -68,7 +68,7 @@ std::vector<CDSkillBehavior> CDSkillBehaviorTable::Query(std::function<bool(CDSk
return data;*/ return data;*/
//Logger::LogDebug("CDSkillBehaviorTable", "The 'Query' function is no longer working! Please use GetSkillByID instead!\n"); //Logger::LogDebug("CDSkillBehaviorTable", "The 'Query' function is no longer working! Please use GetSkillByID instead!");
std::vector<CDSkillBehavior> data; //So MSVC shuts up std::vector<CDSkillBehavior> data; //So MSVC shuts up
return data; return data;
} }

View File

@ -65,8 +65,7 @@ std::string CDZoneTableTable::GetName(void) const {
const CDZoneTable* CDZoneTableTable::Query(unsigned int zoneID) { const CDZoneTable* CDZoneTableTable::Query(unsigned int zoneID) {
const auto& iter = m_Entries.find(zoneID); const auto& iter = m_Entries.find(zoneID);
if (iter != m_Entries.end()) if (iter != m_Entries.end()) {
{
return &iter->second; return &iter->second;
} }

View File

@ -56,4 +56,4 @@ endforeach()
add_library(dGame STATIC ${DGAME_SOURCES}) add_library(dGame STATIC ${DGAME_SOURCES})
target_link_libraries(dGame dDatabase) target_link_libraries(dGame dDatabase Recast Detour)

View File

@ -78,8 +78,7 @@ Character::~Character() {
m_Doc = nullptr; m_Doc = nullptr;
} }
void Character::UpdateFromDatabase() void Character::UpdateFromDatabase() {
{
sql::PreparedStatement* stmt = Database::CreatePreppedStmt( sql::PreparedStatement* stmt = Database::CreatePreppedStmt(
"SELECT name, pending_name, needs_rename, prop_clone_id, permission_map FROM charinfo WHERE id=? LIMIT 1;" "SELECT name, pending_name, needs_rename, prop_clone_id, permission_map FROM charinfo WHERE id=? LIMIT 1;"
); );
@ -140,16 +139,16 @@ void Character::DoQuickXMLDataParse() {
if (!m_Doc) return; if (!m_Doc) return;
if (m_Doc->Parse(m_XMLData.c_str(), m_XMLData.size()) == 0) { if (m_Doc->Parse(m_XMLData.c_str(), m_XMLData.size()) == 0) {
Game::logger->Log("Character", "Loaded xmlData for character %s (%i)!\n", m_Name.c_str(), m_ID); Game::logger->Log("Character", "Loaded xmlData for character %s (%i)!", m_Name.c_str(), m_ID);
} else { } else {
Game::logger->Log("Character", "Failed to load xmlData!\n"); Game::logger->Log("Character", "Failed to load xmlData!");
//Server::rakServer->CloseConnection(m_ParentUser->GetSystemAddress(), true); //Server::rakServer->CloseConnection(m_ParentUser->GetSystemAddress(), true);
return; return;
} }
tinyxml2::XMLElement* mf = m_Doc->FirstChildElement("obj")->FirstChildElement("mf"); tinyxml2::XMLElement* mf = m_Doc->FirstChildElement("obj")->FirstChildElement("mf");
if (!mf) { if (!mf) {
Game::logger->Log("Character", "Failed to find mf tag!\n"); Game::logger->Log("Character", "Failed to find mf tag!");
return; return;
} }
@ -168,19 +167,18 @@ void Character::DoQuickXMLDataParse() {
tinyxml2::XMLElement* inv = m_Doc->FirstChildElement("obj")->FirstChildElement("inv"); tinyxml2::XMLElement* inv = m_Doc->FirstChildElement("obj")->FirstChildElement("inv");
if (!inv) { if (!inv) {
Game::logger->Log("Character", "Char has no inv!\n"); Game::logger->Log("Character", "Char has no inv!");
return; return;
} }
tinyxml2::XMLElement* bag = inv->FirstChildElement("items")->FirstChildElement("in"); tinyxml2::XMLElement* bag = inv->FirstChildElement("items")->FirstChildElement("in");
if (!bag) { if (!bag) {
Game::logger->Log("Character", "Couldn't find bag0!\n"); Game::logger->Log("Character", "Couldn't find bag0!");
return; return;
} }
while (bag != nullptr) while (bag != nullptr) {
{
auto* sib = bag->FirstChildElement(); auto* sib = bag->FirstChildElement();
while (sib != nullptr) { while (sib != nullptr) {
@ -279,14 +277,12 @@ void Character::DoQuickXMLDataParse() {
} }
} }
void Character::UnlockEmote(int emoteID) void Character::UnlockEmote(int emoteID) {
{
m_UnlockedEmotes.push_back(emoteID); m_UnlockedEmotes.push_back(emoteID);
GameMessages::SendSetEmoteLockState(EntityManager::Instance()->GetEntity(m_ObjectID), false, emoteID); GameMessages::SendSetEmoteLockState(EntityManager::Instance()->GetEntity(m_ObjectID), false, emoteID);
} }
void Character::SetBuildMode(bool buildMode) void Character::SetBuildMode(bool buildMode) {
{
m_BuildMode = buildMode; m_BuildMode = buildMode;
auto* controller = dZoneManager::Instance()->GetZoneControlObject(); auto* controller = dZoneManager::Instance()->GetZoneControlObject();
@ -305,9 +301,9 @@ void Character::SaveXMLToDatabase() {
character->SetAttribute("gm", m_GMLevel); character->SetAttribute("gm", m_GMLevel);
character->SetAttribute("cc", m_Coins); character->SetAttribute("cc", m_Coins);
// lzid garbage, binary concat of zoneID, zoneInstance and zoneClone
if (Game::server->GetZoneID() != 0) {
auto zoneInfo = dZoneManager::Instance()->GetZone()->GetZoneID(); auto zoneInfo = dZoneManager::Instance()->GetZone()->GetZoneID();
// lzid garbage, binary concat of zoneID, zoneInstance and zoneClone
if (zoneInfo.GetMapID() != 0 && zoneInfo.GetCloneID() == 0) {
uint64_t lzidConcat = zoneInfo.GetCloneID(); uint64_t lzidConcat = zoneInfo.GetCloneID();
lzidConcat = (lzidConcat << 16) | uint16_t(zoneInfo.GetInstanceID()); lzidConcat = (lzidConcat << 16) | uint16_t(zoneInfo.GetInstanceID());
lzidConcat = (lzidConcat << 16) | uint16_t(zoneInfo.GetMapID()); lzidConcat = (lzidConcat << 16) | uint16_t(zoneInfo.GetMapID());
@ -359,7 +355,7 @@ void Character::SaveXMLToDatabase() {
//Call upon the entity to update our xmlDoc: //Call upon the entity to update our xmlDoc:
if (!m_OurEntity) { if (!m_OurEntity) {
Game::logger->Log("Character", "We didn't have an entity set while saving! CHARACTER WILL NOT BE SAVED!\n"); Game::logger->Log("Character", "We didn't have an entity set while saving! CHARACTER WILL NOT BE SAVED!");
return; return;
} }
@ -380,7 +376,7 @@ void Character::SaveXMLToDatabase() {
//For metrics, log the time it took to save: //For metrics, log the time it took to save:
auto end = std::chrono::system_clock::now(); auto end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed = end - start; std::chrono::duration<double> elapsed = end - start;
Game::logger->Log("Character", "Saved character to Database in: %fs\n", elapsed.count()); Game::logger->Log("Character", "Saved character to Database in: %fs", elapsed.count());
delete printer; delete printer;
} }
@ -389,17 +385,14 @@ void Character::SetPlayerFlag(const uint32_t flagId, const bool value) {
// If the flag is already set, we don't have to recalculate it // If the flag is already set, we don't have to recalculate it
if (GetPlayerFlag(flagId) == value) return; if (GetPlayerFlag(flagId) == value) return;
if (value) if (value) {
{
// Update the mission component: // Update the mission component:
auto* player = EntityManager::Instance()->GetEntity(m_ObjectID); auto* player = EntityManager::Instance()->GetEntity(m_ObjectID);
if (player != nullptr) if (player != nullptr) {
{
auto* missionComponent = player->GetComponent<MissionComponent>(); auto* missionComponent = player->GetComponent<MissionComponent>();
if (missionComponent != nullptr) if (missionComponent != nullptr) {
{
missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_PLAYER_FLAG, flagId); missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_PLAYER_FLAG, flagId);
} }
} }
@ -413,8 +406,7 @@ void Character::SetPlayerFlag(const uint32_t flagId, const bool value) {
auto it = m_PlayerFlags.find(flagIndex); auto it = m_PlayerFlags.find(flagIndex);
// Check if flag index exists // Check if flag index exists
if (it != m_PlayerFlags.end()) if (it != m_PlayerFlags.end()) {
{
// Update the value // Update the value
if (value) { if (value) {
it->second |= shiftedValue; it->second |= shiftedValue;
@ -458,8 +450,7 @@ void Character::SetRetroactiveFlags() {
} }
} }
void Character::SaveXmlRespawnCheckpoints() void Character::SaveXmlRespawnCheckpoints() {
{
//Export our respawn points: //Export our respawn points:
auto* points = m_Doc->FirstChildElement("obj")->FirstChildElement("res"); auto* points = m_Doc->FirstChildElement("obj")->FirstChildElement("res");
if (!points) { if (!points) {
@ -480,8 +471,7 @@ void Character::SaveXmlRespawnCheckpoints()
} }
} }
void Character::LoadXmlRespawnCheckpoints() void Character::LoadXmlRespawnCheckpoints() {
{
m_WorldRespawnCheckpoints.clear(); m_WorldRespawnCheckpoints.clear();
auto* points = m_Doc->FirstChildElement("obj")->FirstChildElement("res"); auto* points = m_Doc->FirstChildElement("obj")->FirstChildElement("res");
@ -490,8 +480,7 @@ void Character::LoadXmlRespawnCheckpoints()
} }
auto* r = points->FirstChildElement("r"); auto* r = points->FirstChildElement("r");
while (r != nullptr) while (r != nullptr) {
{
int32_t map = 0; int32_t map = 0;
NiPoint3 point = NiPoint3::ZERO; NiPoint3 point = NiPoint3::ZERO;
@ -507,8 +496,7 @@ void Character::LoadXmlRespawnCheckpoints()
} }
void Character::OnZoneLoad() void Character::OnZoneLoad() {
{
if (m_OurEntity == nullptr) { if (m_OurEntity == nullptr) {
return; return;
} }
@ -550,23 +538,19 @@ void Character::OnZoneLoad()
} }
} }
PermissionMap Character::GetPermissionMap() const PermissionMap Character::GetPermissionMap() const {
{
return m_PermissionMap; return m_PermissionMap;
} }
bool Character::HasPermission(PermissionMap permission) const bool Character::HasPermission(PermissionMap permission) const {
{
return (static_cast<uint64_t>(m_PermissionMap) & static_cast<uint64_t>(permission)) != 0; return (static_cast<uint64_t>(m_PermissionMap) & static_cast<uint64_t>(permission)) != 0;
} }
void Character::SetRespawnPoint(LWOMAPID map, const NiPoint3& point) void Character::SetRespawnPoint(LWOMAPID map, const NiPoint3& point) {
{
m_WorldRespawnCheckpoints[map] = point; m_WorldRespawnCheckpoints[map] = point;
} }
const NiPoint3& Character::GetRespawnPoint(LWOMAPID map) const const NiPoint3& Character::GetRespawnPoint(LWOMAPID map) const {
{
const auto& pair = m_WorldRespawnCheckpoints.find(map); const auto& pair = m_WorldRespawnCheckpoints.find(map);
if (pair == m_WorldRespawnCheckpoints.end()) return NiPoint3::ZERO; if (pair == m_WorldRespawnCheckpoints.end()) return NiPoint3::ZERO;
@ -575,8 +559,7 @@ const NiPoint3& Character::GetRespawnPoint(LWOMAPID map) const
} }
void Character::SetCoins(int64_t newCoins, eLootSourceType lootSource) { void Character::SetCoins(int64_t newCoins, eLootSourceType lootSource) {
if (newCoins < 0) if (newCoins < 0) {
{
newCoins = 0; newCoins = 0;
} }
@ -585,21 +568,18 @@ void Character::SetCoins(int64_t newCoins, eLootSourceType lootSource) {
GameMessages::SendSetCurrency(EntityManager::Instance()->GetEntity(m_ObjectID), m_Coins, 0, 0, 0, 0, true, lootSource); GameMessages::SendSetCurrency(EntityManager::Instance()->GetEntity(m_ObjectID), m_Coins, 0, 0, 0, 0, true, lootSource);
} }
bool Character::HasBeenToWorld(LWOMAPID mapID) const bool Character::HasBeenToWorld(LWOMAPID mapID) const {
{
return m_WorldRespawnCheckpoints.find(mapID) != m_WorldRespawnCheckpoints.end(); return m_WorldRespawnCheckpoints.find(mapID) != m_WorldRespawnCheckpoints.end();
} }
void Character::SendMuteNotice() const void Character::SendMuteNotice() const {
{
if (!m_ParentUser->GetIsMuted()) return; if (!m_ParentUser->GetIsMuted()) return;
time_t expire = m_ParentUser->GetMuteExpire(); time_t expire = m_ParentUser->GetMuteExpire();
char buffer[32] = "brought up for review.\0"; char buffer[32] = "brought up for review.\0";
if (expire != 1) if (expire != 1) {
{
std::tm* ptm = std::localtime(&expire); std::tm* ptm = std::localtime(&expire);
// Format: Mo, 15.06.2009 20:20:00 // Format: Mo, 15.06.2009 20:20:00
std::strftime(buffer, 32, "%a, %d.%m.%Y %H:%M:%S", ptm); std::strftime(buffer, 32, "%a, %d.%m.%Y %H:%M:%S", ptm);

View File

@ -425,6 +425,18 @@ public:
*/ */
const std::vector<LOT>& GetEquippedItems() const { return m_EquippedItems; } const std::vector<LOT>& GetEquippedItems() const { return m_EquippedItems; }
/**
* @brief Get the flying state
* @return value of the flying state
*/
bool GetIsFlying() { return m_IsFlying; }
/**
* @brief Set the value of the flying state
* @param isFlying the flying state
*/
void SetIsFlying(bool isFlying) { m_IsFlying = isFlying; }
private: private:
/** /**
* The ID of this character. First 32 bits of the ObjectID. * The ID of this character. First 32 bits of the ObjectID.
@ -621,6 +633,11 @@ private:
*/ */
std::string m_TargetScene; std::string m_TargetScene;
/**
* Bool that tracks the flying state of the user.
*/
bool m_IsFlying = false;
/** /**
* Queries the character XML and updates all the fields of this object * Queries the character XML and updates all the fields of this object
* NOTE: quick as there's no DB lookups * NOTE: quick as there's no DB lookups

File diff suppressed because it is too large Load Diff

View File

@ -338,12 +338,10 @@ protected:
*/ */
template<typename T> template<typename T>
bool Entity::TryGetComponent(const int32_t componentId, T*& component) const bool Entity::TryGetComponent(const int32_t componentId, T*& component) const {
{
const auto& index = m_Components.find(componentId); const auto& index = m_Components.find(componentId);
if (index == m_Components.end()) if (index == m_Components.end()) {
{
component = nullptr; component = nullptr;
return false; return false;
@ -355,26 +353,22 @@ bool Entity::TryGetComponent(const int32_t componentId, T*& component) const
} }
template <typename T> template <typename T>
T* Entity::GetComponent() const T* Entity::GetComponent() const {
{
return dynamic_cast<T*>(GetComponent(T::ComponentType)); return dynamic_cast<T*>(GetComponent(T::ComponentType));
} }
template<typename T> template<typename T>
const T& Entity::GetVar(const std::u16string& name) const const T& Entity::GetVar(const std::u16string& name) const {
{
auto* data = GetVarData(name); auto* data = GetVarData(name);
if (data == nullptr) if (data == nullptr) {
{
return LDFData<T>::Default; return LDFData<T>::Default;
} }
auto* typed = dynamic_cast<LDFData<T>*>(data); auto* typed = dynamic_cast<LDFData<T>*>(data);
if (typed == nullptr) if (typed == nullptr) {
{
return LDFData<T>::Default; return LDFData<T>::Default;
} }
@ -382,14 +376,12 @@ const T& Entity::GetVar(const std::u16string& name) const
} }
template<typename T> template<typename T>
T Entity::GetVarAs(const std::u16string& name) const T Entity::GetVarAs(const std::u16string& name) const {
{
const auto data = GetVarAsString(name); const auto data = GetVarAsString(name);
T value; T value;
if (!GeneralUtils::TryParse(data, value)) if (!GeneralUtils::TryParse(data, value)) {
{
return LDFData<T>::Default; return LDFData<T>::Default;
} }
@ -397,12 +389,10 @@ T Entity::GetVarAs(const std::u16string& name) const
} }
template<typename T> template<typename T>
void Entity::SetVar(const std::u16string& name, T value) void Entity::SetVar(const std::u16string& name, T value) {
{
auto* data = GetVarData(name); auto* data = GetVarData(name);
if (data == nullptr) if (data == nullptr) {
{
auto* data = new LDFData<T>(name, value); auto* data = new LDFData<T>(name, value);
m_Settings.push_back(data); m_Settings.push_back(data);
@ -412,8 +402,7 @@ void Entity::SetVar(const std::u16string& name, T value)
auto* typed = dynamic_cast<LDFData<T>*>(data); auto* typed = dynamic_cast<LDFData<T>*>(data);
if (typed == nullptr) if (typed == nullptr) {
{
return; return;
} }

View File

@ -110,8 +110,7 @@ Entity* EntityManager::CreateEntity(EntityInfo info, User* user, Entity* parentE
// Check if the entitty if a player, in case use the extended player entity class // Check if the entitty if a player, in case use the extended player entity class
if (user != nullptr) { if (user != nullptr) {
entity = new Player(id, info, user, parentEntity); entity = new Player(id, info, user, parentEntity);
} } else {
else {
entity = new Entity(id, info, parentEntity); entity = new Entity(id, info, parentEntity);
} }
@ -165,104 +164,74 @@ void EntityManager::UpdateEntities(const float deltaTime) {
e.second->Update(deltaTime); e.second->Update(deltaTime);
} }
for (const auto entityId : m_EntitiesToSerialize) for (auto entry = m_EntitiesToSerialize.begin(); entry != m_EntitiesToSerialize.end(); entry++) {
{ auto* entity = GetEntity(*entry);
auto* entity = GetEntity(entityId);
if (entity == nullptr) continue; if (entity == nullptr) continue;
m_SerializationCounter++; m_SerializationCounter++;
RakNet::BitStream stream; RakNet::BitStream stream;
stream.Write(static_cast<char>(ID_REPLICA_MANAGER_SERIALIZE)); stream.Write(static_cast<char>(ID_REPLICA_MANAGER_SERIALIZE));
stream.Write(static_cast<unsigned short>(entity->GetNetworkId())); stream.Write(static_cast<unsigned short>(entity->GetNetworkId()));
entity->WriteBaseReplicaData(&stream, PACKET_TYPE_SERIALIZATION); entity->WriteBaseReplicaData(&stream, PACKET_TYPE_SERIALIZATION);
entity->WriteComponents(&stream, PACKET_TYPE_SERIALIZATION); entity->WriteComponents(&stream, PACKET_TYPE_SERIALIZATION);
if (entity->GetIsGhostingCandidate()) if (entity->GetIsGhostingCandidate()) {
{ for (auto* player : Player::GetAllPlayers()) {
for (auto* player : Player::GetAllPlayers()) if (player->IsObserved(*entry)) {
{
if (player->IsObserved(entityId))
{
Game::server->Send(&stream, player->GetSystemAddress(), false); Game::server->Send(&stream, player->GetSystemAddress(), false);
} }
} }
} } else {
else
{
Game::server->Send(&stream, UNASSIGNED_SYSTEM_ADDRESS, true); Game::server->Send(&stream, UNASSIGNED_SYSTEM_ADDRESS, true);
} }
} }
m_EntitiesToSerialize.clear(); m_EntitiesToSerialize.clear();
for (const auto& entry : m_EntitiesToKill) for (auto entry = m_EntitiesToKill.begin(); entry != m_EntitiesToKill.end(); entry++) {
{ auto* entity = GetEntity(*entry);
auto* entity = GetEntity(entry);
if (!entity) continue; if (!entity) continue;
if (entity->GetScheduledKiller()) if (entity->GetScheduledKiller()) {
{
entity->Smash(entity->GetScheduledKiller()->GetObjectID(), SILENT); entity->Smash(entity->GetScheduledKiller()->GetObjectID(), SILENT);
} } else {
else
{
entity->Smash(LWOOBJID_EMPTY, SILENT); entity->Smash(LWOOBJID_EMPTY, SILENT);
} }
} }
m_EntitiesToKill.clear(); m_EntitiesToKill.clear();
for (const auto entry : m_EntitiesToDelete) for (auto entry = m_EntitiesToDelete.begin(); entry != m_EntitiesToDelete.end(); entry++) {
{
// Get all this info first before we delete the player. // Get all this info first before we delete the player.
auto entityToDelete = GetEntity(entry); auto entityToDelete = GetEntity(*entry);
auto networkIdToErase = entityToDelete->GetNetworkId(); auto networkIdToErase = entityToDelete->GetNetworkId();
const auto& ghostingToDelete = std::find(m_EntitiesToGhost.begin(), m_EntitiesToGhost.end(), entityToDelete); const auto& ghostingToDelete = std::find(m_EntitiesToGhost.begin(), m_EntitiesToGhost.end(), entityToDelete);
if (entityToDelete) if (entityToDelete) {
{
// If we are a player run through the player destructor. // If we are a player run through the player destructor.
if (entityToDelete->IsPlayer()) if (entityToDelete->IsPlayer()) {
{
delete dynamic_cast<Player*>(entityToDelete); delete dynamic_cast<Player*>(entityToDelete);
} } else {
else
{
delete entityToDelete; delete entityToDelete;
} }
entityToDelete = nullptr; entityToDelete = nullptr;
if (networkIdToErase != 0) m_LostNetworkIds.push(networkIdToErase);
if (networkIdToErase != 0)
{
m_LostNetworkIds.push(networkIdToErase);
}
} }
if (ghostingToDelete != m_EntitiesToGhost.end()) if (ghostingToDelete != m_EntitiesToGhost.end()) m_EntitiesToGhost.erase(ghostingToDelete);
{
m_EntitiesToGhost.erase(ghostingToDelete); m_Entities.erase(*entry);
} }
m_Entities.erase(entry);
}
m_EntitiesToDelete.clear(); m_EntitiesToDelete.clear();
} }
Entity* EntityManager::GetEntity(const LWOOBJID& objectId) const { Entity* EntityManager::GetEntity(const LWOOBJID& objectId) const {
const auto& index = m_Entities.find(objectId); const auto& index = m_Entities.find(objectId);
if (index == m_Entities.end()) if (index == m_Entities.end()) {
{
return nullptr; return nullptr;
} }
@ -303,18 +272,15 @@ std::vector<Entity *> EntityManager::GetEntitiesByLOT(const LOT &lot) const {
return entities; return entities;
} }
Entity* EntityManager::GetZoneControlEntity() const Entity* EntityManager::GetZoneControlEntity() const {
{
return m_ZoneControlEntity; return m_ZoneControlEntity;
} }
Entity* EntityManager::GetSpawnPointEntity(const std::string& spawnName) const Entity* EntityManager::GetSpawnPointEntity(const std::string& spawnName) const {
{
// Lookup the spawn point entity in the map // Lookup the spawn point entity in the map
const auto& spawnPoint = m_SpawnPoints.find(spawnName); const auto& spawnPoint = m_SpawnPoints.find(spawnName);
if (spawnPoint == m_SpawnPoints.end()) if (spawnPoint == m_SpawnPoints.end()) {
{
return nullptr; return nullptr;
} }
@ -322,23 +288,18 @@ Entity* EntityManager::GetSpawnPointEntity(const std::string& spawnName) const
return GetEntity(spawnPoint->second); return GetEntity(spawnPoint->second);
} }
const std::unordered_map<std::string, LWOOBJID>& EntityManager::GetSpawnPointEntities() const const std::unordered_map<std::string, LWOOBJID>& EntityManager::GetSpawnPointEntities() const {
{
return m_SpawnPoints; return m_SpawnPoints;
} }
void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr, const bool skipChecks) { void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr, const bool skipChecks) {
if (entity->GetNetworkId() == 0) if (entity->GetNetworkId() == 0) {
{
uint16_t networkId; uint16_t networkId;
if (!m_LostNetworkIds.empty()) if (!m_LostNetworkIds.empty()) {
{
networkId = m_LostNetworkIds.top(); networkId = m_LostNetworkIds.top();
m_LostNetworkIds.pop(); m_LostNetworkIds.pop();
} } else {
else
{
networkId = ++m_NetworkIdCounter; networkId = ++m_NetworkIdCounter;
} }
@ -347,18 +308,15 @@ void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr
const auto checkGhosting = entity->GetIsGhostingCandidate(); const auto checkGhosting = entity->GetIsGhostingCandidate();
if (checkGhosting) if (checkGhosting) {
{
const auto& iter = std::find(m_EntitiesToGhost.begin(), m_EntitiesToGhost.end(), entity); const auto& iter = std::find(m_EntitiesToGhost.begin(), m_EntitiesToGhost.end(), entity);
if (iter == m_EntitiesToGhost.end()) if (iter == m_EntitiesToGhost.end()) {
{
m_EntitiesToGhost.push_back(entity); m_EntitiesToGhost.push_back(entity);
} }
} }
if (checkGhosting && sysAddr == UNASSIGNED_SYSTEM_ADDRESS) if (checkGhosting && sysAddr == UNASSIGNED_SYSTEM_ADDRESS) {
{
CheckGhosting(entity); CheckGhosting(entity);
return; return;
@ -375,38 +333,26 @@ void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr
entity->WriteBaseReplicaData(&stream, PACKET_TYPE_CONSTRUCTION); entity->WriteBaseReplicaData(&stream, PACKET_TYPE_CONSTRUCTION);
entity->WriteComponents(&stream, PACKET_TYPE_CONSTRUCTION); entity->WriteComponents(&stream, PACKET_TYPE_CONSTRUCTION);
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) {
{ if (skipChecks) {
if (skipChecks)
{
Game::server->Send(&stream, UNASSIGNED_SYSTEM_ADDRESS, true); Game::server->Send(&stream, UNASSIGNED_SYSTEM_ADDRESS, true);
} } else {
else for (auto* player : Player::GetAllPlayers()) {
{ if (player->GetPlayerReadyForUpdates()) {
for (auto* player : Player::GetAllPlayers())
{
if (player->GetPlayerReadyForUpdates())
{
Game::server->Send(&stream, player->GetSystemAddress(), false); Game::server->Send(&stream, player->GetSystemAddress(), false);
} } else {
else
{
player->AddLimboConstruction(entity->GetObjectID()); player->AddLimboConstruction(entity->GetObjectID());
} }
} }
} }
} } else {
else
{
Game::server->Send(&stream, sysAddr, false); Game::server->Send(&stream, sysAddr, false);
} }
// PacketUtils::SavePacket("[24]_"+std::to_string(entity->GetObjectID()) + "_" + std::to_string(m_SerializationCounter) + ".bin", (char*)stream.GetData(), stream.GetNumberOfBytesUsed()); // PacketUtils::SavePacket("[24]_"+std::to_string(entity->GetObjectID()) + "_" + std::to_string(m_SerializationCounter) + ".bin", (char*)stream.GetData(), stream.GetNumberOfBytesUsed());
if (entity->IsPlayer()) if (entity->IsPlayer()) {
{ if (entity->GetGMLevel() > GAME_MASTER_LEVEL_CIVILIAN) {
if (entity->GetGMLevel() > GAME_MASTER_LEVEL_CIVILIAN)
{
GameMessages::SendToggleGMInvis(entity->GetObjectID(), true, sysAddr); GameMessages::SendToggleGMInvis(entity->GetObjectID(), true, sysAddr);
} }
} }
@ -426,8 +372,7 @@ void EntityManager::ConstructAllEntities(const SystemAddress& sysAddr) {
} }
void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr) { void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr) {
if (entity->GetNetworkId() == 0) if (entity->GetNetworkId() == 0) {
{
return; return;
} }
@ -438,23 +383,19 @@ void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr)
Game::server->Send(&stream, sysAddr, sysAddr == UNASSIGNED_SYSTEM_ADDRESS); Game::server->Send(&stream, sysAddr, sysAddr == UNASSIGNED_SYSTEM_ADDRESS);
for (auto* player : Player::GetAllPlayers()) for (auto* player : Player::GetAllPlayers()) {
{ if (!player->GetPlayerReadyForUpdates()) {
if (!player->GetPlayerReadyForUpdates())
{
player->RemoveLimboConstruction(entity->GetObjectID()); player->RemoveLimboConstruction(entity->GetObjectID());
} }
} }
} }
void EntityManager::SerializeEntity(Entity* entity) { void EntityManager::SerializeEntity(Entity* entity) {
if (entity->GetNetworkId() == 0) if (entity->GetNetworkId() == 0) {
{
return; return;
} }
if (std::find(m_EntitiesToSerialize.begin(), m_EntitiesToSerialize.end(), entity->GetObjectID()) == m_EntitiesToSerialize.end()) if (std::find(m_EntitiesToSerialize.begin(), m_EntitiesToSerialize.end(), entity->GetObjectID()) == m_EntitiesToSerialize.end()) {
{
m_EntitiesToSerialize.push_back(entity->GetObjectID()); m_EntitiesToSerialize.push_back(entity->GetObjectID());
} }
@ -467,44 +408,35 @@ void EntityManager::DestructAllEntities(const SystemAddress& sysAddr) {
} }
} }
void EntityManager::SetGhostDistanceMax(float value) void EntityManager::SetGhostDistanceMax(float value) {
{
m_GhostDistanceMaxSquared = value * value; m_GhostDistanceMaxSquared = value * value;
} }
float EntityManager::GetGhostDistanceMax() const float EntityManager::GetGhostDistanceMax() const {
{
return std::sqrt(m_GhostDistanceMaxSquared); return std::sqrt(m_GhostDistanceMaxSquared);
} }
void EntityManager::SetGhostDistanceMin(float value) void EntityManager::SetGhostDistanceMin(float value) {
{
m_GhostDistanceMinSqaured = value * value; m_GhostDistanceMinSqaured = value * value;
} }
float EntityManager::GetGhostDistanceMin() const float EntityManager::GetGhostDistanceMin() const {
{
return std::sqrt(m_GhostDistanceMinSqaured); return std::sqrt(m_GhostDistanceMinSqaured);
} }
void EntityManager::QueueGhostUpdate(LWOOBJID playerID) void EntityManager::QueueGhostUpdate(LWOOBJID playerID) {
{
const auto& iter = std::find(m_PlayersToUpdateGhosting.begin(), m_PlayersToUpdateGhosting.end(), playerID); const auto& iter = std::find(m_PlayersToUpdateGhosting.begin(), m_PlayersToUpdateGhosting.end(), playerID);
if (iter == m_PlayersToUpdateGhosting.end()) if (iter == m_PlayersToUpdateGhosting.end()) {
{
m_PlayersToUpdateGhosting.push_back(playerID); m_PlayersToUpdateGhosting.push_back(playerID);
} }
} }
void EntityManager::UpdateGhosting() void EntityManager::UpdateGhosting() {
{ for (const auto playerID : m_PlayersToUpdateGhosting) {
for (const auto playerID : m_PlayersToUpdateGhosting)
{
auto* player = Player::GetPlayer(playerID); auto* player = Player::GetPlayer(playerID);
if (player == nullptr) if (player == nullptr) {
{
continue; continue;
} }
@ -514,25 +446,21 @@ void EntityManager::UpdateGhosting()
m_PlayersToUpdateGhosting.clear(); m_PlayersToUpdateGhosting.clear();
} }
void EntityManager::UpdateGhosting(Player* player) void EntityManager::UpdateGhosting(Player* player) {
{ if (player == nullptr) {
if (player == nullptr)
{
return; return;
} }
auto* missionComponent = player->GetComponent<MissionComponent>(); auto* missionComponent = player->GetComponent<MissionComponent>();
if (missionComponent == nullptr) if (missionComponent == nullptr) {
{
return; return;
} }
const auto& referencePoint = player->GetGhostReferencePoint(); const auto& referencePoint = player->GetGhostReferencePoint();
const auto isOverride = player->GetGhostOverride(); const auto isOverride = player->GetGhostOverride();
for (auto* entity : m_EntitiesToGhost) for (auto* entity : m_EntitiesToGhost) {
{
const auto isAudioEmitter = entity->GetLOT() == 6368; const auto isAudioEmitter = entity->GetLOT() == 6368;
const auto& entityPoint = entity->GetPosition(); const auto& entityPoint = entity->GetPosition();
@ -546,30 +474,24 @@ void EntityManager::UpdateGhosting(Player* player)
auto ghostingDistanceMax = m_GhostDistanceMaxSquared; auto ghostingDistanceMax = m_GhostDistanceMaxSquared;
auto ghostingDistanceMin = m_GhostDistanceMinSqaured; auto ghostingDistanceMin = m_GhostDistanceMinSqaured;
if (isAudioEmitter) if (isAudioEmitter) {
{
ghostingDistanceMax = ghostingDistanceMin; ghostingDistanceMax = ghostingDistanceMin;
} }
if (observed && distance > ghostingDistanceMax && !isOverride) if (observed && distance > ghostingDistanceMax && !isOverride) {
{
player->GhostEntity(id); player->GhostEntity(id);
DestructEntity(entity, player->GetSystemAddress()); DestructEntity(entity, player->GetSystemAddress());
entity->SetObservers(entity->GetObservers() - 1); entity->SetObservers(entity->GetObservers() - 1);
} } else if (!observed && ghostingDistanceMin > distance) {
else if (!observed && ghostingDistanceMin > distance)
{
// Check collectables, don't construct if it has been collected // Check collectables, don't construct if it has been collected
uint32_t collectionId = entity->GetCollectibleID(); uint32_t collectionId = entity->GetCollectibleID();
if (collectionId != 0) if (collectionId != 0) {
{
collectionId = static_cast<uint32_t>(collectionId) + static_cast<uint32_t>(Game::server->GetZoneID() << 8); collectionId = static_cast<uint32_t>(collectionId) + static_cast<uint32_t>(Game::server->GetZoneID() << 8);
if (missionComponent->HasCollectible(collectionId)) if (missionComponent->HasCollectible(collectionId)) {
{
continue; continue;
} }
} }
@ -583,10 +505,8 @@ void EntityManager::UpdateGhosting(Player* player)
} }
} }
void EntityManager::CheckGhosting(Entity* entity) void EntityManager::CheckGhosting(Entity* entity) {
{ if (entity == nullptr) {
if (entity == nullptr)
{
return; return;
} }
@ -597,8 +517,7 @@ void EntityManager::CheckGhosting(Entity* entity)
const auto isAudioEmitter = entity->GetLOT() == 6368; const auto isAudioEmitter = entity->GetLOT() == 6368;
for (auto* player : Player::GetAllPlayers()) for (auto* player : Player::GetAllPlayers()) {
{
const auto& entityPoint = player->GetGhostReferencePoint(); const auto& entityPoint = player->GetGhostReferencePoint();
const int32_t id = entity->GetObjectID(); const int32_t id = entity->GetObjectID();
@ -607,16 +526,13 @@ void EntityManager::CheckGhosting(Entity* entity)
const auto distance = NiPoint3::DistanceSquared(referencePoint, entityPoint); const auto distance = NiPoint3::DistanceSquared(referencePoint, entityPoint);
if (observed && distance > ghostingDistanceMax) if (observed && distance > ghostingDistanceMax) {
{
player->GhostEntity(id); player->GhostEntity(id);
DestructEntity(entity, player->GetSystemAddress()); DestructEntity(entity, player->GetSystemAddress());
entity->SetObservers(entity->GetObservers() - 1); entity->SetObservers(entity->GetObservers() - 1);
} } else if (!observed && ghostingDistanceMin > distance) {
else if (!observed && ghostingDistanceMin > distance)
{
player->ObserveEntity(id); player->ObserveEntity(id);
ConstructEntity(entity, player->GetSystemAddress()); ConstructEntity(entity, player->GetSystemAddress());
@ -626,12 +542,9 @@ void EntityManager::CheckGhosting(Entity* entity)
} }
} }
Entity* EntityManager::GetGhostCandidate(int32_t id) Entity* EntityManager::GetGhostCandidate(int32_t id) {
{ for (auto* entity : m_EntitiesToGhost) {
for (auto* entity : m_EntitiesToGhost) if (entity->GetObjectID() == id) {
{
if (entity->GetObjectID() == id)
{
return entity; return entity;
} }
} }
@ -639,8 +552,7 @@ Entity* EntityManager::GetGhostCandidate(int32_t id)
return nullptr; return nullptr;
} }
bool EntityManager::GetGhostingEnabled() const bool EntityManager::GetGhostingEnabled() const {
{
return m_GhostingEnabled; return m_GhostingEnabled;
} }
@ -662,18 +574,15 @@ void EntityManager::ScheduleForKill(Entity* entity) {
const auto objectId = entity->GetObjectID(); const auto objectId = entity->GetObjectID();
if (std::count(m_EntitiesToKill.begin(), m_EntitiesToKill.end(), objectId)) if (std::count(m_EntitiesToKill.begin(), m_EntitiesToKill.end(), objectId)) {
{
return; return;
} }
m_EntitiesToKill.push_back(objectId); m_EntitiesToKill.push_back(objectId);
} }
void EntityManager::ScheduleForDeletion(LWOOBJID entity) void EntityManager::ScheduleForDeletion(LWOOBJID entity) {
{ if (std::count(m_EntitiesToDelete.begin(), m_EntitiesToDelete.end(), entity)) {
if (std::count(m_EntitiesToDelete.begin(), m_EntitiesToDelete.end(), entity))
{
return; return;
} }
@ -689,7 +598,6 @@ void EntityManager::FireEventServerSide(Entity* origin, std::string args) {
} }
} }
bool EntityManager::IsExcludedFromGhosting(LOT lot) bool EntityManager::IsExcludedFromGhosting(LOT lot) {
{
return std::find(m_GhostingExcludedLOTs.begin(), m_GhostingExcludedLOTs.end(), lot) != m_GhostingExcludedLOTs.end(); return std::find(m_GhostingExcludedLOTs.begin(), m_GhostingExcludedLOTs.end(), lot) != m_GhostingExcludedLOTs.end();
} }

View File

@ -45,7 +45,7 @@ std::u16string Leaderboard::ToString() const {
index++; index++;
} }
return GeneralUtils::ASCIIToUTF16(leaderboard); return GeneralUtils::UTF8ToUTF16(leaderboard);
} }
std::vector<LeaderboardEntry> Leaderboard::GetEntries() { std::vector<LeaderboardEntry> Leaderboard::GetEntries() {
@ -116,8 +116,7 @@ void LeaderboardManager::SaveScore(LWOOBJID playerID, uint32_t gameID, uint32_t
if (time <= storedTime) { // Based on time (LU live) if (time <= storedTime) { // Based on time (LU live)
highscore = false; highscore = false;
} }
} } else {
else {
if (score <= storedScore) // Based on score (DLU) if (score <= storedScore) // Based on score (DLU)
highscore = false; highscore = false;
} }

View File

@ -1,4 +1,4 @@
#include "Player.h" #include "Player.h"
#include <ctime> #include <ctime>
@ -17,8 +17,7 @@
std::vector<Player*> Player::m_Players = {}; std::vector<Player*> Player::m_Players = {};
Player::Player(const LWOOBJID& objectID, const EntityInfo info, User* user, Entity* parentEntity) : Entity(objectID, info, parentEntity) Player::Player(const LWOOBJID& objectID, const EntityInfo info, User* user, Entity* parentEntity) : Entity(objectID, info, parentEntity) {
{
m_ParentUser = user; m_ParentUser = user;
m_Character = m_ParentUser->GetLastUsedChar(); m_Character = m_ParentUser->GetLastUsedChar();
m_ParentUser->SetLoggedInChar(objectID); m_ParentUser->SetLoggedInChar(objectID);
@ -38,58 +37,48 @@ Player::Player(const LWOOBJID& objectID, const EntityInfo info, User* user, Enti
const auto& iter = std::find(m_Players.begin(), m_Players.end(), this); const auto& iter = std::find(m_Players.begin(), m_Players.end(), this);
if (iter != m_Players.end()) if (iter != m_Players.end()) {
{
return; return;
} }
m_Players.push_back(this); m_Players.push_back(this);
} }
User* Player::GetParentUser() const User* Player::GetParentUser() const {
{
return m_ParentUser; return m_ParentUser;
} }
SystemAddress Player::GetSystemAddress() const SystemAddress Player::GetSystemAddress() const {
{
return m_SystemAddress; return m_SystemAddress;
} }
void Player::SetSystemAddress(const SystemAddress& value) void Player::SetSystemAddress(const SystemAddress& value) {
{
m_SystemAddress = value; m_SystemAddress = value;
} }
void Player::SetRespawnPos(const NiPoint3 position) void Player::SetRespawnPos(const NiPoint3 position) {
{
m_respawnPos = position; m_respawnPos = position;
m_Character->SetRespawnPoint(dZoneManager::Instance()->GetZone()->GetWorldID(), position); m_Character->SetRespawnPoint(dZoneManager::Instance()->GetZone()->GetWorldID(), position);
} }
void Player::SetRespawnRot(const NiQuaternion rotation) void Player::SetRespawnRot(const NiQuaternion rotation) {
{
m_respawnRot = rotation; m_respawnRot = rotation;
} }
NiPoint3 Player::GetRespawnPosition() const NiPoint3 Player::GetRespawnPosition() const {
{
return m_respawnPos; return m_respawnPos;
} }
NiQuaternion Player::GetRespawnRotation() const NiQuaternion Player::GetRespawnRotation() const {
{
return m_respawnRot; return m_respawnRot;
} }
void Player::SendMail(const LWOOBJID sender, const std::string& senderName, const std::string& subject, const std::string& body, LOT attachment, uint16_t attachmentCount) const void Player::SendMail(const LWOOBJID sender, const std::string& senderName, const std::string& subject, const std::string& body, LOT attachment, uint16_t attachmentCount) const {
{
Mail::SendMail(sender, senderName, this, subject, body, attachment, attachmentCount); Mail::SendMail(sender, senderName, this, subject, body, attachment, attachmentCount);
} }
void Player::SendToZone(LWOMAPID zoneId, LWOCLONEID cloneId) void Player::SendToZone(LWOMAPID zoneId, LWOCLONEID cloneId) {
{
const auto objid = GetObjectID(); const auto objid = GetObjectID();
ZoneInstanceManager::Instance()->RequestZoneTransfer(Game::server, zoneId, cloneId, false, [objid](bool mythranShift, uint32_t zoneID, uint32_t zoneInstance, uint32_t zoneClone, std::string serverIP, uint16_t serverPort) { ZoneInstanceManager::Instance()->RequestZoneTransfer(Game::server, zoneId, cloneId, false, [objid](bool mythranShift, uint32_t zoneID, uint32_t zoneInstance, uint32_t zoneClone, std::string serverIP, uint16_t serverPort) {
@ -121,38 +110,31 @@ void Player::SendToZone(LWOMAPID zoneId, LWOCLONEID cloneId)
}); });
} }
void Player::AddLimboConstruction(LWOOBJID objectId) void Player::AddLimboConstruction(LWOOBJID objectId) {
{
const auto& iter = std::find(m_LimboConstructions.begin(), m_LimboConstructions.end(), objectId); const auto& iter = std::find(m_LimboConstructions.begin(), m_LimboConstructions.end(), objectId);
if (iter != m_LimboConstructions.end()) if (iter != m_LimboConstructions.end()) {
{
return; return;
} }
m_LimboConstructions.push_back(objectId); m_LimboConstructions.push_back(objectId);
} }
void Player::RemoveLimboConstruction(LWOOBJID objectId) void Player::RemoveLimboConstruction(LWOOBJID objectId) {
{
const auto& iter = std::find(m_LimboConstructions.begin(), m_LimboConstructions.end(), objectId); const auto& iter = std::find(m_LimboConstructions.begin(), m_LimboConstructions.end(), objectId);
if (iter == m_LimboConstructions.end()) if (iter == m_LimboConstructions.end()) {
{
return; return;
} }
m_LimboConstructions.erase(iter); m_LimboConstructions.erase(iter);
} }
void Player::ConstructLimboEntities() void Player::ConstructLimboEntities() {
{ for (const auto objectId : m_LimboConstructions) {
for (const auto objectId : m_LimboConstructions)
{
auto* entity = EntityManager::Instance()->GetEntity(objectId); auto* entity = EntityManager::Instance()->GetEntity(objectId);
if (entity == nullptr) if (entity == nullptr) {
{
continue; continue;
} }
@ -162,52 +144,41 @@ void Player::ConstructLimboEntities()
m_LimboConstructions.clear(); m_LimboConstructions.clear();
} }
std::map<LWOOBJID, Loot::Info>& Player::GetDroppedLoot() std::map<LWOOBJID, Loot::Info>& Player::GetDroppedLoot() {
{
return m_DroppedLoot; return m_DroppedLoot;
} }
const NiPoint3& Player::GetGhostReferencePoint() const const NiPoint3& Player::GetGhostReferencePoint() const {
{
return m_GhostOverride ? m_GhostOverridePoint : m_GhostReferencePoint; return m_GhostOverride ? m_GhostOverridePoint : m_GhostReferencePoint;
} }
const NiPoint3& Player::GetOriginGhostReferencePoint() const const NiPoint3& Player::GetOriginGhostReferencePoint() const {
{
return m_GhostReferencePoint; return m_GhostReferencePoint;
} }
void Player::SetGhostReferencePoint(const NiPoint3& value) void Player::SetGhostReferencePoint(const NiPoint3& value) {
{
m_GhostReferencePoint = value; m_GhostReferencePoint = value;
} }
void Player::SetGhostOverridePoint(const NiPoint3& value) void Player::SetGhostOverridePoint(const NiPoint3& value) {
{
m_GhostOverridePoint = value; m_GhostOverridePoint = value;
} }
const NiPoint3& Player::GetGhostOverridePoint() const const NiPoint3& Player::GetGhostOverridePoint() const {
{
return m_GhostOverridePoint; return m_GhostOverridePoint;
} }
void Player::SetGhostOverride(bool value) void Player::SetGhostOverride(bool value) {
{
m_GhostOverride = value; m_GhostOverride = value;
} }
bool Player::GetGhostOverride() const bool Player::GetGhostOverride() const {
{
return m_GhostOverride; return m_GhostOverride;
} }
void Player::ObserveEntity(int32_t id) void Player::ObserveEntity(int32_t id) {
{ for (int32_t i = 0; i < m_ObservedEntitiesUsed; i++) {
for (int32_t i = 0; i < m_ObservedEntitiesUsed; i++) if (m_ObservedEntities[i] == 0 || m_ObservedEntities[i] == id) {
{
if (m_ObservedEntities[i] == 0 || m_ObservedEntities[i] == id)
{
m_ObservedEntities[i] = id; m_ObservedEntities[i] = id;
return; return;
@ -216,8 +187,7 @@ void Player::ObserveEntity(int32_t id)
const auto index = m_ObservedEntitiesUsed++; const auto index = m_ObservedEntitiesUsed++;
if (m_ObservedEntitiesUsed > m_ObservedEntitiesLength) if (m_ObservedEntitiesUsed > m_ObservedEntitiesLength) {
{
m_ObservedEntities.resize(m_ObservedEntitiesLength + m_ObservedEntitiesLength); m_ObservedEntities.resize(m_ObservedEntitiesLength + m_ObservedEntitiesLength);
m_ObservedEntitiesLength = m_ObservedEntitiesLength + m_ObservedEntitiesLength; m_ObservedEntitiesLength = m_ObservedEntitiesLength + m_ObservedEntitiesLength;
@ -226,12 +196,9 @@ void Player::ObserveEntity(int32_t id)
m_ObservedEntities[index] = id; m_ObservedEntities[index] = id;
} }
bool Player::IsObserved(int32_t id) bool Player::IsObserved(int32_t id) {
{ for (int32_t i = 0; i < m_ObservedEntitiesUsed; i++) {
for (int32_t i = 0; i < m_ObservedEntitiesUsed; i++) if (m_ObservedEntities[i] == id) {
{
if (m_ObservedEntities[i] == id)
{
return true; return true;
} }
} }
@ -239,34 +206,27 @@ bool Player::IsObserved(int32_t id)
return false; return false;
} }
void Player::GhostEntity(int32_t id) void Player::GhostEntity(int32_t id) {
{ for (int32_t i = 0; i < m_ObservedEntitiesUsed; i++) {
for (int32_t i = 0; i < m_ObservedEntitiesUsed; i++) if (m_ObservedEntities[i] == id) {
{
if (m_ObservedEntities[i] == id)
{
m_ObservedEntities[i] = 0; m_ObservedEntities[i] = 0;
} }
} }
} }
Player* Player::GetPlayer(const SystemAddress& sysAddr) Player* Player::GetPlayer(const SystemAddress& sysAddr) {
{
auto* entity = UserManager::Instance()->GetUser(sysAddr)->GetLastUsedChar()->GetEntity(); auto* entity = UserManager::Instance()->GetUser(sysAddr)->GetLastUsedChar()->GetEntity();
return static_cast<Player*>(entity); return static_cast<Player*>(entity);
} }
Player* Player::GetPlayer(const std::string& name) Player* Player::GetPlayer(const std::string& name) {
{
const auto characters = EntityManager::Instance()->GetEntitiesByComponent(COMPONENT_TYPE_CHARACTER); const auto characters = EntityManager::Instance()->GetEntitiesByComponent(COMPONENT_TYPE_CHARACTER);
for (auto* character : characters) for (auto* character : characters) {
{
if (!character->IsPlayer()) continue; if (!character->IsPlayer()) continue;
if (character->GetCharacter()->GetName() == name) if (character->GetCharacter()->GetName() == name) {
{
return static_cast<Player*>(character); return static_cast<Player*>(character);
} }
} }
@ -274,12 +234,9 @@ Player* Player::GetPlayer(const std::string& name)
return nullptr; return nullptr;
} }
Player* Player::GetPlayer(LWOOBJID playerID) Player* Player::GetPlayer(LWOOBJID playerID) {
{ for (auto* player : m_Players) {
for (auto* player : m_Players) if (player->GetObjectID() == playerID) {
{
if (player->GetObjectID() == playerID)
{
return player; return player;
} }
} }
@ -287,8 +244,7 @@ Player* Player::GetPlayer(LWOOBJID playerID)
return nullptr; return nullptr;
} }
const std::vector<Player*>& Player::GetAllPlayers() const std::vector<Player*>& Player::GetAllPlayers() {
{
return m_Players; return m_Players;
} }
@ -300,23 +256,19 @@ void Player::SetDroppedCoins(uint64_t value) {
m_DroppedCoins = value; m_DroppedCoins = value;
} }
Player::~Player() Player::~Player() {
{ Game::logger->Log("Player", "Deleted player");
Game::logger->Log("Player", "Deleted player\n");
for (int32_t i = 0; i < m_ObservedEntitiesUsed; i++) for (int32_t i = 0; i < m_ObservedEntitiesUsed; i++) {
{
const auto id = m_ObservedEntities[i]; const auto id = m_ObservedEntities[i];
if (id == 0) if (id == 0) {
{
continue; continue;
} }
auto* entity = EntityManager::Instance()->GetGhostCandidate(id); auto* entity = EntityManager::Instance()->GetGhostCandidate(id);
if (entity != nullptr) if (entity != nullptr) {
{
entity->SetObservers(entity->GetObservers() - 1); entity->SetObservers(entity->GetObservers() - 1);
} }
} }
@ -325,8 +277,7 @@ Player::~Player()
const auto& iter = std::find(m_Players.begin(), m_Players.end(), this); const auto& iter = std::find(m_Players.begin(), m_Players.end(), this);
if (iter == m_Players.end()) if (iter == m_Players.end()) {
{
return; return;
} }

View File

@ -1,4 +1,4 @@
#pragma once #pragma once
#include "Entity.h" #include "Entity.h"

View File

@ -3,18 +3,13 @@
TeamManager* TeamManager::m_Address = nullptr; //For singleton method TeamManager* TeamManager::m_Address = nullptr; //For singleton method
TeamManager::TeamManager() TeamManager::TeamManager() {
{
} }
Team* TeamManager::GetTeam(LWOOBJID member) const Team* TeamManager::GetTeam(LWOOBJID member) const {
{ for (const auto& pair : m_Teams) {
for (const auto& pair : m_Teams) for (const auto memberId : pair.second->members) {
{ if (memberId == member) {
for (const auto memberId : pair.second->members)
{
if (memberId == member)
{
return pair.second; return pair.second;
} }
} }
@ -23,36 +18,29 @@ Team* TeamManager::GetTeam(LWOOBJID member) const
return nullptr; return nullptr;
} }
LWOOBJID TeamManager::GetNextLootOwner(Team* team) const LWOOBJID TeamManager::GetNextLootOwner(Team* team) const {
{
team->lootRound++; team->lootRound++;
if (team->lootRound >= team->members.size()) if (team->lootRound >= team->members.size()) {
{
team->lootRound = 0; team->lootRound = 0;
} }
return team->members[team->lootRound]; return team->members[team->lootRound];
} }
void TeamManager::UpdateTeam(LWOOBJID teamId, char lootOption, const std::vector<LWOOBJID>& members) void TeamManager::UpdateTeam(LWOOBJID teamId, char lootOption, const std::vector<LWOOBJID>& members) {
{
const auto& pair = m_Teams.find(teamId); const auto& pair = m_Teams.find(teamId);
Team* team; Team* team;
if (pair == m_Teams.end()) if (pair == m_Teams.end()) {
{ if (members.size() <= 1) {
if (members.size() <= 1)
{
return; return;
} }
team = new Team(); team = new Team();
m_Teams[teamId] = team; m_Teams[teamId] = team;
} } else {
else
{
team = pair->second; team = pair->second;
} }
@ -60,8 +48,7 @@ void TeamManager::UpdateTeam(LWOOBJID teamId, char lootOption, const std::vector
team->lootOption = lootOption; team->lootOption = lootOption;
} }
void TeamManager::DeleteTeam(LWOOBJID teamId) void TeamManager::DeleteTeam(LWOOBJID teamId) {
{
const auto& pair = m_Teams.find(teamId); const auto& pair = m_Teams.find(teamId);
if (pair == m_Teams.end()) return; if (pair == m_Teams.end()) return;
@ -71,6 +58,5 @@ void TeamManager::DeleteTeam(LWOOBJID teamId)
m_Teams.erase(teamId); m_Teams.erase(teamId);
} }
TeamManager::~TeamManager() TeamManager::~TeamManager() {
{
} }

View File

@ -12,122 +12,93 @@
TradingManager* TradingManager::m_Address = nullptr; TradingManager* TradingManager::m_Address = nullptr;
Trade::Trade(LWOOBJID tradeId, LWOOBJID participantA, LWOOBJID participantB) Trade::Trade(LWOOBJID tradeId, LWOOBJID participantA, LWOOBJID participantB) {
{
m_TradeId = tradeId; m_TradeId = tradeId;
m_ParticipantA = participantA; m_ParticipantA = participantA;
m_ParticipantB = participantB; m_ParticipantB = participantB;
} }
Trade::~Trade() Trade::~Trade() {
{
} }
LWOOBJID Trade::GetTradeId() const LWOOBJID Trade::GetTradeId() const {
{
return m_TradeId; return m_TradeId;
} }
bool Trade::IsParticipant(LWOOBJID playerId) const bool Trade::IsParticipant(LWOOBJID playerId) const {
{
return m_ParticipantA == playerId || m_ParticipantB == playerId; return m_ParticipantA == playerId || m_ParticipantB == playerId;
} }
LWOOBJID Trade::GetParticipantA() const LWOOBJID Trade::GetParticipantA() const {
{
return m_ParticipantA; return m_ParticipantA;
} }
LWOOBJID Trade::GetParticipantB() const LWOOBJID Trade::GetParticipantB() const {
{
return m_ParticipantB; return m_ParticipantB;
} }
Entity* Trade::GetParticipantAEntity() const Entity* Trade::GetParticipantAEntity() const {
{
return EntityManager::Instance()->GetEntity(m_ParticipantA); return EntityManager::Instance()->GetEntity(m_ParticipantA);
} }
Entity* Trade::GetParticipantBEntity() const Entity* Trade::GetParticipantBEntity() const {
{
return EntityManager::Instance()->GetEntity(m_ParticipantB); return EntityManager::Instance()->GetEntity(m_ParticipantB);
} }
void Trade::SetCoins(LWOOBJID participant, uint64_t coins) void Trade::SetCoins(LWOOBJID participant, uint64_t coins) {
{ if (participant == m_ParticipantA) {
if (participant == m_ParticipantA)
{
m_CoinsA = coins; m_CoinsA = coins;
} } else if (participant == m_ParticipantB) {
else if (participant == m_ParticipantB)
{
m_CoinsB = coins; m_CoinsB = coins;
} }
} }
void Trade::SetItems(LWOOBJID participant, std::vector<TradeItem> items) void Trade::SetItems(LWOOBJID participant, std::vector<TradeItem> items) {
{ if (participant == m_ParticipantA) {
if (participant == m_ParticipantA)
{
m_ItemsA = items; m_ItemsA = items;
} } else if (participant == m_ParticipantB) {
else if (participant == m_ParticipantB)
{
m_ItemsB = items; m_ItemsB = items;
} }
} }
void Trade::SetAccepted(LWOOBJID participant, bool value) void Trade::SetAccepted(LWOOBJID participant, bool value) {
{ if (participant == m_ParticipantA) {
if (participant == m_ParticipantA)
{
m_AcceptedA = !value; m_AcceptedA = !value;
Game::logger->Log("Trade", "Accepted from A (%d), B: (%d)\n", value, m_AcceptedB); Game::logger->Log("Trade", "Accepted from A (%d), B: (%d)", value, m_AcceptedB);
auto* entityB = GetParticipantBEntity(); auto* entityB = GetParticipantBEntity();
if (entityB != nullptr) if (entityB != nullptr) {
{
GameMessages::SendServerTradeAccept(m_ParticipantB, value, entityB->GetSystemAddress()); GameMessages::SendServerTradeAccept(m_ParticipantB, value, entityB->GetSystemAddress());
} }
} } else if (participant == m_ParticipantB) {
else if (participant == m_ParticipantB)
{
m_AcceptedB = !value; m_AcceptedB = !value;
Game::logger->Log("Trade", "Accepted from B (%d), A: (%d)\n", value, m_AcceptedA); Game::logger->Log("Trade", "Accepted from B (%d), A: (%d)", value, m_AcceptedA);
auto* entityA = GetParticipantAEntity(); auto* entityA = GetParticipantAEntity();
if (entityA != nullptr) if (entityA != nullptr) {
{
GameMessages::SendServerTradeAccept(m_ParticipantA, value, entityA->GetSystemAddress()); GameMessages::SendServerTradeAccept(m_ParticipantA, value, entityA->GetSystemAddress());
} }
} }
if (m_AcceptedA && m_AcceptedB) if (m_AcceptedA && m_AcceptedB) {
{
auto* entityB = GetParticipantBEntity(); auto* entityB = GetParticipantBEntity();
if (entityB != nullptr) if (entityB != nullptr) {
{
GameMessages::SendServerTradeAccept(m_ParticipantB, false, entityB->GetSystemAddress()); GameMessages::SendServerTradeAccept(m_ParticipantB, false, entityB->GetSystemAddress());
} } else {
else
{
return; return;
} }
auto* entityA = GetParticipantAEntity(); auto* entityA = GetParticipantAEntity();
if (entityA != nullptr) if (entityA != nullptr) {
{
GameMessages::SendServerTradeAccept(m_ParticipantA, false, entityA->GetSystemAddress()); GameMessages::SendServerTradeAccept(m_ParticipantA, false, entityA->GetSystemAddress());
} } else {
else
{
return; return;
} }
@ -135,8 +106,7 @@ void Trade::SetAccepted(LWOOBJID participant, bool value)
} }
} }
void Trade::Complete() void Trade::Complete() {
{
auto* entityA = GetParticipantAEntity(); auto* entityA = GetParticipantAEntity();
auto* entityB = GetParticipantBEntity(); auto* entityB = GetParticipantBEntity();
@ -154,27 +124,23 @@ void Trade::Complete()
characterA->SetCoins(characterA->GetCoins() - m_CoinsA + m_CoinsB, eLootSourceType::LOOT_SOURCE_TRADE); characterA->SetCoins(characterA->GetCoins() - m_CoinsA + m_CoinsB, eLootSourceType::LOOT_SOURCE_TRADE);
characterB->SetCoins(characterB->GetCoins() - m_CoinsB + m_CoinsA, eLootSourceType::LOOT_SOURCE_TRADE); characterB->SetCoins(characterB->GetCoins() - m_CoinsB + m_CoinsA, eLootSourceType::LOOT_SOURCE_TRADE);
for (const auto& tradeItem : m_ItemsA) for (const auto& tradeItem : m_ItemsA) {
{
inventoryA->RemoveItem(tradeItem.itemLot, tradeItem.itemCount, INVALID, true); inventoryA->RemoveItem(tradeItem.itemLot, tradeItem.itemCount, INVALID, true);
missionsA->Progress(MissionTaskType::MISSION_TASK_TYPE_ITEM_COLLECTION, tradeItem.itemLot, LWOOBJID_EMPTY, "", -tradeItem.itemCount); missionsA->Progress(MissionTaskType::MISSION_TASK_TYPE_ITEM_COLLECTION, tradeItem.itemLot, LWOOBJID_EMPTY, "", -tradeItem.itemCount);
} }
for (const auto& tradeItem : m_ItemsB) for (const auto& tradeItem : m_ItemsB) {
{
inventoryB->RemoveItem(tradeItem.itemLot, tradeItem.itemCount, INVALID, true); inventoryB->RemoveItem(tradeItem.itemLot, tradeItem.itemCount, INVALID, true);
missionsB->Progress(MissionTaskType::MISSION_TASK_TYPE_ITEM_COLLECTION, tradeItem.itemLot, LWOOBJID_EMPTY, "", -tradeItem.itemCount); missionsB->Progress(MissionTaskType::MISSION_TASK_TYPE_ITEM_COLLECTION, tradeItem.itemLot, LWOOBJID_EMPTY, "", -tradeItem.itemCount);
} }
for (const auto& tradeItem : m_ItemsA) for (const auto& tradeItem : m_ItemsA) {
{
inventoryB->AddItem(tradeItem.itemLot, tradeItem.itemCount, eLootSourceType::LOOT_SOURCE_TRADE); inventoryB->AddItem(tradeItem.itemLot, tradeItem.itemCount, eLootSourceType::LOOT_SOURCE_TRADE);
} }
for (const auto& tradeItem : m_ItemsB) for (const auto& tradeItem : m_ItemsB) {
{
inventoryA->AddItem(tradeItem.itemLot, tradeItem.itemCount, eLootSourceType::LOOT_SOURCE_TRADE); inventoryA->AddItem(tradeItem.itemLot, tradeItem.itemCount, eLootSourceType::LOOT_SOURCE_TRADE);
} }
@ -184,8 +150,7 @@ void Trade::Complete()
characterB->SaveXMLToDatabase(); characterB->SaveXMLToDatabase();
} }
void Trade::Cancel() void Trade::Cancel() {
{
auto* entityA = GetParticipantAEntity(); auto* entityA = GetParticipantAEntity();
auto* entityB = GetParticipantBEntity(); auto* entityB = GetParticipantBEntity();
@ -195,31 +160,25 @@ void Trade::Cancel()
GameMessages::SendServerTradeCancel(entityB->GetObjectID(), entityB->GetSystemAddress()); GameMessages::SendServerTradeCancel(entityB->GetObjectID(), entityB->GetSystemAddress());
} }
void Trade::SendUpdateToOther(LWOOBJID participant) void Trade::SendUpdateToOther(LWOOBJID participant) {
{
Entity* other = nullptr; Entity* other = nullptr;
Entity* self = nullptr; Entity* self = nullptr;
uint64_t coins; uint64_t coins;
std::vector<TradeItem> itemIds; std::vector<TradeItem> itemIds;
Game::logger->Log("Trade", "Attempting to send trade update\n"); Game::logger->Log("Trade", "Attempting to send trade update");
if (participant == m_ParticipantA) if (participant == m_ParticipantA) {
{
other = GetParticipantBEntity(); other = GetParticipantBEntity();
self = GetParticipantAEntity(); self = GetParticipantAEntity();
coins = m_CoinsA; coins = m_CoinsA;
itemIds = m_ItemsA; itemIds = m_ItemsA;
} } else if (participant == m_ParticipantB) {
else if (participant == m_ParticipantB)
{
other = GetParticipantAEntity(); other = GetParticipantAEntity();
self = GetParticipantBEntity(); self = GetParticipantBEntity();
coins = m_CoinsB; coins = m_CoinsB;
itemIds = m_ItemsB; itemIds = m_ItemsB;
} } else {
else
{
return; return;
} }
@ -231,8 +190,7 @@ void Trade::SendUpdateToOther(LWOOBJID participant)
if (inventoryComponent == nullptr) return; if (inventoryComponent == nullptr) return;
for (const auto tradeItem : itemIds) for (const auto tradeItem : itemIds) {
{
auto* item = inventoryComponent->FindItemById(tradeItem.itemId); auto* item = inventoryComponent->FindItemById(tradeItem.itemId);
if (item == nullptr) return; if (item == nullptr) return;
@ -242,27 +200,23 @@ void Trade::SendUpdateToOther(LWOOBJID participant)
items.push_back(tradeItem); items.push_back(tradeItem);
} }
Game::logger->Log("Trade", "Sending trade update\n"); Game::logger->Log("Trade", "Sending trade update");
GameMessages::SendServerTradeUpdate(other->GetObjectID(), coins, items, other->GetSystemAddress()); GameMessages::SendServerTradeUpdate(other->GetObjectID(), coins, items, other->GetSystemAddress());
} }
TradingManager::TradingManager() TradingManager::TradingManager() {
{
} }
TradingManager::~TradingManager() TradingManager::~TradingManager() {
{ for (const auto& pair : trades) {
for (const auto& pair : trades)
{
delete pair.second; delete pair.second;
} }
trades.clear(); trades.clear();
} }
Trade* TradingManager::GetTrade(LWOOBJID tradeId) const Trade* TradingManager::GetTrade(LWOOBJID tradeId) const {
{
const auto& pair = trades.find(tradeId); const auto& pair = trades.find(tradeId);
if (pair == trades.end()) return nullptr; if (pair == trades.end()) return nullptr;
@ -270,12 +224,9 @@ Trade* TradingManager::GetTrade(LWOOBJID tradeId) const
return pair->second; return pair->second;
} }
Trade* TradingManager::GetPlayerTrade(LWOOBJID playerId) const Trade* TradingManager::GetPlayerTrade(LWOOBJID playerId) const {
{ for (const auto& pair : trades) {
for (const auto& pair : trades) if (pair.second->IsParticipant(playerId)) {
{
if (pair.second->IsParticipant(playerId))
{
return pair.second; return pair.second;
} }
} }
@ -283,8 +234,7 @@ Trade* TradingManager::GetPlayerTrade(LWOOBJID playerId) const
return nullptr; return nullptr;
} }
void TradingManager::CancelTrade(LWOOBJID tradeId) void TradingManager::CancelTrade(LWOOBJID tradeId) {
{
auto* trade = GetTrade(tradeId); auto* trade = GetTrade(tradeId);
if (trade == nullptr) return; if (trade == nullptr) return;
@ -294,15 +244,14 @@ void TradingManager::CancelTrade(LWOOBJID tradeId)
trades.erase(tradeId); trades.erase(tradeId);
} }
Trade* TradingManager::NewTrade(LWOOBJID participantA, LWOOBJID participantB) Trade* TradingManager::NewTrade(LWOOBJID participantA, LWOOBJID participantB) {
{
const LWOOBJID tradeId = ObjectIDManager::Instance()->GenerateObjectID(); const LWOOBJID tradeId = ObjectIDManager::Instance()->GenerateObjectID();
auto* trade = new Trade(tradeId, participantA, participantB); auto* trade = new Trade(tradeId, participantA, participantB);
trades[tradeId] = trade; trades[tradeId] = trade;
Game::logger->Log("TradingManager", "Created new trade between (%llu) <-> (%llu)\n", participantA, participantB); Game::logger->Log("TradingManager", "Created new trade between (%llu) <-> (%llu)", participantA, participantB);
return trade; return trade;
} }

View File

@ -19,6 +19,8 @@ User::User(const SystemAddress& sysAddr, const std::string& username, const std:
m_Username = username; m_Username = username;
m_LoggedInCharID = 0; m_LoggedInCharID = 0;
m_IsBestFriendMap = std::unordered_map<std::string, bool>();
//HACK HACK HACK //HACK HACK HACK
//This needs to be re-enabled / updated whenever the mute stuff is moved to another table. //This needs to be re-enabled / updated whenever the mute stuff is moved to another table.
//This was only done because otherwise the website's account page dies and the website is waiting on a migration to wordpress. //This was only done because otherwise the website's account page dies and the website is waiting on a migration to wordpress.
@ -48,7 +50,7 @@ User::User(const SystemAddress& sysAddr, const std::string& username, const std:
LWOOBJID objID = res->getUInt64(1); LWOOBJID objID = res->getUInt64(1);
Character* character = new Character(uint32_t(objID), this); Character* character = new Character(uint32_t(objID), this);
m_Characters.push_back(character); m_Characters.push_back(character);
Game::logger->Log("User", "Loaded %llu as it is the last used char\n", objID); Game::logger->Log("User", "Loaded %llu as it is the last used char", objID);
} }
} }
@ -107,18 +109,15 @@ Character * User::GetLastUsedChar() {
} }
} }
bool User::GetIsMuted() const bool User::GetIsMuted() const {
{
return m_MuteExpire == 1 || m_MuteExpire > time(NULL); return m_MuteExpire == 1 || m_MuteExpire > time(NULL);
} }
time_t User::GetMuteExpire() const time_t User::GetMuteExpire() const {
{
return m_MuteExpire; return m_MuteExpire;
} }
void User::SetMuteExpire(time_t value) void User::SetMuteExpire(time_t value) {
{
m_MuteExpire = value; m_MuteExpire = value;
} }
@ -126,7 +125,7 @@ void User::UserOutOfSync() {
m_AmountOfTimesOutOfSync++; m_AmountOfTimesOutOfSync++;
if (m_AmountOfTimesOutOfSync > m_MaxDesyncAllowed) { if (m_AmountOfTimesOutOfSync > m_MaxDesyncAllowed) {
//YEET //YEET
Game::logger->Log("User", "User %s was out of sync %i times out of %i, disconnecting for suspected speedhacking.\n", m_Username.c_str(), m_AmountOfTimesOutOfSync, m_MaxDesyncAllowed); Game::logger->Log("User", "User %s was out of sync %i times out of %i, disconnecting for suspected speedhacking.", m_Username.c_str(), m_AmountOfTimesOutOfSync, m_MaxDesyncAllowed);
Game::server->Disconnect(this->m_SystemAddress, SERVER_DISCON_KICK); Game::server->Disconnect(this->m_SystemAddress, SERVER_DISCON_KICK);
} }
} }

View File

@ -42,6 +42,9 @@ public:
bool GetLastChatMessageApproved() { return m_LastChatMessageApproved; } bool GetLastChatMessageApproved() { return m_LastChatMessageApproved; }
void SetLastChatMessageApproved(bool approved) { m_LastChatMessageApproved = approved; } void SetLastChatMessageApproved(bool approved) { m_LastChatMessageApproved = approved; }
std::unordered_map<std::string, bool> GetIsBestFriendMap() { return m_IsBestFriendMap; }
void SetIsBestFriendMap(std::unordered_map<std::string, bool> mapToSet) { m_IsBestFriendMap = mapToSet; }
bool GetIsMuted() const; bool GetIsMuted() const;
time_t GetMuteExpire() const; time_t GetMuteExpire() const;
@ -63,6 +66,8 @@ private:
std::vector<Character*> m_Characters; std::vector<Character*> m_Characters;
LWOOBJID m_LoggedInCharID; LWOOBJID m_LoggedInCharID;
std::unordered_map<std::string, bool> m_IsBestFriendMap;
bool m_LastChatMessageApproved = false; bool m_LastChatMessageApproved = false;
int m_AmountOfTimesOutOfSync = 0; int m_AmountOfTimesOutOfSync = 0;
const int m_MaxDesyncAllowed = 12; const int m_MaxDesyncAllowed = 12;

View File

@ -109,8 +109,7 @@ User* UserManager::GetUser ( const std::string& username ) {
bool UserManager::DeleteUser(const SystemAddress& sysAddr) { bool UserManager::DeleteUser(const SystemAddress& sysAddr) {
const auto& it = m_Users.find(sysAddr); const auto& it = m_Users.find(sysAddr);
if (it != m_Users.end()) if (it != m_Users.end()) {
{
if (std::count(m_UsersToDelete.begin(), m_UsersToDelete.end(), it->second)) return false; if (std::count(m_UsersToDelete.begin(), m_UsersToDelete.end(), it->second)) return false;
m_UsersToDelete.push_back(it->second); m_UsersToDelete.push_back(it->second);
@ -123,11 +122,9 @@ bool UserManager::DeleteUser ( const SystemAddress& sysAddr ) {
return false; return false;
} }
void UserManager::DeletePendingRemovals() void UserManager::DeletePendingRemovals() {
{ for (auto* user : m_UsersToDelete) {
for (auto* user : m_UsersToDelete) Game::logger->Log("UserManager", "Deleted user %i", user->GetAccountID());
{
Game::logger->Log("UserManager", "Deleted user %i\n", user->GetAccountID());
delete user; delete user;
} }
@ -185,8 +182,7 @@ void UserManager::RequestCharacterList ( const SystemAddress& sysAddr ) {
if (res->rowsCount() > 0) { if (res->rowsCount() > 0) {
std::vector<Character*>& chars = u->GetCharacters(); std::vector<Character*>& chars = u->GetCharacters();
for (size_t i = 0; i < chars.size(); ++i) for (size_t i = 0; i < chars.size(); ++i) {
{
if (chars[i]->GetEntity() == nullptr) // We don't have entity data to save if (chars[i]->GetEntity() == nullptr) // We don't have entity data to save
{ {
delete chars[i]; delete chars[i];
@ -196,8 +192,7 @@ void UserManager::RequestCharacterList ( const SystemAddress& sysAddr ) {
auto* skillComponent = chars[i]->GetEntity()->GetComponent<SkillComponent>(); auto* skillComponent = chars[i]->GetEntity()->GetComponent<SkillComponent>();
if (skillComponent != nullptr) if (skillComponent != nullptr) {
{
skillComponent->Reset(); skillComponent->Reset();
} }
@ -251,22 +246,21 @@ void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet)
LOT pantsLOT = FindCharPantsID(pantsColor); LOT pantsLOT = FindCharPantsID(pantsColor);
if (name != "" && !UserManager::IsNameAvailable(name)) { if (name != "" && !UserManager::IsNameAvailable(name)) {
Game::logger->Log("UserManager", "AccountID: %i chose unavailable name: %s\n", u->GetAccountID(), name.c_str()); Game::logger->Log("UserManager", "AccountID: %i chose unavailable name: %s", u->GetAccountID(), name.c_str());
WorldPackets::SendCharacterCreationResponse(sysAddr, CREATION_RESPONSE_CUSTOM_NAME_IN_USE); WorldPackets::SendCharacterCreationResponse(sysAddr, CREATION_RESPONSE_CUSTOM_NAME_IN_USE);
return; return;
} }
if (!IsNameAvailable(predefinedName)) { if (!IsNameAvailable(predefinedName)) {
Game::logger->Log("UserManager", "AccountID: %i chose unavailable predefined name: %s\n", u->GetAccountID(), predefinedName.c_str()); Game::logger->Log("UserManager", "AccountID: %i chose unavailable predefined name: %s", u->GetAccountID(), predefinedName.c_str());
WorldPackets::SendCharacterCreationResponse(sysAddr, CREATION_RESPONSE_PREDEFINED_NAME_IN_USE); WorldPackets::SendCharacterCreationResponse(sysAddr, CREATION_RESPONSE_PREDEFINED_NAME_IN_USE);
return; return;
} }
if (name == "") { if (name == "") {
Game::logger->Log("UserManager", "AccountID: %i is creating a character with predefined name: %s\n", u->GetAccountID(), predefinedName.c_str()); Game::logger->Log("UserManager", "AccountID: %i is creating a character with predefined name: %s", u->GetAccountID(), predefinedName.c_str());
} } else {
else { Game::logger->Log("UserManager", "AccountID: %i is creating a character with name: %s (temporary: %s)", u->GetAccountID(), name.c_str(), predefinedName.c_str());
Game::logger->Log("UserManager", "AccountID: %i is creating a character with name: %s (temporary: %s)\n", u->GetAccountID(), name.c_str(), predefinedName.c_str());
} }
//Now that the name is ok, we can get an objectID from Master: //Now that the name is ok, we can get an objectID from Master:
@ -277,7 +271,7 @@ void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet)
auto* overlapResult = overlapStmt->executeQuery(); auto* overlapResult = overlapStmt->executeQuery();
if (overlapResult->next()) { if (overlapResult->next()) {
Game::logger->Log("UserManager", "Character object id unavailable, check objectidtracker!\n"); Game::logger->Log("UserManager", "Character object id unavailable, check objectidtracker!");
WorldPackets::SendCharacterCreationResponse(sysAddr, CREATION_RESPONSE_OBJECT_ID_UNAVAILABLE); WorldPackets::SendCharacterCreationResponse(sysAddr, CREATION_RESPONSE_OBJECT_ID_UNAVAILABLE);
return; return;
} }
@ -364,14 +358,14 @@ void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet)
void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet) { void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet) {
User* u = GetUser(sysAddr); User* u = GetUser(sysAddr);
if (!u) { if (!u) {
Game::logger->Log("UserManager", "Couldn't get user to delete character\n"); Game::logger->Log("UserManager", "Couldn't get user to delete character");
return; return;
} }
LWOOBJID objectID = PacketUtils::ReadPacketS64(8, packet); LWOOBJID objectID = PacketUtils::ReadPacketS64(8, packet);
uint32_t charID = static_cast<uint32_t>(objectID); uint32_t charID = static_cast<uint32_t>(objectID);
Game::logger->Log("UserManager", "Received char delete req for ID: %llu (%u)\n", objectID, charID); Game::logger->Log("UserManager", "Received char delete req for ID: %llu (%u)", objectID, charID);
//Check if this user has this character: //Check if this user has this character:
bool hasCharacter = false; bool hasCharacter = false;
@ -381,11 +375,10 @@ void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet)
} }
if (!hasCharacter) { if (!hasCharacter) {
Game::logger->Log("UserManager", "User %i tried to delete a character that it does not own!\n", u->GetAccountID()); Game::logger->Log("UserManager", "User %i tried to delete a character that it does not own!", u->GetAccountID());
WorldPackets::SendCharacterDeleteResponse(sysAddr, false); WorldPackets::SendCharacterDeleteResponse(sysAddr, false);
} } else {
else { Game::logger->Log("UserManager", "Deleting character %i", charID);
Game::logger->Log("UserManager", "Deleting character %i\n", charID);
{ {
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("DELETE FROM charxml WHERE id=? LIMIT 1;"); sql::PreparedStatement* stmt = Database::CreatePreppedStmt("DELETE FROM charxml WHERE id=? LIMIT 1;");
stmt->setUInt64(1, charID); stmt->setUInt64(1, charID);
@ -461,7 +454,7 @@ void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet)
void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet) { void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet) {
User* u = GetUser(sysAddr); User* u = GetUser(sysAddr);
if (!u) { if (!u) {
Game::logger->Log("UserManager", "Couldn't get user to delete character\n"); Game::logger->Log("UserManager", "Couldn't get user to delete character");
return; return;
} }
@ -470,7 +463,7 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
objectID = GeneralUtils::ClearBit(objectID, OBJECT_BIT_PERSISTENT); objectID = GeneralUtils::ClearBit(objectID, OBJECT_BIT_PERSISTENT);
uint32_t charID = static_cast<uint32_t>(objectID); uint32_t charID = static_cast<uint32_t>(objectID);
Game::logger->Log("UserManager", "Received char rename request for ID: %llu (%u)\n", objectID, charID); Game::logger->Log("UserManager", "Received char rename request for ID: %llu (%u)", objectID, charID);
std::string newName = PacketUtils::ReadString(16, packet, true); std::string newName = PacketUtils::ReadString(16, packet, true);
@ -484,7 +477,7 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
} }
if (!hasCharacter || !character) { if (!hasCharacter || !character) {
Game::logger->Log("UserManager", "User %i tried to rename a character that it does not own!\n", u->GetAccountID()); Game::logger->Log("UserManager", "User %i tried to rename a character that it does not own!", u->GetAccountID());
WorldPackets::SendCharacterRenameResponse(sysAddr, RENAME_RESPONSE_UNKNOWN_ERROR); WorldPackets::SendCharacterRenameResponse(sysAddr, RENAME_RESPONSE_UNKNOWN_ERROR);
} else if (hasCharacter && character) { } else if (hasCharacter && character) {
if (newName == character->GetName()) { if (newName == character->GetName()) {
@ -501,7 +494,7 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
stmt->execute(); stmt->execute();
delete stmt; delete stmt;
Game::logger->Log("UserManager", "Character %s now known as %s\n", character->GetName().c_str(), newName.c_str()); Game::logger->Log("UserManager", "Character %s now known as %s", character->GetName().c_str(), newName.c_str());
WorldPackets::SendCharacterRenameResponse(sysAddr, RENAME_RESPONSE_SUCCESS); WorldPackets::SendCharacterRenameResponse(sysAddr, RENAME_RESPONSE_SUCCESS);
UserManager::RequestCharacterList(sysAddr); UserManager::RequestCharacterList(sysAddr);
} else { } else {
@ -512,7 +505,7 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
stmt->execute(); stmt->execute();
delete stmt; delete stmt;
Game::logger->Log("UserManager", "Character %s has been renamed to %s and is pending approval by a moderator.\n", character->GetName().c_str(), newName.c_str()); Game::logger->Log("UserManager", "Character %s has been renamed to %s and is pending approval by a moderator.", character->GetName().c_str(), newName.c_str());
WorldPackets::SendCharacterRenameResponse(sysAddr, RENAME_RESPONSE_SUCCESS); WorldPackets::SendCharacterRenameResponse(sysAddr, RENAME_RESPONSE_SUCCESS);
UserManager::RequestCharacterList(sysAddr); UserManager::RequestCharacterList(sysAddr);
} }
@ -520,7 +513,7 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
WorldPackets::SendCharacterRenameResponse(sysAddr, RENAME_RESPONSE_NAME_IN_USE); WorldPackets::SendCharacterRenameResponse(sysAddr, RENAME_RESPONSE_NAME_IN_USE);
} }
} else { } else {
Game::logger->Log("UserManager", "Unknown error occurred when renaming character, either hasCharacter or character variable != true.\n"); Game::logger->Log("UserManager", "Unknown error occurred when renaming character, either hasCharacter or character variable != true.");
WorldPackets::SendCharacterRenameResponse(sysAddr, RENAME_RESPONSE_UNKNOWN_ERROR); WorldPackets::SendCharacterRenameResponse(sysAddr, RENAME_RESPONSE_UNKNOWN_ERROR);
} }
} }
@ -528,7 +521,7 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
void UserManager::LoginCharacter(const SystemAddress& sysAddr, uint32_t playerID) { void UserManager::LoginCharacter(const SystemAddress& sysAddr, uint32_t playerID) {
User* u = GetUser(sysAddr); User* u = GetUser(sysAddr);
if (!u) { if (!u) {
Game::logger->Log("UserManager", "Couldn't get user to log in character\n"); Game::logger->Log("UserManager", "Couldn't get user to log in character");
return; return;
} }
@ -551,7 +544,7 @@ void UserManager::LoginCharacter(const SystemAddress& sysAddr, uint32_t playerID
if (zoneID == LWOZONEID_INVALID) zoneID = 1000; //Send char to VE if (zoneID == LWOZONEID_INVALID) zoneID = 1000; //Send char to VE
ZoneInstanceManager::Instance()->RequestZoneTransfer(Game::server, zoneID, character->GetZoneClone(), false, [=](bool mythranShift, uint32_t zoneID, uint32_t zoneInstance, uint32_t zoneClone, std::string serverIP, uint16_t serverPort) { ZoneInstanceManager::Instance()->RequestZoneTransfer(Game::server, zoneID, character->GetZoneClone(), false, [=](bool mythranShift, uint32_t zoneID, uint32_t zoneInstance, uint32_t zoneClone, std::string serverIP, uint16_t serverPort) {
Game::logger->Log("UserManager", "Transferring %s to Zone %i (Instance %i | Clone %i | Mythran Shift: %s) with IP %s and Port %i\n", character->GetName().c_str(), zoneID, zoneInstance, zoneClone, mythranShift == true ? "true" : "false", serverIP.c_str(), serverPort); Game::logger->Log("UserManager", "Transferring %s to Zone %i (Instance %i | Clone %i | Mythran Shift: %s) with IP %s and Port %i", character->GetName().c_str(), zoneID, zoneInstance, zoneClone, mythranShift == true ? "true" : "false", serverIP.c_str(), serverPort);
if (character) { if (character) {
character->SetZoneID(zoneID); character->SetZoneID(zoneID);
character->SetZoneInstance(zoneInstance); character->SetZoneInstance(zoneInstance);
@ -561,7 +554,7 @@ void UserManager::LoginCharacter(const SystemAddress& sysAddr, uint32_t playerID
return; return;
}); });
} else { } else {
Game::logger->Log("UserManager", "Unknown error occurred when logging in a character, either hasCharacter or character variable != true.\n"); Game::logger->Log("UserManager", "Unknown error occurred when logging in a character, either hasCharacter or character variable != true.");
} }
} }
@ -575,8 +568,7 @@ uint32_t FindCharShirtID(uint32_t shirtColor, uint32_t shirtStyle) {
auto shirtLOT = tableData.getIntField(0, -1); auto shirtLOT = tableData.getIntField(0, -1);
tableData.finalize(); tableData.finalize();
return shirtLOT; return shirtLOT;
} } catch (const std::exception&) {
catch (const std::exception&){
Game::logger->Log("Character Create", "Failed to execute query! Using backup..."); Game::logger->Log("Character Create", "Failed to execute query! Using backup...");
// in case of no shirt found in CDServer, return problematic red vest. // in case of no shirt found in CDServer, return problematic red vest.
return 4069; return 4069;
@ -591,8 +583,7 @@ uint32_t FindCharPantsID(uint32_t pantsColor) {
auto pantsLOT = tableData.getIntField(0, -1); auto pantsLOT = tableData.getIntField(0, -1);
tableData.finalize(); tableData.finalize();
return pantsLOT; return pantsLOT;
} } catch (const std::exception&) {
catch (const std::exception&){
Game::logger->Log("Character Create", "Failed to execute query! Using backup..."); Game::logger->Log("Character Create", "Failed to execute query! Using backup...");
// in case of no pants color found in CDServer, return red pants. // in case of no pants color found in CDServer, return red pants.
return 2508; return 2508;

View File

@ -1,10 +1,9 @@
#include "AirMovementBehavior.h" #include "AirMovementBehavior.h"
#include "BehaviorBranchContext.h" #include "BehaviorBranchContext.h"
#include "BehaviorContext.h" #include "BehaviorContext.h"
#include "EntityManager.h" #include "EntityManager.h"
void AirMovementBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) void AirMovementBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
{
uint32_t handle; uint32_t handle;
bitStream->Read(handle); bitStream->Read(handle);
@ -12,15 +11,13 @@ void AirMovementBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bi
context->RegisterSyncBehavior(handle, this, branch); context->RegisterSyncBehavior(handle, this, branch);
} }
void AirMovementBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) void AirMovementBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
{
const auto handle = context->GetUniqueSkillId(); const auto handle = context->GetUniqueSkillId();
bitStream->Write(handle); bitStream->Write(handle);
} }
void AirMovementBehavior::Sync(BehaviorContext* context, RakNet::BitStream* bit_stream, BehaviorBranchContext branch) void AirMovementBehavior::Sync(BehaviorContext* context, RakNet::BitStream* bit_stream, BehaviorBranchContext branch) {
{
uint32_t behaviorId; uint32_t behaviorId;
bit_stream->Read(behaviorId); bit_stream->Read(behaviorId);
@ -31,14 +28,12 @@ void AirMovementBehavior::Sync(BehaviorContext* context, RakNet::BitStream* bit_
auto* behavior = CreateBehavior(behaviorId); auto* behavior = CreateBehavior(behaviorId);
if (EntityManager::Instance()->GetEntity(target) != nullptr) if (EntityManager::Instance()->GetEntity(target) != nullptr) {
{
branch.target = target; branch.target = target;
} }
behavior->Handle(context, bit_stream, branch); behavior->Handle(context, bit_stream, branch);
} }
void AirMovementBehavior::Load() void AirMovementBehavior::Load() {
{
} }

View File

@ -1,4 +1,4 @@
#pragma once #pragma once
#include "Behavior.h" #include "Behavior.h"
class AirMovementBehavior final : public Behavior class AirMovementBehavior final : public Behavior
@ -9,8 +9,7 @@ public:
* Inherited * Inherited
*/ */
explicit AirMovementBehavior(const uint32_t behavior_id) : Behavior(behavior_id) explicit AirMovementBehavior(const uint32_t behavior_id) : Behavior(behavior_id) {
{
} }
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override; void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;

View File

@ -1,4 +1,4 @@
#include "AndBehavior.h" #include "AndBehavior.h"
#include "BehaviorBranchContext.h" #include "BehaviorBranchContext.h"
#include "Game.h" #include "Game.h"
#include "dLogger.h" #include "dLogger.h"
@ -13,10 +13,8 @@ void AndBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream,
} }
} }
void AndBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) void AndBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) {
{ for (auto* behavior : this->m_behaviors) {
for (auto* behavior : this->m_behaviors)
{
behavior->Calculate(context, bitStream, branch); behavior->Calculate(context, bitStream, branch);
} }
} }

View File

@ -1,4 +1,4 @@
#pragma once #pragma once
#include <vector> #include <vector>
@ -12,8 +12,7 @@ public:
/* /*
* Inherited * Inherited
*/ */
explicit AndBehavior(const uint32_t behaviorId) : Behavior(behaviorId) explicit AndBehavior(const uint32_t behaviorId) : Behavior(behaviorId) {
{
} }
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override; void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;

View File

@ -5,8 +5,7 @@
#include "BuffComponent.h" #include "BuffComponent.h"
void ApplyBuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) void ApplyBuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
{
auto* entity = EntityManager::Instance()->GetEntity(branch.target == LWOOBJID_EMPTY ? context->originator : branch.target); auto* entity = EntityManager::Instance()->GetEntity(branch.target == LWOOBJID_EMPTY ? context->originator : branch.target);
if (entity == nullptr) return; if (entity == nullptr) return;
@ -19,8 +18,7 @@ void ApplyBuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitS
cancelOnLogout, cancelonRemoveBuff, cancelOnUi, cancelOnUnequip, cancelOnZone); cancelOnLogout, cancelonRemoveBuff, cancelOnUi, cancelOnUnequip, cancelOnZone);
} }
void ApplyBuffBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch) void ApplyBuffBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch) {
{
auto* entity = EntityManager::Instance()->GetEntity(branch.target); auto* entity = EntityManager::Instance()->GetEntity(branch.target);
if (entity == nullptr) return; if (entity == nullptr) return;
@ -32,13 +30,11 @@ void ApplyBuffBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext b
buffComponent->RemoveBuff(m_BuffId); buffComponent->RemoveBuff(m_BuffId);
} }
void ApplyBuffBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) void ApplyBuffBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
{
Handle(context, bitStream, branch); Handle(context, bitStream, branch);
} }
void ApplyBuffBehavior::Load() void ApplyBuffBehavior::Load() {
{
m_BuffId = GetInt("buff_id"); m_BuffId = GetInt("buff_id");
m_Duration = GetFloat("duration_secs"); m_Duration = GetFloat("duration_secs");
addImmunity = GetBoolean("add_immunity"); addImmunity = GetBoolean("add_immunity");

View File

@ -21,8 +21,7 @@ public:
/* /*
* Inherited * Inherited
*/ */
explicit ApplyBuffBehavior(const uint32_t behaviorId) : Behavior(behaviorId) explicit ApplyBuffBehavior(const uint32_t behaviorId) : Behavior(behaviorId) {
{
} }
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override; void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;

View File

@ -1,4 +1,4 @@
#include "AreaOfEffectBehavior.h" #include "AreaOfEffectBehavior.h"
#include <vector> #include <vector>
@ -10,14 +10,12 @@
#include "RebuildComponent.h" #include "RebuildComponent.h"
#include "DestroyableComponent.h" #include "DestroyableComponent.h"
void AreaOfEffectBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) void AreaOfEffectBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
{
uint32_t targetCount; uint32_t targetCount;
bitStream->Read(targetCount); bitStream->Read(targetCount);
if (targetCount > this->m_maxTargets) if (targetCount > this->m_maxTargets) {
{
return; return;
} }
@ -25,8 +23,7 @@ void AreaOfEffectBehavior::Handle(BehaviorContext* context, RakNet::BitStream* b
targets.reserve(targetCount); targets.reserve(targetCount);
for (auto i = 0u; i < targetCount; ++i) for (auto i = 0u; i < targetCount; ++i) {
{
LWOOBJID target; LWOOBJID target;
bitStream->Read(target); bitStream->Read(target);
@ -34,21 +31,18 @@ void AreaOfEffectBehavior::Handle(BehaviorContext* context, RakNet::BitStream* b
targets.push_back(target); targets.push_back(target);
} }
for (auto target : targets) for (auto target : targets) {
{
branch.target = target; branch.target = target;
this->m_action->Handle(context, bitStream, branch); this->m_action->Handle(context, bitStream, branch);
} }
} }
void AreaOfEffectBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) void AreaOfEffectBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
{
auto* self = EntityManager::Instance()->GetEntity(context->caster); auto* self = EntityManager::Instance()->GetEntity(context->caster);
if (self == nullptr) if (self == nullptr) {
{ Game::logger->Log("TacArcBehavior", "Invalid self for (%llu)!", context->originator);
Game::logger->Log("TacArcBehavior", "Invalid self for (%llu)!\n", context->originator);
return; return;
} }
@ -59,10 +53,8 @@ void AreaOfEffectBehavior::Calculate(BehaviorContext* context, RakNet::BitStream
auto* presetTarget = EntityManager::Instance()->GetEntity(branch.target); auto* presetTarget = EntityManager::Instance()->GetEntity(branch.target);
if (presetTarget != nullptr) if (presetTarget != nullptr) {
{ if (this->m_radius * this->m_radius >= Vector3::DistanceSquared(reference, presetTarget->GetPosition())) {
if (this->m_radius * this->m_radius >= Vector3::DistanceSquared(reference, presetTarget->GetPosition()))
{
targets.push_back(presetTarget); targets.push_back(presetTarget);
} }
} }
@ -75,44 +67,37 @@ void AreaOfEffectBehavior::Calculate(BehaviorContext* context, RakNet::BitStream
} }
// Gets all of the valid targets, passing in if should target enemies and friends // Gets all of the valid targets, passing in if should target enemies and friends
for (auto validTarget : context->GetValidTargets(m_ignoreFaction , includeFaction, m_TargetSelf == 1, m_targetEnemy == 1, m_targetFriend == 1)) for (auto validTarget : context->GetValidTargets(m_ignoreFaction, includeFaction, m_TargetSelf == 1, m_targetEnemy == 1, m_targetFriend == 1)) {
{
auto* entity = EntityManager::Instance()->GetEntity(validTarget); auto* entity = EntityManager::Instance()->GetEntity(validTarget);
if (entity == nullptr) if (entity == nullptr) {
{ Game::logger->Log("TacArcBehavior", "Invalid target (%llu) for (%llu)!", validTarget, context->originator);
Game::logger->Log("TacArcBehavior", "Invalid target (%llu) for (%llu)!\n", validTarget, context->originator);
continue; continue;
} }
if (std::find(targets.begin(), targets.end(), entity) != targets.end()) if (std::find(targets.begin(), targets.end(), entity) != targets.end()) {
{
continue; continue;
} }
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>(); auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
if (destroyableComponent == nullptr) if (destroyableComponent == nullptr) {
{
continue; continue;
} }
if (destroyableComponent->HasFaction(m_ignoreFaction)) if (destroyableComponent->HasFaction(m_ignoreFaction)) {
{
continue; continue;
} }
const auto distance = Vector3::DistanceSquared(reference, entity->GetPosition()); const auto distance = Vector3::DistanceSquared(reference, entity->GetPosition());
if (this->m_radius * this->m_radius >= distance && (this->m_maxTargets == 0 || targets.size() < this->m_maxTargets)) if (this->m_radius * this->m_radius >= distance && (this->m_maxTargets == 0 || targets.size() < this->m_maxTargets)) {
{
targets.push_back(entity); targets.push_back(entity);
} }
} }
std::sort(targets.begin(), targets.end(), [reference](Entity* a, Entity* b) std::sort(targets.begin(), targets.end(), [reference](Entity* a, Entity* b) {
{
const auto aDistance = Vector3::DistanceSquared(a->GetPosition(), reference); const auto aDistance = Vector3::DistanceSquared(a->GetPosition(), reference);
const auto bDistance = Vector3::DistanceSquared(b->GetPosition(), reference); const auto bDistance = Vector3::DistanceSquared(b->GetPosition(), reference);
@ -123,30 +108,26 @@ void AreaOfEffectBehavior::Calculate(BehaviorContext* context, RakNet::BitStream
bitStream->Write(size); bitStream->Write(size);
if (size == 0) if (size == 0) {
{
return; return;
} }
context->foundTarget = true; context->foundTarget = true;
for (auto* target : targets) for (auto* target : targets) {
{
bitStream->Write(target->GetObjectID()); bitStream->Write(target->GetObjectID());
PlayFx(u"cast", context->originator, target->GetObjectID()); PlayFx(u"cast", context->originator, target->GetObjectID());
} }
for (auto* target : targets) for (auto* target : targets) {
{
branch.target = target->GetObjectID(); branch.target = target->GetObjectID();
this->m_action->Calculate(context, bitStream, branch); this->m_action->Calculate(context, bitStream, branch);
} }
} }
void AreaOfEffectBehavior::Load() void AreaOfEffectBehavior::Load() {
{
this->m_action = GetAction("action"); this->m_action = GetAction("action");
this->m_radius = GetFloat("radius"); this->m_radius = GetFloat("radius");

View File

@ -1,4 +1,4 @@
#pragma once #pragma once
#include "Behavior.h" #include "Behavior.h"
class AreaOfEffectBehavior final : public Behavior class AreaOfEffectBehavior final : public Behavior
@ -23,8 +23,7 @@ public:
/* /*
* Inherited * Inherited
*/ */
explicit AreaOfEffectBehavior(const uint32_t behaviorId) : Behavior(behaviorId) explicit AreaOfEffectBehavior(const uint32_t behaviorId) : Behavior(behaviorId) {
{
} }
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override; void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;

View File

@ -1,51 +1,44 @@
#include "AttackDelayBehavior.h" #include "AttackDelayBehavior.h"
#include "BehaviorBranchContext.h" #include "BehaviorBranchContext.h"
#include "BehaviorContext.h" #include "BehaviorContext.h"
#include "Game.h" #include "Game.h"
#include "dLogger.h" #include "dLogger.h"
void AttackDelayBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) void AttackDelayBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) {
{
uint32_t handle; uint32_t handle;
bitStream->Read(handle); bitStream->Read(handle);
for (auto i = 0u; i < this->m_numIntervals; ++i) for (auto i = 0u; i < this->m_numIntervals; ++i) {
{
context->RegisterSyncBehavior(handle, this, branch); context->RegisterSyncBehavior(handle, this, branch);
} }
} }
void AttackDelayBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) void AttackDelayBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) {
{
const auto handle = context->GetUniqueSkillId(); const auto handle = context->GetUniqueSkillId();
bitStream->Write(handle); bitStream->Write(handle);
context->foundTarget = true; context->foundTarget = true;
for (auto i = 0u; i < this->m_numIntervals; ++i) for (auto i = 0u; i < this->m_numIntervals; ++i) {
{
const auto multiple = static_cast<float>(i + 1); const auto multiple = static_cast<float>(i + 1);
context->SyncCalculation(handle, this->m_delay * multiple, this, branch, m_ignoreInterrupts); context->SyncCalculation(handle, this->m_delay * multiple, this, branch, m_ignoreInterrupts);
} }
} }
void AttackDelayBehavior::Sync(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) void AttackDelayBehavior::Sync(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) {
{
this->m_action->Handle(context, bitStream, branch); this->m_action->Handle(context, bitStream, branch);
} }
void AttackDelayBehavior::SyncCalculation(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) void AttackDelayBehavior::SyncCalculation(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) {
{
PlayFx(u"cast", context->originator); PlayFx(u"cast", context->originator);
this->m_action->Calculate(context, bitStream, branch); this->m_action->Calculate(context, bitStream, branch);
} }
void AttackDelayBehavior::Load() void AttackDelayBehavior::Load() {
{
this->m_numIntervals = GetInt("num_intervals"); this->m_numIntervals = GetInt("num_intervals");
this->m_action = GetAction("action"); this->m_action = GetAction("action");
@ -54,8 +47,7 @@ void AttackDelayBehavior::Load()
this->m_ignoreInterrupts = GetBoolean("ignore_interrupts"); this->m_ignoreInterrupts = GetBoolean("ignore_interrupts");
if (this->m_numIntervals == 0) if (this->m_numIntervals == 0) {
{
this->m_numIntervals = 1; this->m_numIntervals = 1;
} }
} }

View File

@ -1,4 +1,4 @@
#pragma once #pragma once
#include "Behavior.h" #include "Behavior.h"
class AttackDelayBehavior final : public Behavior class AttackDelayBehavior final : public Behavior
@ -16,8 +16,7 @@ public:
* Inherited * Inherited
*/ */
explicit AttackDelayBehavior(const uint32_t behaviorId) : Behavior(behaviorId) explicit AttackDelayBehavior(const uint32_t behaviorId) : Behavior(behaviorId) {
{
} }
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override; void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;

View File

@ -1,4 +1,4 @@
#include "BasicAttackBehavior.h" #include "BasicAttackBehavior.h"
#include "BehaviorBranchContext.h" #include "BehaviorBranchContext.h"
#include "Game.h" #include "Game.h"
#include "dLogger.h" #include "dLogger.h"
@ -69,7 +69,7 @@ void BasicAttackBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bi
this->m_onSuccess->Handle(context, bitStream, branch); this->m_onSuccess->Handle(context, bitStream, branch);
break; break;
default: default:
Game::logger->Log("BasicAttackBehavior", "Unknown success state (%i)!\n", successState); Game::logger->Log("BasicAttackBehavior", "Unknown success state (%i)!", successState);
break; break;
} }
@ -79,7 +79,7 @@ void BasicAttackBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bi
void BasicAttackBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) { void BasicAttackBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
auto* self = EntityManager::Instance()->GetEntity(context->originator); auto* self = EntityManager::Instance()->GetEntity(context->originator);
if (self == nullptr) { if (self == nullptr) {
Game::logger->Log("BasicAttackBehavior", "Invalid self entity (%llu)!\n", context->originator); Game::logger->Log("BasicAttackBehavior", "Invalid self entity (%llu)!", context->originator);
return; return;
} }
@ -127,7 +127,7 @@ void BasicAttackBehavior::Calculate(BehaviorContext* context, RakNet::BitStream*
this->m_onSuccess->Calculate(context, bitStream, branch); this->m_onSuccess->Calculate(context, bitStream, branch);
break; break;
default: default:
Game::logger->Log("BasicAttackBehavior", "Unknown success state (%i)!\n", successState); Game::logger->Log("BasicAttackBehavior", "Unknown success state (%i)!", successState);
break; break;
} }

View File

@ -1,4 +1,4 @@
#pragma once #pragma once
#include "Behavior.h" #include "Behavior.h"
class BasicAttackBehavior final : public Behavior class BasicAttackBehavior final : public Behavior
@ -10,8 +10,7 @@ public:
Behavior* m_onSuccess; Behavior* m_onSuccess;
explicit BasicAttackBehavior(const uint32_t behaviorId) : Behavior(behaviorId) explicit BasicAttackBehavior(const uint32_t behaviorId) : Behavior(behaviorId) {
{
} }
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override; void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;

View File

@ -1,4 +1,4 @@
#include <sstream> #include <sstream>
#include <algorithm> #include <algorithm>
#include "Behavior.h" #include "Behavior.h"
@ -73,34 +73,28 @@
std::unordered_map<uint32_t, Behavior*> Behavior::Cache = {}; std::unordered_map<uint32_t, Behavior*> Behavior::Cache = {};
CDBehaviorParameterTable* Behavior::BehaviorParameterTable = nullptr; CDBehaviorParameterTable* Behavior::BehaviorParameterTable = nullptr;
Behavior* Behavior::GetBehavior(const uint32_t behaviorId) Behavior* Behavior::GetBehavior(const uint32_t behaviorId) {
{ if (BehaviorParameterTable == nullptr) {
if (BehaviorParameterTable == nullptr)
{
BehaviorParameterTable = CDClientManager::Instance()->GetTable<CDBehaviorParameterTable>("BehaviorParameter"); BehaviorParameterTable = CDClientManager::Instance()->GetTable<CDBehaviorParameterTable>("BehaviorParameter");
} }
const auto pair = Cache.find(behaviorId); const auto pair = Cache.find(behaviorId);
if (pair == Cache.end()) if (pair == Cache.end()) {
{
return nullptr; return nullptr;
} }
return static_cast<Behavior*>(pair->second); return static_cast<Behavior*>(pair->second);
} }
Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) {
{
auto* cached = GetBehavior(behaviorId); auto* cached = GetBehavior(behaviorId);
if (cached != nullptr) if (cached != nullptr) {
{
return cached; return cached;
} }
if (behaviorId == 0) if (behaviorId == 0) {
{
return new EmptyBehavior(0); return new EmptyBehavior(0);
} }
@ -108,8 +102,7 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId)
Behavior* behavior = nullptr; Behavior* behavior = nullptr;
switch (templateId) switch (templateId) {
{
case BehaviorTemplates::BEHAVIOR_EMPTY: break; case BehaviorTemplates::BEHAVIOR_EMPTY: break;
case BehaviorTemplates::BEHAVIOR_BASIC_ATTACK: case BehaviorTemplates::BEHAVIOR_BASIC_ATTACK:
behavior = new BasicAttackBehavior(behaviorId); behavior = new BasicAttackBehavior(behaviorId);
@ -269,13 +262,12 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId)
case BehaviorTemplates::BEHAVIOR_MOUNT: break; case BehaviorTemplates::BEHAVIOR_MOUNT: break;
case BehaviorTemplates::BEHAVIOR_SKILL_SET: break; case BehaviorTemplates::BEHAVIOR_SKILL_SET: break;
default: default:
//Game::logger->Log("Behavior", "Failed to load behavior with invalid template id (%i)!\n", templateId); //Game::logger->Log("Behavior", "Failed to load behavior with invalid template id (%i)!", templateId);
break; break;
} }
if (behavior == nullptr) if (behavior == nullptr) {
{ //Game::logger->Log("Behavior", "Failed to load unimplemented template id (%i)!", templateId);
//Game::logger->Log("Behavior", "Failed to load unimplemented template id (%i)!\n", templateId);
behavior = new EmptyBehavior(behaviorId); behavior = new EmptyBehavior(behaviorId);
} }
@ -298,26 +290,23 @@ BehaviorTemplates Behavior::GetBehaviorTemplate(const uint32_t behaviorId) {
} }
if (templateID == BehaviorTemplates::BEHAVIOR_EMPTY && behaviorId != 0) { if (templateID == BehaviorTemplates::BEHAVIOR_EMPTY && behaviorId != 0) {
Game::logger->Log("Behavior", "Failed to load behavior template with id (%i)!\n", behaviorId); Game::logger->Log("Behavior", "Failed to load behavior template with id (%i)!", behaviorId);
} }
return templateID; return templateID;
} }
// For use with enemies, to display the correct damage animations on the players // For use with enemies, to display the correct damage animations on the players
void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID secondary) void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID secondary) {
{
auto* targetEntity = EntityManager::Instance()->GetEntity(target); auto* targetEntity = EntityManager::Instance()->GetEntity(target);
if (targetEntity == nullptr) if (targetEntity == nullptr) {
{
return; return;
} }
const auto effectId = this->m_effectId; const auto effectId = this->m_effectId;
if (effectId == 0) if (effectId == 0) {
{
GameMessages::SendPlayFXEffect(targetEntity, -1, type, "", secondary, 1, 1, true); GameMessages::SendPlayFXEffect(targetEntity, -1, type, "", secondary, 1, 1, true);
return; return;
@ -327,23 +316,17 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID
const auto typeString = GeneralUtils::UTF16ToWTF8(type); const auto typeString = GeneralUtils::UTF16ToWTF8(type);
if (m_effectNames == nullptr) if (m_effectNames == nullptr) {
{
m_effectNames = new std::unordered_map<std::string, std::string>(); m_effectNames = new std::unordered_map<std::string, std::string>();
} } else {
else
{
const auto pair = m_effectNames->find(typeString); const auto pair = m_effectNames->find(typeString);
if (type.empty()) if (type.empty()) {
{
type = GeneralUtils::ASCIIToUTF16(*m_effectType); type = GeneralUtils::ASCIIToUTF16(*m_effectType);
} }
if (pair != m_effectNames->end()) if (pair != m_effectNames->end()) {
{ if (renderComponent == nullptr) {
if (renderComponent == nullptr)
{
GameMessages::SendPlayFXEffect(targetEntity, effectId, type, pair->second, secondary, 1, 1, true); GameMessages::SendPlayFXEffect(targetEntity, effectId, type, pair->second, secondary, 1, 1, true);
return; return;
@ -375,15 +358,13 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID
result = idQuery.execQuery(); result = idQuery.execQuery();
} }
if (result.eof() || result.fieldIsNull(0)) if (result.eof() || result.fieldIsNull(0)) {
{
return; return;
} }
const auto name = std::string(result.getStringField(0)); const auto name = std::string(result.getStringField(0));
if (type.empty()) if (type.empty()) {
{
const auto typeResult = result.getStringField(1); const auto typeResult = result.getStringField(1);
type = GeneralUtils::ASCIIToUTF16(typeResult); type = GeneralUtils::ASCIIToUTF16(typeResult);
@ -395,8 +376,7 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID
m_effectNames->insert_or_assign(typeString, name); m_effectNames->insert_or_assign(typeString, name);
if (renderComponent == nullptr) if (renderComponent == nullptr) {
{
GameMessages::SendPlayFXEffect(targetEntity, effectId, type, name, secondary, 1, 1, true); GameMessages::SendPlayFXEffect(targetEntity, effectId, type, name, secondary, 1, 1, true);
return; return;
@ -405,8 +385,7 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID
renderComponent->PlayEffect(effectId, type, name, secondary); renderComponent->PlayEffect(effectId, type, name, secondary);
} }
Behavior::Behavior(const uint32_t behaviorId) Behavior::Behavior(const uint32_t behaviorId) {
{
auto behaviorTemplateTable = CDClientManager::Instance()->GetTable<CDBehaviorTemplateTable>("BehaviorTemplate"); auto behaviorTemplateTable = CDClientManager::Instance()->GetTable<CDBehaviorTemplateTable>("BehaviorTemplate");
CDBehaviorTemplate templateInDatabase{}; CDBehaviorTemplate templateInDatabase{};
@ -430,9 +409,8 @@ Behavior::Behavior(const uint32_t behaviorId)
} }
// Make sure we do not proceed if we are trying to load an invalid behavior // Make sure we do not proceed if we are trying to load an invalid behavior
if (templateInDatabase.behaviorID == 0) if (templateInDatabase.behaviorID == 0) {
{ Game::logger->Log("Behavior", "Failed to load behavior with id (%i)!", behaviorId);
Game::logger->Log("Behavior", "Failed to load behavior with id (%i)!\n", behaviorId);
this->m_effectId = 0; this->m_effectId = 0;
this->m_effectHandle = nullptr; this->m_effectHandle = nullptr;
@ -449,40 +427,34 @@ Behavior::Behavior(const uint32_t behaviorId)
} }
float Behavior::GetFloat(const std::string& name, const float defaultValue) const float Behavior::GetFloat(const std::string& name, const float defaultValue) const {
{
// Get the behavior parameter entry and return its value. // Get the behavior parameter entry and return its value.
if (!BehaviorParameterTable) BehaviorParameterTable = CDClientManager::Instance()->GetTable<CDBehaviorParameterTable>("BehaviorParameter"); if (!BehaviorParameterTable) BehaviorParameterTable = CDClientManager::Instance()->GetTable<CDBehaviorParameterTable>("BehaviorParameter");
return BehaviorParameterTable->GetEntry(this->m_behaviorId, name, defaultValue); return BehaviorParameterTable->GetEntry(this->m_behaviorId, name, defaultValue);
} }
bool Behavior::GetBoolean(const std::string& name, const bool defaultValue) const bool Behavior::GetBoolean(const std::string& name, const bool defaultValue) const {
{
return GetFloat(name, defaultValue) > 0; return GetFloat(name, defaultValue) > 0;
} }
int32_t Behavior::GetInt(const std::string& name, const int defaultValue) const int32_t Behavior::GetInt(const std::string& name, const int defaultValue) const {
{
return static_cast<int32_t>(GetFloat(name, defaultValue)); return static_cast<int32_t>(GetFloat(name, defaultValue));
} }
Behavior* Behavior::GetAction(const std::string& name) const Behavior* Behavior::GetAction(const std::string& name) const {
{
const auto id = GetInt(name); const auto id = GetInt(name);
return CreateBehavior(id); return CreateBehavior(id);
} }
Behavior* Behavior::GetAction(float value) const Behavior* Behavior::GetAction(float value) const {
{
return CreateBehavior(static_cast<int32_t>(value)); return CreateBehavior(static_cast<int32_t>(value));
} }
std::map<std::string, float> Behavior::GetParameterNames() const std::map<std::string, float> Behavior::GetParameterNames() const {
{
std::map<std::string, float> templatesInDatabase; std::map<std::string, float> templatesInDatabase;
// Find behavior template by its behavior id. // Find behavior template by its behavior id.
/*if (!BehaviorParameterTable) BehaviorParameterTable = CDClientManager::Instance()->GetTable<CDBehaviorParameterTable>("BehaviorParameter"); /*if (!BehaviorParameterTable) BehaviorParameterTable = CDClientManager::Instance()->GetTable<CDBehaviorParameterTable>("BehaviorParameter");
@ -493,40 +465,31 @@ std::map<std::string, float> Behavior::GetParameterNames() const
return templatesInDatabase; return templatesInDatabase;
} }
void Behavior::Load() void Behavior::Load() {
{
} }
void Behavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) void Behavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
{
} }
void Behavior::Sync(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) void Behavior::Sync(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
{
} }
void Behavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch) void Behavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch) {
{
} }
void Behavior::Timer(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) void Behavior::Timer(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) {
{
} }
void Behavior::End(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) void Behavior::End(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) {
{
} }
void Behavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) void Behavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
{
} }
void Behavior::SyncCalculation(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) void Behavior::SyncCalculation(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
{
} }
Behavior::~Behavior() Behavior::~Behavior() {
{
delete m_effectNames; delete m_effectNames;
delete m_effectType; delete m_effectType;
delete m_effectHandle; delete m_effectHandle;

View File

@ -1,4 +1,4 @@
#pragma once #pragma once
#include <map> #include <map>
#include <string> #include <string>

View File

@ -1,13 +1,11 @@
#include "BehaviorBranchContext.h" #include "BehaviorBranchContext.h"
BehaviorBranchContext::BehaviorBranchContext() BehaviorBranchContext::BehaviorBranchContext() {
{
this->isProjectile = false; this->isProjectile = false;
} }
BehaviorBranchContext::BehaviorBranchContext(const LWOOBJID target, const float duration, const NiPoint3& referencePosition) BehaviorBranchContext::BehaviorBranchContext(const LWOOBJID target, const float duration, const NiPoint3& referencePosition) {
{
this->target = target; this->target = target;
this->duration = duration; this->duration = duration;
this->referencePosition = referencePosition; this->referencePosition = referencePosition;

View File

@ -1,4 +1,4 @@
#pragma once #pragma once
#include "dCommonVars.h" #include "dCommonVars.h"
#include "NiPoint3.h" #include "NiPoint3.h"

View File

@ -1,4 +1,4 @@
#include "BehaviorContext.h" #include "BehaviorContext.h"
#include "Behavior.h" #include "Behavior.h"
#include "BehaviorBranchContext.h" #include "BehaviorBranchContext.h"
#include "EntityManager.h" #include "EntityManager.h"
@ -15,34 +15,28 @@
#include "PhantomPhysicsComponent.h" #include "PhantomPhysicsComponent.h"
#include "RebuildComponent.h" #include "RebuildComponent.h"
BehaviorSyncEntry::BehaviorSyncEntry() BehaviorSyncEntry::BehaviorSyncEntry() {
{
} }
BehaviorTimerEntry::BehaviorTimerEntry() BehaviorTimerEntry::BehaviorTimerEntry() {
{
} }
BehaviorEndEntry::BehaviorEndEntry() BehaviorEndEntry::BehaviorEndEntry() {
{
} }
uint32_t BehaviorContext::GetUniqueSkillId() const uint32_t BehaviorContext::GetUniqueSkillId() const {
{
auto* entity = EntityManager::Instance()->GetEntity(this->originator); auto* entity = EntityManager::Instance()->GetEntity(this->originator);
if (entity == nullptr) if (entity == nullptr) {
{ Game::logger->Log("BehaviorContext", "Invalid entity for (%llu)!", this->originator);
Game::logger->Log("BehaviorContext", "Invalid entity for (%llu)!\n", this->originator);
return 0; return 0;
} }
auto* component = entity->GetComponent<SkillComponent>(); auto* component = entity->GetComponent<SkillComponent>();
if (component == nullptr) if (component == nullptr) {
{ Game::logger->Log("BehaviorContext", "No skill component attached to (%llu)!", this->originator);;
Game::logger->Log("BehaviorContext", "No skill component attached to (%llu)!\n", this->originator);;
return 0; return 0;
} }
@ -51,8 +45,7 @@ uint32_t BehaviorContext::GetUniqueSkillId() const
} }
void BehaviorContext::RegisterSyncBehavior(const uint32_t syncId, Behavior* behavior, const BehaviorBranchContext& branchContext) void BehaviorContext::RegisterSyncBehavior(const uint32_t syncId, Behavior* behavior, const BehaviorBranchContext& branchContext) {
{
auto entry = BehaviorSyncEntry(); auto entry = BehaviorSyncEntry();
entry.handle = syncId; entry.handle = syncId;
@ -62,8 +55,7 @@ void BehaviorContext::RegisterSyncBehavior(const uint32_t syncId, Behavior* beha
this->syncEntries.push_back(entry); this->syncEntries.push_back(entry);
} }
void BehaviorContext::RegisterTimerBehavior(Behavior* behavior, const BehaviorBranchContext& branchContext, const LWOOBJID second) void BehaviorContext::RegisterTimerBehavior(Behavior* behavior, const BehaviorBranchContext& branchContext, const LWOOBJID second) {
{
BehaviorTimerEntry entry; BehaviorTimerEntry entry;
entry.time = branchContext.duration; entry.time = branchContext.duration;
@ -74,8 +66,7 @@ void BehaviorContext::RegisterTimerBehavior(Behavior* behavior, const BehaviorBr
this->timerEntries.push_back(entry); this->timerEntries.push_back(entry);
} }
void BehaviorContext::RegisterEndBehavior(Behavior* behavior, const BehaviorBranchContext& branchContext, const LWOOBJID second) void BehaviorContext::RegisterEndBehavior(Behavior* behavior, const BehaviorBranchContext& branchContext, const LWOOBJID second) {
{
BehaviorEndEntry entry; BehaviorEndEntry entry;
entry.behavior = behavior; entry.behavior = behavior;
@ -86,20 +77,16 @@ void BehaviorContext::RegisterEndBehavior(Behavior* behavior, const BehaviorBran
this->endEntries.push_back(entry); this->endEntries.push_back(entry);
} }
void BehaviorContext::ScheduleUpdate(const LWOOBJID id) void BehaviorContext::ScheduleUpdate(const LWOOBJID id) {
{ if (std::find(this->scheduledUpdates.begin(), this->scheduledUpdates.end(), id) != this->scheduledUpdates.end()) {
if (std::find(this->scheduledUpdates.begin(), this->scheduledUpdates.end(), id) != this->scheduledUpdates.end())
{
return; return;
} }
this->scheduledUpdates.push_back(id); this->scheduledUpdates.push_back(id);
} }
void BehaviorContext::ExecuteUpdates() void BehaviorContext::ExecuteUpdates() {
{ for (const auto& id : this->scheduledUpdates) {
for (const auto& id : this->scheduledUpdates)
{
auto* entity = EntityManager::Instance()->GetEntity(id); auto* entity = EntityManager::Instance()->GetEntity(id);
if (entity == nullptr) continue; if (entity == nullptr) continue;
@ -110,20 +97,17 @@ void BehaviorContext::ExecuteUpdates()
this->scheduledUpdates.clear(); this->scheduledUpdates.clear();
} }
void BehaviorContext::SyncBehavior(const uint32_t syncId, RakNet::BitStream* bitStream) void BehaviorContext::SyncBehavior(const uint32_t syncId, RakNet::BitStream* bitStream) {
{
BehaviorSyncEntry entry; BehaviorSyncEntry entry;
auto found = false; auto found = false;
/* /*
* There may be more than one of each handle * There may be more than one of each handle
*/ */
for (auto i = 0u; i < this->syncEntries.size(); ++i) for (auto i = 0u; i < this->syncEntries.size(); ++i) {
{
const auto syncEntry = this->syncEntries.at(i); const auto syncEntry = this->syncEntries.at(i);
if (syncEntry.handle == syncId) if (syncEntry.handle == syncId) {
{
found = true; found = true;
entry = syncEntry; entry = syncEntry;
@ -133,9 +117,8 @@ void BehaviorContext::SyncBehavior(const uint32_t syncId, RakNet::BitStream* bit
} }
} }
if (!found) if (!found) {
{ Game::logger->Log("BehaviorContext", "Failed to find behavior sync entry with sync id (%i)!", syncId);
Game::logger->Log("BehaviorContext", "Failed to find behavior sync entry with sync id (%i)!\n", syncId);
return; return;
} }
@ -143,9 +126,8 @@ void BehaviorContext::SyncBehavior(const uint32_t syncId, RakNet::BitStream* bit
auto* behavior = entry.behavior; auto* behavior = entry.behavior;
const auto branch = entry.branchContext; const auto branch = entry.branchContext;
if (behavior == nullptr) if (behavior == nullptr) {
{ Game::logger->Log("BehaviorContext", "Invalid behavior for sync id (%i)!", syncId);
Game::logger->Log("BehaviorContext", "Invalid behavior for sync id (%i)!\n", syncId);
return; return;
} }
@ -154,21 +136,17 @@ void BehaviorContext::SyncBehavior(const uint32_t syncId, RakNet::BitStream* bit
} }
void BehaviorContext::Update(const float deltaTime) void BehaviorContext::Update(const float deltaTime) {
{ for (auto i = 0u; i < this->timerEntries.size(); ++i) {
for (auto i = 0u; i < this->timerEntries.size(); ++i)
{
auto entry = this->timerEntries.at(i); auto entry = this->timerEntries.at(i);
if (entry.time > 0) if (entry.time > 0) {
{
entry.time -= deltaTime; entry.time -= deltaTime;
this->timerEntries[i] = entry; this->timerEntries[i] = entry;
} }
if (entry.time > 0) if (entry.time > 0) {
{
continue; continue;
} }
@ -177,10 +155,8 @@ void BehaviorContext::Update(const float deltaTime)
std::vector<BehaviorTimerEntry> valid; std::vector<BehaviorTimerEntry> valid;
for (const auto& entry : this->timerEntries) for (const auto& entry : this->timerEntries) {
{ if (entry.time <= 0) {
if (entry.time <= 0)
{
continue; continue;
} }
@ -191,8 +167,7 @@ void BehaviorContext::Update(const float deltaTime)
} }
void BehaviorContext::SyncCalculation(const uint32_t syncId, const float time, Behavior* behavior, const BehaviorBranchContext& branch, const bool ignoreInterrupts) void BehaviorContext::SyncCalculation(const uint32_t syncId, const float time, Behavior* behavior, const BehaviorBranchContext& branch, const bool ignoreInterrupts) {
{
BehaviorSyncEntry entry; BehaviorSyncEntry entry;
entry.behavior = behavior; entry.behavior = behavior;
@ -204,14 +179,11 @@ void BehaviorContext::SyncCalculation(const uint32_t syncId, const float time, B
this->syncEntries.push_back(entry); this->syncEntries.push_back(entry);
} }
void BehaviorContext::InvokeEnd(const uint32_t id) void BehaviorContext::InvokeEnd(const uint32_t id) {
{
std::vector<BehaviorEndEntry> entries; std::vector<BehaviorEndEntry> entries;
for (const auto& entry : this->endEntries) for (const auto& entry : this->endEntries) {
{ if (entry.start == id) {
if (entry.start == id)
{
entry.behavior->End(this, entry.branchContext, entry.second); entry.behavior->End(this, entry.branchContext, entry.second);
continue; continue;
@ -223,23 +195,19 @@ void BehaviorContext::InvokeEnd(const uint32_t id)
this->endEntries = entries; this->endEntries = entries;
} }
bool BehaviorContext::CalculateUpdate(const float deltaTime) bool BehaviorContext::CalculateUpdate(const float deltaTime) {
{
auto any = false; auto any = false;
for (auto i = 0u; i < this->syncEntries.size(); ++i) for (auto i = 0u; i < this->syncEntries.size(); ++i) {
{
auto entry = this->syncEntries.at(i); auto entry = this->syncEntries.at(i);
if (entry.time > 0) if (entry.time > 0) {
{
entry.time -= deltaTime; entry.time -= deltaTime;
this->syncEntries[i] = entry; this->syncEntries[i] = entry;
} }
if (entry.time > 0) if (entry.time > 0) {
{
any = true; any = true;
continue; continue;
@ -257,8 +225,7 @@ bool BehaviorContext::CalculateUpdate(const float deltaTime)
// Calculate sync // Calculate sync
entry.behavior->SyncCalculation(this, bitStream, entry.branchContext); entry.behavior->SyncCalculation(this, bitStream, entry.branchContext);
if (!clientInitalized) if (!clientInitalized) {
{
echo.sBitStream.assign((char*)bitStream->GetData(), bitStream->GetNumberOfBytesUsed()); echo.sBitStream.assign((char*)bitStream->GetData(), bitStream->GetNumberOfBytesUsed());
// Write message // Write message
@ -278,10 +245,8 @@ bool BehaviorContext::CalculateUpdate(const float deltaTime)
std::vector<BehaviorSyncEntry> valid; std::vector<BehaviorSyncEntry> valid;
for (const auto& entry : this->syncEntries) for (const auto& entry : this->syncEntries) {
{ if (entry.time <= 0) {
if (entry.time <= 0)
{
continue; continue;
} }
@ -293,12 +258,10 @@ bool BehaviorContext::CalculateUpdate(const float deltaTime)
return any; return any;
} }
void BehaviorContext::Interrupt() void BehaviorContext::Interrupt() {
{
std::vector<BehaviorSyncEntry> keptSync{}; std::vector<BehaviorSyncEntry> keptSync{};
for (const auto& entry : this->syncEntries) for (const auto& entry : this->syncEntries) {
{
if (!entry.ignoreInterrupts) continue; if (!entry.ignoreInterrupts) continue;
keptSync.push_back(entry); keptSync.push_back(entry);
@ -307,15 +270,12 @@ void BehaviorContext::Interrupt()
this->syncEntries = keptSync; this->syncEntries = keptSync;
} }
void BehaviorContext::Reset() void BehaviorContext::Reset() {
{ for (const auto& entry : this->timerEntries) {
for (const auto& entry : this->timerEntries)
{
entry.behavior->Timer(this, entry.branchContext, entry.second); entry.behavior->Timer(this, entry.branchContext, entry.second);
} }
for (const auto& entry : this->endEntries) for (const auto& entry : this->endEntries) {
{
entry.behavior->End(this, entry.branchContext, entry.second); entry.behavior->End(this, entry.branchContext, entry.second);
} }
@ -325,27 +285,22 @@ void BehaviorContext::Reset()
this->scheduledUpdates.clear(); this->scheduledUpdates.clear();
} }
std::vector<LWOOBJID> BehaviorContext::GetValidTargets(int32_t ignoreFaction, int32_t includeFaction, bool targetSelf, bool targetEnemy, bool targetFriend) const std::vector<LWOOBJID> BehaviorContext::GetValidTargets(int32_t ignoreFaction, int32_t includeFaction, bool targetSelf, bool targetEnemy, bool targetFriend) const {
{
auto* entity = EntityManager::Instance()->GetEntity(this->caster); auto* entity = EntityManager::Instance()->GetEntity(this->caster);
std::vector<LWOOBJID> targets; std::vector<LWOOBJID> targets;
if (entity == nullptr) if (entity == nullptr) {
{ Game::logger->Log("BehaviorContext", "Invalid entity for (%llu)!", this->originator);
Game::logger->Log("BehaviorContext", "Invalid entity for (%llu)!\n", this->originator);
return targets; return targets;
} }
if (!ignoreFaction && !includeFaction) if (!ignoreFaction && !includeFaction) {
{ for (auto entry : entity->GetTargetsInPhantom()) {
for (auto entry : entity->GetTargetsInPhantom())
{
auto* instance = EntityManager::Instance()->GetEntity(entry); auto* instance = EntityManager::Instance()->GetEntity(entry);
if (instance == nullptr) if (instance == nullptr) {
{
continue; continue;
} }
@ -353,21 +308,17 @@ std::vector<LWOOBJID> BehaviorContext::GetValidTargets(int32_t ignoreFaction, in
} }
} }
if (ignoreFaction || includeFaction || (!entity->HasComponent(COMPONENT_TYPE_PHANTOM_PHYSICS) && targets.empty())) if (ignoreFaction || includeFaction || (!entity->HasComponent(COMPONENT_TYPE_PHANTOM_PHYSICS) && targets.empty())) {
{
DestroyableComponent* destroyableComponent; DestroyableComponent* destroyableComponent;
if (!entity->TryGetComponent(COMPONENT_TYPE_DESTROYABLE, destroyableComponent)) if (!entity->TryGetComponent(COMPONENT_TYPE_DESTROYABLE, destroyableComponent)) {
{
return targets; return targets;
} }
auto entities = EntityManager::Instance()->GetEntitiesByComponent(COMPONENT_TYPE_CONTROLLABLE_PHYSICS); auto entities = EntityManager::Instance()->GetEntitiesByComponent(COMPONENT_TYPE_CONTROLLABLE_PHYSICS);
for (auto* candidate : entities) for (auto* candidate : entities) {
{
const auto id = candidate->GetObjectID(); const auto id = candidate->GetObjectID();
if ((id != entity->GetObjectID() || targetSelf) && destroyableComponent->CheckValidity(id, ignoreFaction || includeFaction, targetEnemy, targetFriend)) if ((id != entity->GetObjectID() || targetSelf) && destroyableComponent->CheckValidity(id, ignoreFaction || includeFaction, targetEnemy, targetFriend)) {
{
targets.push_back(id); targets.push_back(id);
} }
} }
@ -377,23 +328,18 @@ std::vector<LWOOBJID> BehaviorContext::GetValidTargets(int32_t ignoreFaction, in
} }
BehaviorContext::BehaviorContext(const LWOOBJID originator, const bool calculation) BehaviorContext::BehaviorContext(const LWOOBJID originator, const bool calculation) {
{
this->originator = originator; this->originator = originator;
this->syncEntries = {}; this->syncEntries = {};
this->timerEntries = {}; this->timerEntries = {};
if (calculation) if (calculation) {
{
this->skillUId = GetUniqueSkillId(); this->skillUId = GetUniqueSkillId();
} } else {
else
{
this->skillUId = 0; this->skillUId = 0;
} }
} }
BehaviorContext::~BehaviorContext() BehaviorContext::~BehaviorContext() {
{
Reset(); Reset();
} }

View File

@ -1,4 +1,4 @@
#pragma once #pragma once
#include "RakPeerInterface.h" #include "RakPeerInterface.h"
#include "dCommonVars.h" #include "dCommonVars.h"

View File

@ -1,4 +1,4 @@
#pragma once #pragma once
#ifndef BEHAVIORSLOT_H #ifndef BEHAVIORSLOT_H
#define BEHAVIORSLOT_H #define BEHAVIORSLOT_H

View File

@ -1 +1 @@
#include "BehaviorTemplates.h" #include "BehaviorTemplates.h"

View File

@ -1,4 +1,4 @@
#pragma once #pragma once
enum class BehaviorTemplates : unsigned int { enum class BehaviorTemplates : unsigned int {
BEHAVIOR_EMPTY, // Not a real behavior, indicates invalid behaviors BEHAVIOR_EMPTY, // Not a real behavior, indicates invalid behaviors

View File

@ -1,4 +1,4 @@
#include "BlockBehavior.h" #include "BlockBehavior.h"
#include "BehaviorContext.h" #include "BehaviorContext.h"
#include "BehaviorBranchContext.h" #include "BehaviorBranchContext.h"
@ -7,52 +7,43 @@
#include "dLogger.h" #include "dLogger.h"
#include "DestroyableComponent.h" #include "DestroyableComponent.h"
void BlockBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) void BlockBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
{
const auto target = context->originator; const auto target = context->originator;
auto* entity = EntityManager::Instance()->GetEntity(target); auto* entity = EntityManager::Instance()->GetEntity(target);
if (entity == nullptr) if (entity == nullptr) {
{ Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!", branch.target);
Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!\n", branch.target);
return; return;
} }
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>(); auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
if (destroyableComponent == nullptr) if (destroyableComponent == nullptr) {
{
return; return;
} }
destroyableComponent->SetAttacksToBlock(this->m_numAttacksCanBlock); destroyableComponent->SetAttacksToBlock(this->m_numAttacksCanBlock);
if (branch.start > 0) if (branch.start > 0) {
{
context->RegisterEndBehavior(this, branch); context->RegisterEndBehavior(this, branch);
} } else if (branch.duration > 0) {
else if (branch.duration > 0)
{
context->RegisterTimerBehavior(this, branch); context->RegisterTimerBehavior(this, branch);
} }
} }
void BlockBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) void BlockBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
{
Handle(context, bitStream, branch); Handle(context, bitStream, branch);
} }
void BlockBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch) void BlockBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch) {
{
const auto target = context->originator; const auto target = context->originator;
auto* entity = EntityManager::Instance()->GetEntity(target); auto* entity = EntityManager::Instance()->GetEntity(target);
if (entity == nullptr) if (entity == nullptr) {
{ Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!", branch.target);
Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!\n", branch.target);
return; return;
} }
@ -61,25 +52,21 @@ void BlockBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branc
destroyableComponent->SetAttacksToBlock(this->m_numAttacksCanBlock); destroyableComponent->SetAttacksToBlock(this->m_numAttacksCanBlock);
if (destroyableComponent == nullptr) if (destroyableComponent == nullptr) {
{
return; return;
} }
destroyableComponent->SetAttacksToBlock(0); destroyableComponent->SetAttacksToBlock(0);
} }
void BlockBehavior::Timer(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) void BlockBehavior::Timer(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) {
{
UnCast(context, branch); UnCast(context, branch);
} }
void BlockBehavior::End(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) void BlockBehavior::End(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) {
{
UnCast(context, branch); UnCast(context, branch);
} }
void BlockBehavior::Load() void BlockBehavior::Load() {
{
this->m_numAttacksCanBlock = GetInt("num_attacks_can_block"); this->m_numAttacksCanBlock = GetInt("num_attacks_can_block");
} }

View File

@ -1,4 +1,4 @@
#pragma once #pragma once
#include "Behavior.h" #include "Behavior.h"
class BlockBehavior final : public Behavior class BlockBehavior final : public Behavior
@ -10,8 +10,7 @@ public:
* Inherited * Inherited
*/ */
explicit BlockBehavior(const uint32_t behaviorId) : Behavior(behaviorId) explicit BlockBehavior(const uint32_t behaviorId) : Behavior(behaviorId) {
{
} }
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override; void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;

View File

@ -1,4 +1,4 @@
#include "BuffBehavior.h" #include "BuffBehavior.h"
#include "BehaviorContext.h" #include "BehaviorContext.h"
#include "BehaviorBranchContext.h" #include "BehaviorBranchContext.h"
@ -7,24 +7,21 @@
#include "dLogger.h" #include "dLogger.h"
#include "DestroyableComponent.h" #include "DestroyableComponent.h"
void BuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) void BuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
{
const auto target = branch.target != LWOOBJID_EMPTY ? branch.target : context->originator; const auto target = branch.target != LWOOBJID_EMPTY ? branch.target : context->originator;
auto* entity = EntityManager::Instance()->GetEntity(target); auto* entity = EntityManager::Instance()->GetEntity(target);
if (entity == nullptr) if (entity == nullptr) {
{ Game::logger->Log("BuffBehavior", "Invalid target (%llu)!", target);
Game::logger->Log("BuffBehavior", "Invalid target (%llu)!\n", target);
return; return;
} }
auto* component = entity->GetComponent<DestroyableComponent>(); auto* component = entity->GetComponent<DestroyableComponent>();
if (component == nullptr) if (component == nullptr) {
{ Game::logger->Log("BuffBehavior", "Invalid target, no destroyable component (%llu)!", target);
Game::logger->Log("BuffBehavior", "Invalid target, no destroyable component (%llu)!\n", target);
return; return;
} }
@ -35,37 +32,30 @@ void BuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream
EntityManager::Instance()->SerializeEntity(entity); EntityManager::Instance()->SerializeEntity(entity);
if (!context->unmanaged) if (!context->unmanaged) {
{ if (branch.duration > 0) {
if (branch.duration > 0)
{
context->RegisterTimerBehavior(this, branch); context->RegisterTimerBehavior(this, branch);
} } else if (branch.start > 0) {
else if (branch.start > 0)
{
context->RegisterEndBehavior(this, branch); context->RegisterEndBehavior(this, branch);
} }
} }
} }
void BuffBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch) void BuffBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch) {
{
const auto target = branch.target != LWOOBJID_EMPTY ? branch.target : context->originator; const auto target = branch.target != LWOOBJID_EMPTY ? branch.target : context->originator;
auto* entity = EntityManager::Instance()->GetEntity(target); auto* entity = EntityManager::Instance()->GetEntity(target);
if (entity == nullptr) if (entity == nullptr) {
{ Game::logger->Log("BuffBehavior", "Invalid target (%llu)!", target);
Game::logger->Log("BuffBehavior", "Invalid target (%llu)!\n", target);
return; return;
} }
auto* component = entity->GetComponent<DestroyableComponent>(); auto* component = entity->GetComponent<DestroyableComponent>();
if (component == nullptr) if (component == nullptr) {
{ Game::logger->Log("BuffBehavior", "Invalid target, no destroyable component (%llu)!", target);
Game::logger->Log("BuffBehavior", "Invalid target, no destroyable component (%llu)!\n", target);
return; return;
} }
@ -77,18 +67,15 @@ void BuffBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch
EntityManager::Instance()->SerializeEntity(entity); EntityManager::Instance()->SerializeEntity(entity);
} }
void BuffBehavior::Timer(BehaviorContext* context, const BehaviorBranchContext branch, LWOOBJID second) void BuffBehavior::Timer(BehaviorContext* context, const BehaviorBranchContext branch, LWOOBJID second) {
{
UnCast(context, branch); UnCast(context, branch);
} }
void BuffBehavior::End(BehaviorContext* context, const BehaviorBranchContext branch, LWOOBJID second) void BuffBehavior::End(BehaviorContext* context, const BehaviorBranchContext branch, LWOOBJID second) {
{
UnCast(context, branch); UnCast(context, branch);
} }
void BuffBehavior::Load() void BuffBehavior::Load() {
{
this->m_health = GetInt("life"); this->m_health = GetInt("life");
this->m_armor = GetInt("armor"); this->m_armor = GetInt("armor");

View File

@ -1,4 +1,4 @@
#pragma once #pragma once
#include "Behavior.h" #include "Behavior.h"
class BuffBehavior final : public Behavior class BuffBehavior final : public Behavior
@ -13,8 +13,7 @@ public:
/* /*
* Inherited * Inherited
*/ */
explicit BuffBehavior(const uint32_t behaviorId) : Behavior(behaviorId) explicit BuffBehavior(const uint32_t behaviorId) : Behavior(behaviorId) {
{
} }
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override; void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;

View File

@ -8,18 +8,16 @@
#include "dLogger.h" #include "dLogger.h"
#include "PossessableComponent.h" #include "PossessableComponent.h"
void CarBoostBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) void CarBoostBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
{
GameMessages::SendVehicleAddPassiveBoostAction(branch.target, UNASSIGNED_SYSTEM_ADDRESS); GameMessages::SendVehicleAddPassiveBoostAction(branch.target, UNASSIGNED_SYSTEM_ADDRESS);
auto* entity = EntityManager::Instance()->GetEntity(context->originator); auto* entity = EntityManager::Instance()->GetEntity(context->originator);
if (entity == nullptr) if (entity == nullptr) {
{
return; return;
} }
Game::logger->Log("Car boost", "Activating car boost!\n"); Game::logger->Log("Car boost", "Activating car boost!");
auto* possessableComponent = entity->GetComponent<PossessableComponent>(); auto* possessableComponent = entity->GetComponent<PossessableComponent>();
if (possessableComponent != nullptr) { if (possessableComponent != nullptr) {
@ -29,7 +27,7 @@ void CarBoostBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitSt
auto* characterComponent = possessor->GetComponent<CharacterComponent>(); auto* characterComponent = possessor->GetComponent<CharacterComponent>();
if (characterComponent != nullptr) { if (characterComponent != nullptr) {
Game::logger->Log("Car boost", "Tracking car boost!\n"); Game::logger->Log("Car boost", "Tracking car boost!");
characterComponent->UpdatePlayerStatistic(RacingCarBoostsActivated); characterComponent->UpdatePlayerStatistic(RacingCarBoostsActivated);
} }
} }
@ -43,8 +41,7 @@ void CarBoostBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitSt
}); });
} }
void CarBoostBehavior::Load() void CarBoostBehavior::Load() {
{
m_Action = GetAction("action"); m_Action = GetAction("action");
m_Time = GetFloat("time"); m_Time = GetFloat("time");

View File

@ -14,8 +14,7 @@ public:
* Inherited * Inherited
*/ */
explicit CarBoostBehavior(const uint32_t behaviorId) : Behavior(behaviorId) explicit CarBoostBehavior(const uint32_t behaviorId) : Behavior(behaviorId) {
{
} }
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override; void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;

View File

@ -1,24 +1,21 @@
#include "ChainBehavior.h" #include "ChainBehavior.h"
#include "BehaviorBranchContext.h" #include "BehaviorBranchContext.h"
#include "Game.h" #include "Game.h"
#include "dLogger.h" #include "dLogger.h"
void ChainBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) void ChainBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) {
{
uint32_t chain_index; uint32_t chain_index;
bitStream->Read(chain_index); bitStream->Read(chain_index);
chain_index--; chain_index--;
if (chain_index < this->m_behaviors.size()) if (chain_index < this->m_behaviors.size()) {
{
this->m_behaviors.at(chain_index)->Handle(context, bitStream, branch); this->m_behaviors.at(chain_index)->Handle(context, bitStream, branch);
} }
} }
void ChainBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) void ChainBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) {
{
bitStream->Write(1); bitStream->Write(1);
this->m_behaviors.at(0)->Calculate(context, bitStream, branch); this->m_behaviors.at(0)->Calculate(context, bitStream, branch);

View File

@ -1,4 +1,4 @@
#pragma once #pragma once
#include "Behavior.h" #include "Behavior.h"
@ -13,8 +13,7 @@ public:
* Inherited * Inherited
*/ */
explicit ChainBehavior(const uint32_t behaviorId) : Behavior(behaviorId) explicit ChainBehavior(const uint32_t behaviorId) : Behavior(behaviorId) {
{
} }
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override; void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;

View File

@ -4,12 +4,10 @@
#include "EntityManager.h" #include "EntityManager.h"
#include "BaseCombatAIComponent.h" #include "BaseCombatAIComponent.h"
void ChangeOrientationBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) void ChangeOrientationBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
{
} }
void ChangeOrientationBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) void ChangeOrientationBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
{
if (!m_ToTarget) return; // TODO: Add the other arguments to this behavior if (!m_ToTarget) return; // TODO: Add the other arguments to this behavior
auto* self = EntityManager::Instance()->GetEntity(context->originator); auto* self = EntityManager::Instance()->GetEntity(context->originator);
@ -20,8 +18,7 @@ void ChangeOrientationBehavior::Calculate(BehaviorContext* context, RakNet::BitS
const auto source = self->GetPosition(); const auto source = self->GetPosition();
const auto destination = self->GetPosition(); const auto destination = self->GetPosition();
if (m_OrientCaster) if (m_OrientCaster) {
{
auto* baseCombatAIComponent = self->GetComponent<BaseCombatAIComponent>(); auto* baseCombatAIComponent = self->GetComponent<BaseCombatAIComponent>();
/*if (baseCombatAIComponent != nullptr) /*if (baseCombatAIComponent != nullptr)
@ -34,17 +31,14 @@ void ChangeOrientationBehavior::Calculate(BehaviorContext* context, RakNet::BitS
} }
EntityManager::Instance()->SerializeEntity(self); EntityManager::Instance()->SerializeEntity(self);
} } else {
else
{
other->SetRotation(NiQuaternion::LookAt(destination, source)); other->SetRotation(NiQuaternion::LookAt(destination, source));
EntityManager::Instance()->SerializeEntity(other); EntityManager::Instance()->SerializeEntity(other);
} }
} }
void ChangeOrientationBehavior::Load() void ChangeOrientationBehavior::Load() {
{
m_OrientCaster = GetBoolean("orient_caster"); m_OrientCaster = GetBoolean("orient_caster");
m_ToTarget = GetBoolean("to_target"); m_ToTarget = GetBoolean("to_target");
} }

View File

@ -14,8 +14,7 @@ public:
* Inherited * Inherited
*/ */
explicit ChangeOrientationBehavior(const uint32_t behaviorId) : Behavior(behaviorId) explicit ChangeOrientationBehavior(const uint32_t behaviorId) : Behavior(behaviorId) {
{
} }
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override; void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;

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