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

View File

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

View File

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

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/).
Please use [.editorconfig](https://editorconfig.org/#pre-installed) with your preferred IDE.
And run:
```bash
git config blame.ignoreRevsFile .git-blame-ignore-revs
```
to ignore the gitblame of mass formatting commits
## Coding Style
This project has gone through multiple iterations of coding style. In the code you'll find a number of different coding styles in use. What follows is the preferred style for this project.

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.
```
git submodule init
git submodule update
git submodule update --init --recursive
```
**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.
### Prerequisites
**Clone the repository**
#### Clone the repository
```bash
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.
@ -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.
### Using Docker
Refer to [Docker.md](/Docker.md).
For Windows, refer to [Docker_Windows.md](/Docker_Windows.md).
### 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`.
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:
@ -65,8 +70,8 @@ cd build
# Run CMake to generate make files
cmake ..
# Run make to build the project. To build utilizing multiple cores, append `-j` and the amount of cores to utilize, for example `make -j8`
make
# To build utilizing multiple cores, append `-j` and the amount of cores to utilize, for example `cmake --build . --config Release -j8'
cmake --build . --config Release
```
### MacOS builds
@ -88,7 +93,7 @@ cmake --build . --config Release
### 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.
**Build the repository**
#### Build the repository
```batch
:: Create the build directory
mkdir build
@ -100,7 +105,7 @@ cmake ..
:: Run CMake with build flag to build
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
:: Create the build directory
mkdir build
@ -116,13 +121,13 @@ cmake --build . --config Release
### Windows builds (WSL)
This section will go through how to install [WSL](https://docs.microsoft.com/en-us/windows/wsl/install) and building in a Linux environment under Windows. WSL requires Windows 10 version 2004 and higher (Build 19041 and higher) or Windows 11.
**Open the Command Prompt application with Administrator permissions and run the following:**
#### Open the Command Prompt application with Administrator permissions and run the following:
```bash
# Installing Windows Subsystem for Linux
wsl --install
```
**Open the Ubuntu application and run the following:**
#### Open the Ubuntu application and run the following:
```bash
# Make sure the install is up to date
apt update && apt upgrade
@ -154,7 +159,7 @@ now follow the build section for your system
### 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.
@ -177,20 +182,20 @@ shasum -a 256 <file>
certutil -hashfile <file> SHA256
```
**Unpacking the client**
#### Unpacking the client
* Clone lcdr's utilities repository [here](https://github.com/lcdr/utils)
* Use `pkextractor.pyw` to unpack the client files if they are not already unpacked
**Setup resource directory**
#### Setup resource directory
* In the `build` directory create a `res` directory if it does not already exist.
* Copy over or create symlinks from `macros`, `BrickModels`, `chatplus_en_us.txt`, `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`
**Setup locale**
#### Setup locale
* In the `build` directory create a `locale` directory if it does not already exist
* Copy over or create symlinks from `locale.xml` in your client `locale` directory to the `build/locale` directory
**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`
* 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
@ -199,14 +204,18 @@ certutil -hashfile <file> SHA256
Darkflame Universe utilizes a MySQL/MariaDB database for account and character information.
Initial setup can vary drastically based on which operating system or distribution you are running; there are instructions out there for most setups, follow those and come back here when you have a database up and running.
* Create a database for Darkflame Universe to use
* 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.
**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:
* AuthServer
@ -417,10 +426,11 @@ Here is a summary of the commands available in-game. All commands are prefixed b
</tbody>
</table>
## Credits
# Credits
## Active Contributors
* [EmosewaMC](https://github.com/EmosewaMC)
* [Jettford](https://github.com/Jettford)
* [Aaron K.](https://github.com/aronwk-aaron)
## DLU Team
* [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)
* [Jon002](https://github.com/jaller200)
* [Jonny](https://github.com/cuzitsjonny)
* TheMachine
* Matthew
* [Raine](https://github.com/Rainebannister)
* Bricknave
### Research and tools
* [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
* TheMachine
* Matthew
* Raine
* [Raine](https://github.com/Rainebannister)
* Bricknave
### Special thanks
### Logo
* Cole Peterson (BlasterBuilder)
## Special thanks
* humanoid24
* pwjones1969
* BlasterBuilder for the logo
* [Simon](https://github.com/SimonNitzsche)
* 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
cmake ..
# Run make to build the project. To build utilizing multiple cores, append `-j` and the amount of cores to utilize, for example `make -j8`
make
# To build utilizing multiple cores, append `-j` and the amount of cores to utilize, for example `cmake --build . --config Release -j8'
cmake --build . --config Release

View File

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

View File

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

View File

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

View File

@ -33,9 +33,10 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
"WHEN friend_id = ? THEN player_id "
"END AS requested_player, best_friend FROM friends) AS fr "
"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(2, static_cast<uint32_t>(playerID));
stmt->setUInt(3, static_cast<uint32_t>(playerID));
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:
SendFriendUpdate(fr, player, 1, fd.isBestFriend);
}
else {
} else {
fd.isOnline = false;
fd.zoneID = LWOZONEID();
}
@ -114,6 +114,10 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
inStream.Read(isBestFriendRequest);
auto requestor = playerContainer.GetPlayerData(requestorPlayerID);
if (requestor->playerName == playerName) {
SendFriendResponse(requestor, requestor, AddFriendResponseType::MYTHRAN);
return;
};
std::unique_ptr<PlayerData> requestee(playerContainer.GetPlayerData(playerName));
// Check if player is online first
@ -371,8 +375,7 @@ void ChatPacketHandler::HandleRemoveFriend(Packet* packet) {
SendRemoveFriend(goonB, goonAName, true);
}
void ChatPacketHandler::HandleChatMessage(Packet* packet)
{
void ChatPacketHandler::HandleChatMessage(Packet* packet) {
CINSTREAM;
LWOOBJID playerID = LWOOBJID_EMPTY;
inStream.Read(playerID);
@ -393,7 +396,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet)
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;
@ -401,8 +404,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet)
if (team == nullptr) return;
for (const auto memberId : team->memberIDs)
{
for (const auto memberId : team->memberIDs) {
auto* otherMember = playerContainer.GetPlayerData(memberId);
if (otherMember == nullptr) return;
@ -493,8 +495,7 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
}
}
void ChatPacketHandler::HandleTeamInvite(Packet* packet)
{
void ChatPacketHandler::HandleTeamInvite(Packet* packet) {
CINSTREAM;
LWOOBJID playerID;
inStream.Read(playerID);
@ -503,44 +504,39 @@ void ChatPacketHandler::HandleTeamInvite(Packet* packet)
auto* player = playerContainer.GetPlayerData(playerID);
if (player == nullptr)
{
if (player == nullptr) {
return;
}
auto* team = playerContainer.GetTeam(playerID);
if (team == nullptr)
{
if (team == nullptr) {
team = playerContainer.CreateTeam(playerID);
}
auto* other = playerContainer.GetPlayerData(invitedPlayer);
if (other == nullptr)
{
if (other == nullptr) {
return;
}
if (playerContainer.GetTeam(other->playerID) != nullptr)
{
if (playerContainer.GetTeam(other->playerID) != nullptr) {
return;
}
if (team->memberIDs.size() > 3) {
// 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;
}
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;
LWOOBJID playerID = LWOOBJID_EMPTY;
inStream.Read(playerID);
@ -552,33 +548,29 @@ void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet)
LWOOBJID leaderID = LWOOBJID_EMPTY;
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;
}
auto* team = playerContainer.GetTeam(leaderID);
if (team == nullptr)
{
Game::logger->Log("ChatPacketHandler", "Failed to find team for leader (%llu)\n", leaderID);
if (team == nullptr) {
Game::logger->Log("ChatPacketHandler", "Failed to find team for leader (%llu)", leaderID);
team = playerContainer.GetTeam(playerID);
}
if (team == nullptr)
{
Game::logger->Log("ChatPacketHandler", "Failed to find team for player (%llu)\n", playerID);
if (team == nullptr) {
Game::logger->Log("ChatPacketHandler", "Failed to find team for player (%llu)", playerID);
return;
}
playerContainer.AddMember(team, playerID);
}
void ChatPacketHandler::HandleTeamLeave(Packet* packet)
{
void ChatPacketHandler::HandleTeamLeave(Packet* packet) {
CINSTREAM;
LWOOBJID playerID = LWOOBJID_EMPTY;
inStream.Read(playerID);
@ -588,16 +580,14 @@ void ChatPacketHandler::HandleTeamLeave(Packet* packet)
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);
}
}
void ChatPacketHandler::HandleTeamKick(Packet* packet)
{
void ChatPacketHandler::HandleTeamKick(Packet* packet) {
CINSTREAM;
LWOOBJID playerID = LWOOBJID_EMPTY;
inStream.Read(playerID);
@ -605,35 +595,30 @@ void ChatPacketHandler::HandleTeamKick(Packet* packet)
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);
LWOOBJID kickedId = LWOOBJID_EMPTY;
if (kicked != nullptr)
{
if (kicked != nullptr) {
kickedId = kicked->playerID;
}
else
{
kickedId = playerContainer.GetId(GeneralUtils::ASCIIToUTF16(kickedPlayer));
} else {
kickedId = playerContainer.GetId(GeneralUtils::UTF8ToUTF16(kickedPlayer));
}
if (kickedId == LWOOBJID_EMPTY) return;
auto* team = playerContainer.GetTeam(playerID);
if (team != nullptr)
{
if (team != nullptr) {
if (team->leaderID != playerID || team->leaderID == kickedId) return;
playerContainer.RemoveMember(team, kickedId, false, true, false);
}
}
void ChatPacketHandler::HandleTeamPromote(Packet* packet)
{
void ChatPacketHandler::HandleTeamPromote(Packet* packet) {
CINSTREAM;
LWOOBJID playerID = LWOOBJID_EMPTY;
inStream.Read(playerID);
@ -641,7 +626,7 @@ void ChatPacketHandler::HandleTeamPromote(Packet* packet)
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);
@ -649,16 +634,14 @@ void ChatPacketHandler::HandleTeamPromote(Packet* packet)
auto* team = playerContainer.GetTeam(playerID);
if (team != nullptr)
{
if (team != nullptr) {
if (team->leaderID != playerID) return;
playerContainer.PromoteMember(team, promoted->playerID);
}
}
void ChatPacketHandler::HandleTeamLootOption(Packet* packet)
{
void ChatPacketHandler::HandleTeamLootOption(Packet* packet) {
CINSTREAM;
LWOOBJID playerID = LWOOBJID_EMPTY;
inStream.Read(playerID);
@ -671,8 +654,7 @@ void ChatPacketHandler::HandleTeamLootOption(Packet* packet)
auto* team = playerContainer.GetTeam(playerID);
if (team != nullptr)
{
if (team != nullptr) {
if (team->leaderID != playerID) return;
team->lootFlag = option;
@ -683,8 +665,7 @@ void ChatPacketHandler::HandleTeamLootOption(Packet* packet)
}
}
void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet)
{
void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
CINSTREAM;
LWOOBJID playerID = LWOOBJID_EMPTY;
inStream.Read(playerID);
@ -693,45 +674,37 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet)
auto* team = playerContainer.GetTeam(playerID);
auto* data = playerContainer.GetPlayerData(playerID);
if (team != nullptr && data != nullptr)
{
if (team->local && data->zoneID.GetMapID() != team->zoneId.GetMapID() && data->zoneID.GetCloneID() != team->zoneId.GetCloneID())
{
if (team != nullptr && data != nullptr) {
if (team->local && data->zoneID.GetMapID() != team->zoneId.GetMapID() && data->zoneID.GetCloneID() != team->zoneId.GetCloneID()) {
playerContainer.RemoveMember(team, playerID, false, false, true, true);
return;
}
if (team->memberIDs.size() <= 1 && !team->local)
{
if (team->memberIDs.size() <= 1 && !team->local) {
playerContainer.DisbandTeam(team);
return;
}
if (!team->local)
{
if (!team->local) {
ChatPacketHandler::SendTeamSetLeader(data, team->leaderID);
}
else
{
} else {
ChatPacketHandler::SendTeamSetLeader(data, LWOOBJID_EMPTY);
}
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);
if (memberId == playerID) continue;
const auto memberName = playerContainer.GetName(memberId);
if (otherMember != nullptr)
{
if (otherMember != nullptr) {
ChatPacketHandler::SendTeamSetOffWorldFlag(otherMember, data->playerID, data->zoneID);
}
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;
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID);
@ -757,14 +729,13 @@ void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender)
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;
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID);
//portion that will get routed:
CMSGHEADER
CMSGHEADER;
bitStream.Write(receiver->playerID);
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(ucResponseCode);
bitStream.Write(static_cast<uint32_t>(wsLeaderName.size()));
for (const auto character : wsLeaderName)
{
for (const auto character : wsLeaderName) {
bitStream.Write(character);
}
@ -786,14 +756,13 @@ void ChatPacketHandler::SendTeamInviteConfirm(PlayerData* receiver, bool bLeader
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;
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID);
//portion that will get routed:
CMSGHEADER
CMSGHEADER;
bitStream.Write(receiver->playerID);
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(ucNumOfOtherPlayers);
bitStream.Write(static_cast<uint32_t>(wsLeaderName.size()));
for (const auto character : wsLeaderName)
{
for (const auto character : wsLeaderName) {
bitStream.Write(character);
}
@ -813,14 +781,13 @@ void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderI
SEND_PACKET;
}
void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64PlayerID)
{
void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64PlayerID) {
CBITSTREAM;
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID);
//portion that will get routed:
CMSGHEADER
CMSGHEADER;
bitStream.Write(receiver->playerID);
bitStream.Write(GAME_MSG::GAME_MSG_TEAM_SET_LEADER);
@ -831,14 +798,13 @@ void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64Play
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;
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID);
//portion that will get routed:
CMSGHEADER
CMSGHEADER;
bitStream.Write(receiver->playerID);
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(i64PlayerID);
bitStream.Write(static_cast<uint32_t>(wsPlayerName.size()));
for (const auto character : wsPlayerName)
{
for (const auto character : wsPlayerName) {
bitStream.Write(character);
}
bitStream.Write1();
if (receiver->zoneID.GetCloneID() == zoneID.GetCloneID())
{
if (receiver->zoneID.GetCloneID() == zoneID.GetCloneID()) {
zoneID = LWOZONEID(zoneID.GetMapID(), zoneID.GetInstanceID(), 0);
}
bitStream.Write(zoneID);
@ -863,14 +827,13 @@ void ChatPacketHandler::SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTria
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;
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID);
//portion that will get routed:
CMSGHEADER
CMSGHEADER;
bitStream.Write(receiver->playerID);
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(i64PlayerID);
bitStream.Write(static_cast<uint32_t>(wsPlayerName.size()));
for (const auto character : wsPlayerName)
{
for (const auto character : wsPlayerName) {
bitStream.Write(character);
}
@ -891,21 +853,19 @@ void ChatPacketHandler::SendTeamRemovePlayer(PlayerData* receiver, bool bDisband
SEND_PACKET;
}
void ChatPacketHandler::SendTeamSetOffWorldFlag(PlayerData* receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID)
{
void ChatPacketHandler::SendTeamSetOffWorldFlag(PlayerData* receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID) {
CBITSTREAM;
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID);
//portion that will get routed:
CMSGHEADER
CMSGHEADER;
bitStream.Write(receiver->playerID);
bitStream.Write(GAME_MSG::GAME_MSG_TEAM_SET_OFF_WORLD_FLAG);
bitStream.Write(i64PlayerID);
if (receiver->zoneID.GetCloneID() == zoneID.GetCloneID())
{
if (receiver->zoneID.GetCloneID() == zoneID.GetCloneID()) {
zoneID = LWOZONEID(zoneID.GetMapID(), zoneID.GetInstanceID(), 0);
}
bitStream.Write(zoneID);
@ -943,12 +903,9 @@ void ChatPacketHandler::SendFriendUpdate(PlayerData* friendData, PlayerData* pla
bitStream.Write(playerData->zoneID.GetMapID());
bitStream.Write(playerData->zoneID.GetInstanceID());
if (playerData->zoneID.GetCloneID() == friendData->zoneID.GetCloneID())
{
if (playerData->zoneID.GetCloneID() == friendData->zoneID.GetCloneID()) {
bitStream.Write(0);
}
else
{
} else {
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:
Game::logger = SetupLogger();
if (!Game::logger) return 0;
Game::logger->Log("ChatServer", "Starting Chat server...\n");
Game::logger->Log("ChatServer", "Version: %i.%i\n", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
Game::logger->Log("ChatServer", "Compiled on: %s\n", __TIMESTAMP__);
Game::logger->Log("ChatServer", "Starting Chat server...");
Game::logger->Log("ChatServer", "Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
Game::logger->Log("ChatServer", "Compiled on: %s", __TIMESTAMP__);
//Read our config:
dConfig config("chatconfig.ini");
@ -58,9 +58,8 @@ int main(int argc, char** argv) {
try {
Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password);
}
catch (sql::SQLException& ex) {
Game::logger->Log("ChatServer", "Got an error while connecting to the database: %s\n", ex.what());
} catch (sql::SQLException& ex) {
Game::logger->Log("ChatServer", "Got an error while connecting to the database: %s", ex.what());
Database::Destroy("ChatServer");
delete Game::server;
delete Game::logger;
@ -104,8 +103,7 @@ int main(int argc, char** argv) {
if (framesSinceMasterDisconnect >= 30)
break; //Exit our loop, shut down.
}
else framesSinceMasterDisconnect = 0;
} else framesSinceMasterDisconnect = 0;
//In world we'd update our other systems here.
@ -122,8 +120,7 @@ int main(int argc, char** argv) {
if (framesSinceLastFlush >= 900) {
Game::logger->Flush();
framesSinceLastFlush = 0;
}
else framesSinceLastFlush++;
} else framesSinceLastFlush++;
//Every 10 min we ping our sql server to keep it alive hopefully:
if (framesSinceLastSQLPing >= 40000) {
@ -141,8 +138,7 @@ int main(int argc, char** argv) {
delete stmt;
framesSinceLastSQLPing = 0;
}
else framesSinceLastSQLPing++;
} else framesSinceLastSQLPing++;
//Sleep our thread since auth can afford to.
t += std::chrono::milliseconds(mediumFramerate); //Chat can run at a lower "fps"
@ -172,11 +168,11 @@ dLogger * SetupLogger() {
void HandlePacket(Packet* packet) {
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
Game::logger->Log("ChatServer", "A server has disconnected, erasing their connected players from the list.\n");
Game::logger->Log("ChatServer", "A server has disconnected, erasing their connected players from the list.");
}
if (packet->data[0] == ID_NEW_INCOMING_CONNECTION) {
Game::logger->Log("ChatServer", "A server is connecting, awaiting user list.\n");
Game::logger->Log("ChatServer", "A server is connecting, awaiting user list.");
}
if (packet->data[1] == CHAT_INTERNAL) {
@ -205,7 +201,7 @@ void HandlePacket(Packet* packet) {
}
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;
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;
case MSG_CHAT_TEAM_GET_STATUS:
@ -274,19 +270,19 @@ void HandlePacket(Packet* packet) {
break;
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) {
switch (packet->data[3]) {
case MSG_WORLD_CLIENT_ROUTE_PACKET: {
printf("routing packet from world\n");
Game::logger->Log("ChatServer", "Routing packet from world");
break;
}
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);
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));
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 (?, ?, ?, ?);");
@ -70,12 +70,10 @@ void PlayerContainer::RemovePlayer(Packet* packet) {
auto* team = GetTeam(playerID);
if (team != nullptr)
{
const auto memberName = GeneralUtils::ASCIIToUTF16(std::string(player->playerName.c_str()));
if (team != nullptr) {
const auto memberName = GeneralUtils::UTF8ToUTF16(std::string(player->playerName.c_str()));
for (const auto memberId : team->memberIDs)
{
for (const auto memberId : team->memberIDs) {
auto* otherMember = GetPlayerData(memberId);
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);
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();
}
void PlayerContainer::MuteUpdate(Packet* packet)
{
void PlayerContainer::MuteUpdate(Packet* packet) {
CINSTREAM;
LWOOBJID playerID;
inStream.Read(playerID); //skip header
@ -108,9 +105,8 @@ void PlayerContainer::MuteUpdate(Packet* packet)
auto* player = this->GetPlayerData(playerID);
if (player == nullptr)
{
Game::logger->Log("PlayerContainer", "Failed to find user: %llu\n", playerID);
if (player == nullptr) {
Game::logger->Log("PlayerContainer", "Failed to find user: %llu", playerID);
return;
}
@ -120,8 +116,7 @@ void PlayerContainer::MuteUpdate(Packet* packet)
BroadcastMuteUpdate(playerID, expire);
}
void PlayerContainer::CreateTeamServer(Packet* packet)
{
void PlayerContainer::CreateTeamServer(Packet* packet) {
CINSTREAM;
LWOOBJID playerID;
inStream.Read(playerID); //skip header
@ -133,8 +128,7 @@ void PlayerContainer::CreateTeamServer(Packet* packet)
members.reserve(membersSize);
for (size_t i = 0; i < membersSize; i++)
{
for (size_t i = 0; i < membersSize; i++) {
LWOOBJID member;
inStream.Read(member);
members.push_back(member);
@ -146,16 +140,14 @@ void PlayerContainer::CreateTeamServer(Packet* packet)
auto* team = CreateLocalTeam(members);
if (team != nullptr)
{
if (team != nullptr) {
team->zoneId = zoneId;
}
UpdateTeamsOnWorld(team, false);
}
void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time)
{
void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time) {
CBITSTREAM;
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_MUTE_UPDATE);
@ -165,30 +157,23 @@ void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time)
Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
}
TeamData* PlayerContainer::CreateLocalTeam(std::vector<LWOOBJID> members)
{
if (members.empty())
{
TeamData* PlayerContainer::CreateLocalTeam(std::vector<LWOOBJID> members) {
if (members.empty()) {
return nullptr;
}
TeamData* newTeam = nullptr;
for (const auto member : members)
{
for (const auto member : members) {
auto* team = GetTeam(member);
if (team != nullptr)
{
if (team != nullptr) {
RemoveMember(team, member, false, false, true);
}
if (newTeam == nullptr)
{
if (newTeam == nullptr) {
newTeam = CreateTeam(member, true);
}
else
{
} else {
AddMember(newTeam, member);
}
}
@ -200,8 +185,7 @@ TeamData* PlayerContainer::CreateLocalTeam(std::vector<LWOOBJID> members)
return newTeam;
}
TeamData* PlayerContainer::CreateTeam(LWOOBJID leader, bool local)
{
TeamData* PlayerContainer::CreateTeam(LWOOBJID leader, bool local) {
auto* team = new TeamData();
team->teamID = ++mTeamIDCounter;
@ -215,10 +199,8 @@ TeamData* PlayerContainer::CreateTeam(LWOOBJID leader, bool local)
return team;
}
TeamData* PlayerContainer::GetTeam(LWOOBJID playerID)
{
for (auto* team : mTeams)
{
TeamData* PlayerContainer::GetTeam(LWOOBJID playerID) {
for (auto* team : mTeams) {
if (std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID) == team->memberIDs.end()) continue;
return team;
@ -227,8 +209,7 @@ TeamData* PlayerContainer::GetTeam(LWOOBJID playerID)
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);
if (index != team->memberIDs.end()) return;
@ -240,24 +221,20 @@ void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID)
if (leader == nullptr || member == nullptr) return;
const auto leaderName = GeneralUtils::ASCIIToUTF16(std::string(leader->playerName.c_str()));
const auto memberName = GeneralUtils::ASCIIToUTF16(std::string(member->playerName.c_str()));
const auto leaderName = GeneralUtils::UTF8ToUTF16(leader->playerName);
const auto memberName = GeneralUtils::UTF8ToUTF16(member->playerName);
ChatPacketHandler::SendTeamInviteConfirm(member, false, leader->playerID, leader->zoneID, team->lootFlag, 0, 0, leaderName);
if (!team->local)
{
if (!team->local) {
ChatPacketHandler::SendTeamSetLeader(member, leader->playerID);
}
else
{
} else {
ChatPacketHandler::SendTeamSetLeader(member, LWOOBJID_EMPTY);
}
UpdateTeamsOnWorld(team, false);
for (const auto memberId : team->memberIDs)
{
for (const auto memberId : team->memberIDs) {
auto* otherMember = GetPlayerData(memberId);
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));
if (otherMember != nullptr)
{
if (otherMember != nullptr) {
ChatPacketHandler::SendTeamAddPlayer(otherMember, false, team->local, false, member->playerID, memberName, member->zoneID);
}
}
}
void PlayerContainer::RemoveMember(TeamData* team, LWOOBJID playerID, bool disband, bool kicked, bool leaving, bool silent)
{
void PlayerContainer::RemoveMember(TeamData* team, LWOOBJID playerID, bool disband, bool kicked, bool leaving, bool silent) {
const auto index = std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID);
if (index == team->memberIDs.end()) return;
auto* member = GetPlayerData(playerID);
if (member != nullptr && !silent)
{
if (member != nullptr && !silent) {
ChatPacketHandler::SendTeamSetLeader(member, LWOOBJID_EMPTY);
}
const auto memberName = GetName(playerID);
for (const auto memberId : team->memberIDs)
{
if (silent && memberId == playerID)
{
for (const auto memberId : team->memberIDs) {
if (silent && memberId == playerID) {
continue;
}
@ -306,25 +278,19 @@ void PlayerContainer::RemoveMember(TeamData* team, LWOOBJID playerID, bool disba
UpdateTeamsOnWorld(team, false);
if (team->memberIDs.size() <= 1)
{
if (team->memberIDs.size() <= 1) {
DisbandTeam(team);
}
else
{
if (playerID == team->leaderID)
{
} else {
if (playerID == team->leaderID) {
PromoteMember(team, team->memberIDs[0]);
}
}
}
void PlayerContainer::PromoteMember(TeamData* team, LWOOBJID newLeader)
{
void PlayerContainer::PromoteMember(TeamData* team, LWOOBJID newLeader) {
team->leaderID = newLeader;
for (const auto memberId : team->memberIDs)
{
for (const auto memberId : team->memberIDs) {
auto* otherMember = GetPlayerData(memberId);
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);
if (index == mTeams.end()) return;
for (const auto memberId : team->memberIDs)
{
for (const auto memberId : team->memberIDs) {
auto* otherMember = GetPlayerData(memberId);
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::SendTeamRemovePlayer(otherMember, true, false, false, team->local, team->leaderID, otherMember->playerID, memberName);
@ -358,8 +322,7 @@ void PlayerContainer::DisbandTeam(TeamData* team)
delete team;
}
void PlayerContainer::TeamStatusUpdate(TeamData* team)
{
void PlayerContainer::TeamStatusUpdate(TeamData* team) {
const auto index = std::find(mTeams.begin(), mTeams.end(), team);
if (index == mTeams.end()) return;
@ -368,16 +331,14 @@ void PlayerContainer::TeamStatusUpdate(TeamData* team)
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);
if (otherMember == nullptr) continue;
if (!team->local)
{
if (!team->local) {
ChatPacketHandler::SendTeamStatus(otherMember, team->leaderID, leader->zoneID, team->lootFlag, 0, leaderName);
}
}
@ -385,20 +346,17 @@ void PlayerContainer::TeamStatusUpdate(TeamData* team)
UpdateTeamsOnWorld(team, false);
}
void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam)
{
void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) {
CBITSTREAM;
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_TEAM_UPDATE);
bitStream.Write(team->teamID);
bitStream.Write(deleteTeam);
if (!deleteTeam)
{
if (!deleteTeam) {
bitStream.Write(team->lootFlag);
bitStream.Write(static_cast<char>(team->memberIDs.size()));
for (const auto memberID : team->memberIDs)
{
for (const auto memberID : team->memberIDs) {
bitStream.Write(memberID);
}
}
@ -406,8 +364,7 @@ void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam)
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);
if (pair == mNames.end()) return u"";
@ -415,12 +372,9 @@ std::u16string PlayerContainer::GetName(LWOOBJID playerID)
return pair->second;
}
LWOOBJID PlayerContainer::GetId(const std::u16string& playerName)
{
for (const auto& pair : mNames)
{
if (pair.second == playerName)
{
LWOOBJID PlayerContainer::GetId(const std::u16string& playerName) {
for (const auto& pair : mNames) {
if (pair.second == playerName) {
return pair.first;
}
}
@ -428,7 +382,6 @@ LWOOBJID PlayerContainer::GetId(const std::u16string& playerName)
return LWOOBJID_EMPTY;
}
bool PlayerContainer::GetIsMuted(PlayerData* data)
{
bool PlayerContainer::GetIsMuted(PlayerData* data) {
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();
}
AMFArrayValue::~AMFArrayValue() {
for (auto valueToDelete : GetDenseArray()) {
if (valueToDelete) delete valueToDelete;
}
for (auto valueToDelete : GetAssociativeMap()) {
if (valueToDelete.second) delete valueToDelete.second;
}
}
// AMFObject Constructor
AMFObjectValue::AMFObjectValue(std::vector<std::pair<std::string, AMFValueType>> traits) {
@ -155,3 +163,9 @@ _AMFObjectTraits_::iterator AMFObjectValue::GetTraitsIteratorEnd() {
uint32_t AMFObjectValue::GetTraitArrayCount() {
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
*/
virtual AMFValueType GetValueType() = 0;
virtual ~AMFValue() {};
};
//! A typedef for a pointer to an AMF value
@ -233,6 +234,7 @@ public:
};
//! 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 {
private:
_AMFArrayMap_ associative; //!< The array map (associative part)
@ -245,6 +247,7 @@ private:
AMFValueType GetValueType() { return AMFArray; }
public:
~AMFArrayValue() override;
//! Inserts an item into the array map for a specific key
/*!
\param key The key to set
@ -308,6 +311,18 @@ public:
\return Where the iterator ends
*/
_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
@ -320,6 +335,7 @@ private:
\return The AMF value type
*/
AMFValueType GetValueType() { return AMFObject; }
~AMFObjectValue() override;
public:
//! Constructor

View File

@ -37,6 +37,12 @@ void RakNet::BitStream::Write<AMFValue*>(AMFValue* value) {
break;
}
case AMFDouble: {
AMFDoubleValue* v = (AMFDoubleValue*)value;
this->Write(*v);
break;
}
case AMFString: {
AMFStringValue* v = (AMFStringValue*)value;
this->Write(*v);
@ -56,15 +62,17 @@ void RakNet::BitStream::Write<AMFValue*>(AMFValue* value) {
}
case AMFArray: {
AMFArrayValue* v = (AMFArrayValue*)value;
this->Write(*v);
this->Write((AMFArrayValue*)value);
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) {
unsigned char b4 = (unsigned char)v;
if (v < 0x00200000) {
@ -102,79 +110,50 @@ void WriteUInt29(RakNet::BitStream* bs, uint32_t v) {
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) {
v = (v << 1) | 0x01;
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) {
WriteFlagNumber(bs, (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) {
unsigned char b2;
b2 = (unsigned char)value;
value = value >> 8;
bs->Write((unsigned char)value);
bs->Write(b2);
bs->Write(value);
}
// 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) {
unsigned char b2;
unsigned char b3;
unsigned char b4;
b4 = (unsigned char)value;
value = value >> 8;
b3 = (unsigned char)value;
value = value >> 8;
b2 = (unsigned char)value;
value = value >> 8;
bs->Write((unsigned char)value);
bs->Write(b2);
bs->Write(b3);
bs->Write(b4);
bs->Write(value);
}
// 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) {
unsigned char b2;
unsigned char b3;
unsigned char b4;
unsigned char b5;
unsigned char b6;
unsigned char b7;
unsigned char b8;
b8 = (unsigned char)value;
value = value >> 8;
b7 = (unsigned char)value;
value = value >> 8;
b6 = (unsigned char)value;
value = value >> 8;
b5 = (unsigned char)value;
value = value >> 8;
b4 = (unsigned char)value;
value = value >> 8;
b3 = (unsigned char)value;
value = value >> 8;
b2 = (unsigned char)value;
value = value >> 8;
bs->Write((unsigned char)value);
bs->Write(b2);
bs->Write(b3);
bs->Write(b4);
bs->Write(b5);
bs->Write(b6);
bs->Write(b7);
bs->Write(b8);
bs->Write(value);
}
@ -243,13 +222,13 @@ void RakNet::BitStream::Write<AMFDateValue>(AMFDateValue value) {
// Writes an AMFArrayValue to BitStream
template<>
void RakNet::BitStream::Write<AMFArrayValue>(AMFArrayValue value) {
void RakNet::BitStream::Write<AMFArrayValue*>(AMFArrayValue* value) {
this->Write(AMFArray);
uint32_t denseSize = value.GetDenseValueSize();
uint32_t denseSize = value->GetDenseValueSize();
WriteFlagNumber(this, denseSize);
_AMFArrayMap_::iterator it = value.GetAssociativeIteratorValueBegin();
_AMFArrayMap_::iterator end = value.GetAssociativeIteratorValueEnd();
_AMFArrayMap_::iterator it = value->GetAssociativeIteratorValueBegin();
_AMFArrayMap_::iterator end = value->GetAssociativeIteratorValueEnd();
while (it != end) {
WriteAMFString(this, it->first);
@ -260,8 +239,8 @@ void RakNet::BitStream::Write<AMFArrayValue>(AMFArrayValue value) {
this->Write(AMFNull);
if (denseSize > 0) {
_AMFArrayList_::iterator it2 = value.GetDenseIteratorBegin();
_AMFArrayList_::iterator end2 = value.GetDenseIteratorEnd();
_AMFArrayList_::iterator it2 = value->GetDenseIteratorBegin();
_AMFArrayList_::iterator end2 = value->GetDenseIteratorEnd();
while (it2 != end2) {
this->Write(*it2);

View File

@ -7,7 +7,7 @@
#include <BitStream.h>
/*!
\file AMFBitStream.hpp
\file AMFFormat_BitStream.h
\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
*/
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"
"AMFDeserialize.cpp"
"AMFFormat_BitStream.cpp"
"BinaryIO.cpp"
"dConfig.cpp"
@ -12,15 +13,43 @@ set(DCOMMON_SOURCES "AMFFormat.cpp"
"NiQuaternion.cpp"
"SHA512.cpp"
"Type.cpp"
"ZCompression.cpp")
"ZCompression.cpp"
"BrickByBrickFix.cpp"
)
include_directories(${PROJECT_SOURCE_DIR}/dCommon/)
add_library(dCommon STATIC ${DCOMMON_SOURCES})
target_link_libraries(dCommon libbcrypt)
target_link_libraries(dCommon bcrypt dDatabase tinyxml2)
if (UNIX)
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 ()
target_link_libraries(dCommon ZLIB::ZLIB)

View File

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

View File

@ -6,7 +6,7 @@
#include <algorithm>
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()) {
return string.size();
} else {
@ -24,7 +24,7 @@ inline bool IsTrailSurrogate(char16_t c) {
inline void PushUTF8CodePoint(std::string& ret, char32_t cp) {
if (cp <= 0x007F) {
ret.push_back(cp);
ret.push_back(static_cast<uint8_t>(cp));
} else if (cp <= 0x07FF) {
ret.push_back(0xC0 | (cp >> 6));
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
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);
std::u16string ret;
ret.reserve(newSize);
for (size_t i = 0; i < newSize; i++) {
char c = string[i];
assert(c > 0 && c <= 127);
ret.push_back(static_cast<char16_t>(c));
// Note: both 7-bit ascii characters and REPLACEMENT_CHARACTER fit in one char16_t
ret.push_back((c > 0 && c <= 127) ? static_cast<char16_t>(c) : REPLACEMENT_CHARACTER);
}
return ret;
@ -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
//! 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);
std::string ret;
ret.reserve(newSize);
@ -114,8 +221,7 @@ bool GeneralUtils::ReplaceInString(std::string& str, const std::string& from, co
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::wstring current;
@ -132,8 +238,7 @@ std::vector<std::wstring> GeneralUtils::SplitString(std::wstring& str, wchar_t d
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::u16string current;
@ -150,22 +255,17 @@ std::vector<std::u16string> GeneralUtils::SplitString(std::u16string& str, char1
return vector;
}
std::vector<std::string> GeneralUtils::SplitString(const std::string& str, char delimiter)
{
std::vector<std::string> GeneralUtils::SplitString(const std::string& str, char delimiter) {
std::vector<std::string> vector = std::vector<std::string>();
std::string current = "";
for (size_t i = 0; i < str.length(); i++)
{
for (size_t i = 0; i < str.length(); i++) {
char c = str[i];
if (c == delimiter)
{
if (c == delimiter) {
vector.push_back(current);
current = "";
}
else
{
} else {
current += c;
}
}
@ -193,8 +293,7 @@ std::u16string GeneralUtils::ReadWString(RakNet::BitStream *inStream) {
#define WIN32_LEAN_AND_MEAN
#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::string search_path = folder + "/*.*";
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)
\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
/*!
@ -34,7 +45,7 @@ namespace GeneralUtils {
\param size A size to trim the string to. Default is -1 (No trimming)
\return An UTF-8 representation of the string
*/
std::string UTF16ToWTF8(const std::u16string& string, size_t size = -1);
std::string UTF16ToWTF8(const std::u16string_view& string, size_t size = -1);
/**
* 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
std::uniform_int_distribution<T> distribution(min, max);
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);
return distribution(Game::randomEngine);
}
@ -134,78 +144,64 @@ namespace GeneralUtils {
T Parse(const char* value);
template <>
inline int32_t Parse(const char* value)
{
inline int32_t Parse(const char* value) {
return std::stoi(value);
}
template <>
inline int64_t Parse(const char* value)
{
inline int64_t Parse(const char* value) {
return std::stoll(value);
}
template <>
inline float Parse(const char* value)
{
inline float Parse(const char* value) {
return std::stof(value);
}
template <>
inline double Parse(const char* value)
{
inline double Parse(const char* value) {
return std::stod(value);
}
template <>
inline uint32_t Parse(const char* value)
{
inline uint32_t Parse(const char* value) {
return std::stoul(value);
}
template <>
inline uint64_t Parse(const char* value)
{
inline uint64_t Parse(const char* value) {
return std::stoull(value);
}
template <typename T>
bool TryParse(const char* value, T& dst)
{
try
{
bool TryParse(const char* value, T& dst) {
try {
dst = Parse<T>(value);
return true;
}
catch (...)
{
} catch (...) {
return false;
}
}
template <typename T>
T Parse(const std::string& value)
{
T Parse(const std::string& value) {
return Parse<T>(value.c_str());
}
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);
}
template<typename T>
std::u16string to_u16string(T value)
{
std::u16string to_u16string(T value) {
return GeneralUtils::ASCIIToUTF16(std::to_string(value));
}
// From boost::hash_combine
template <class T>
void hash_combine(std::size_t& s, const T& v)
{
void hash_combine(std::size_t& s, const T& v) {
std::hash<T> h;
s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2);
}

View File

@ -49,7 +49,7 @@ LDFBaseData * LDFBaseData::DataFromString(const std::string& format) {
switch (type) {
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);
}
@ -72,16 +72,11 @@ LDFBaseData * LDFBaseData::DataFromString(const std::string& format) {
{
uint32_t data;
if (dataArray[1] == "true")
{
if (dataArray[1] == "true") {
data = 1;
}
else if (dataArray[1] == "false")
{
} else if (dataArray[1] == "false") {
data = 0;
}
else
{
} else {
data = static_cast<uint32_t>(stoul(dataArray[1]));
}
@ -91,16 +86,11 @@ LDFBaseData * LDFBaseData::DataFromString(const std::string& format) {
case LDF_TYPE_BOOLEAN: {
bool data;
if (dataArray[1] == "true")
{
if (dataArray[1] == "true") {
data = true;
}
else if (dataArray[1] == "false")
{
} else if (dataArray[1] == "false") {
data = false;
}
else
{
} else {
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
MD5::MD5()
{
MD5::MD5() {
init();
}
//////////////////////////////////////////////
// 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();
update(text.c_str(), text.length());
finalize();
@ -117,8 +115,7 @@ MD5::MD5(const std::string &text)
//////////////////////////////
void MD5::init()
{
void MD5::init() {
finalized = false;
count[0] = 0;
@ -134,8 +131,7 @@ void MD5::init()
//////////////////////////////
// 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)
output[i] = ((uint4)input[j]) | (((uint4)input[j + 1]) << 8) |
(((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
// 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) {
output[j] = input[i] & 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
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];
decode(x, block, blocksize);
@ -248,8 +242,7 @@ void MD5::transform(const uint1 block[blocksize])
// MD5 block update operation. Continues an MD5 message-digest
// 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
size_type index = count[0] / 8 % blocksize;
@ -264,8 +257,7 @@ void MD5::update(const unsigned char input[], size_type length)
size_type i;
// transform as many times as possible.
if (length >= firstpart)
{
if (length >= firstpart) {
// fill buffer first, transform
memcpy(&buffer[index], input, firstpart);
transform(buffer);
@ -275,8 +267,7 @@ void MD5::update(const unsigned char input[], size_type length)
transform(&input[i]);
index = 0;
}
else
} else
i = 0;
// 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
void MD5::update(const char input[], size_type length)
{
void MD5::update(const char input[], size_type 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
// the message digest and zeroizing the context.
MD5& MD5::finalize()
{
MD5& MD5::finalize() {
static unsigned char padding[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -332,8 +321,7 @@ MD5& MD5::finalize()
//////////////////////////////
// return hex representation of digest as string
std::string MD5::hexdigest() const
{
std::string MD5::hexdigest() const {
if (!finalized)
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();
}
//////////////////////////////
std::string md5(const std::string str)
{
std::string md5(const std::string str) {
MD5 md5 = MD5(str);
return md5.hexdigest();

View File

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

View File

@ -175,8 +175,7 @@ bool NiPoint3::IsWithinSpehere(const NiPoint3& sphereCenter, float 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;
const auto pa = p - a;
@ -191,16 +190,14 @@ NiPoint3 NiPoint3::ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, cons
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 lenA = a.SquaredLength();
const auto lenB = a.SquaredLength();
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 dy = a.y - b.y;
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);
}
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 dy = a.y - b.y;
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;
}
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 dy = target.y - current.y;
float dz = target.z - current.z;

View File

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

View File

@ -45,8 +45,7 @@ const unsigned long long SHA512::sha512_k[80] = //ULL = uint64
0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
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 wv[8];
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[1] = 0xbb67ae8584caa73bULL;
m_h[2] = 0x3c6ef372fe94f82bULL;
@ -97,8 +95,7 @@ void SHA512::init()
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 new_len, rem_len, tmp_len;
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;
}
void SHA512::final(unsigned char *digest)
{
void SHA512::final(unsigned char* digest) {
unsigned int block_nb;
unsigned int pm_len;
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];
memset(digest, 0, SHA512::DIGEST_SIZE);
class SHA512 ctx;

View File

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

View File

@ -1,13 +1,8 @@
#pragma once
#pragma once
#include <cstdint>
#include "dPlatforms.h"
#ifndef DARKFLAME_PLATFORM_WIN32
namespace ZCompression
{
namespace ZCompression {
int32_t GetMaxCompressedLength(int32_t nLenSrc);
int32_t Compress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst);
@ -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);
}
#endif

View File

@ -387,6 +387,7 @@ enum eReplicaComponentType : int32_t {
COMPONENT_TYPE_PROPERTY = 36, //!< The Property Component
COMPONENT_TYPE_SCRIPTED_ACTIVITY = 39, //!< The ScriptedActivity Component
COMPONENT_TYPE_PHANTOM_PHYSICS = 40, //!< The PhantomPhysics Component
COMPONENT_TYPE_MODEL = 42, //!< The Model Component
COMPONENT_TYPE_PROPERTY_ENTRANCE = 43, //!< The PhantomPhysics Component
COMPONENT_TYPE_PROPERTY_MANAGEMENT = 45, //!< The PropertyManagement 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_MISSION_OFFER = 73, //!< The MissionOffer 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_PROXIMITY_MONITOR = 78, //!< The Proximity Monitor Component
COMPONENT_TYPE_MISSION = 84, //!< The Mission Component
COMPONENT_TYPE_ROCKET_LAUNCH_LUP = 97, //!< The LUP Launchpad Componen
COMPONENT_TYPE_RAIL_ACTIVATOR = 104,
COMPONENT_TYPE_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_LEVEL_PROGRESSION = 109, //!< The Level Progression Component
COMPONENT_TYPE_POSSESSOR = 110, //!< The Possessor Component
COMPONENT_TYPE_BUILD_BORDER = 114, //!< The Build Border Component
COMPONENT_TYPE_DESTROYABLE = 1000, //!< The Destroyable Component
COMPONENT_TYPE_MODEL = 5398484 //look man idk
};
enum class UseItemResponse : uint32_t {
@ -541,7 +542,7 @@ enum ePlayerFlags {
TOOLTIP_TALK_TO_SKYLAND_TO_GET_HAT = 52,
MODULAR_BUILD_PLAYER_PLACES_FIRST_MODEL_IN_SCRATCH = 53,
MODULAR_BUILD_FIRST_ARROW_DISPLAY_FOR_MODULE = 54,
AG_BEACON_QB,_SO_THE_PLAYER_CAN_ALWAYS_BUILD_THEM = 55,
AG_BEACON_QB_SO_THE_PLAYER_CAN_ALWAYS_BUILD_THEM = 55,
GF_PET_DIG_FLAG_1 = 56,
GF_PET_DIG_FLAG_2 = 57,
GF_PET_DIG_FLAG_3 = 58,
@ -627,6 +628,7 @@ enum ePlayerFlags {
GF_BINOC_IN_CROC_AREA = 1308,
GF_BINOC_IN_JAIL_AREA = 1309,
GF_BINOC_TELESCOPE_NEXT_TO_CAPTAIN_JACK = 1310,
NT_PLINTH_REBUILD = 1919,
NT_FACTION_SPY_DUKE = 1974,
NT_FACTION_SPY_OVERBUILD = 1976,
NT_FACTION_SPY_HAEL = 1977,

View File

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

View File

@ -43,8 +43,8 @@ void Database::Destroy(std::string source, bool log) {
if (!con) return;
if (log) {
if (source != "") Game::logger->Log("Database", "Destroying MySQL connection from %s!\n", source.c_str());
else Game::logger->Log("Database", "Destroying MySQL connection!\n");
if (source != "") Game::logger->Log("Database", "Destroying MySQL connection from %s!", source.c_str());
else Game::logger->Log("Database", "Destroying MySQL connection!");
}
con->close();
@ -63,17 +63,16 @@ sql::PreparedStatement* Database::CreatePreppedStmt(const std::string& query) {
if (!con) {
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;
con = nullptr;
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);
@ -84,3 +83,15 @@ sql::PreparedStatement* Database::CreatePreppedStmt(const std::string& query) {
void Database::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::PreparedStatement* CreatePreppedStmt(const std::string& query);
static void Commit();
static bool GetAutoCommit();
static void SetAutoCommit(bool value);
static std::string GetDatabase() { return database; }
static sql::Properties GetProperties() { return props; }

View File

@ -1,5 +1,6 @@
#include "MigrationRunner.h"
#include "BrickByBrickFix.h"
#include "GeneralUtils.h"
#include <fstream>
@ -7,13 +8,13 @@
#include <thread>
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());");
stmt->executeQuery();
auto* stmt = Database::CreatePreppedStmt("CREATE TABLE IF NOT EXISTS migration_history (name TEXT NOT NULL, date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP());");
stmt->execute();
delete stmt;
sql::SQLString finalSQL = "";
Migration checkMigration{};
bool runSd0Migrations = false;
for (const auto& entry : GeneralUtils::GetFileNamesFromFolder("./migrations/")) {
auto migration = LoadMigration(entry);
@ -25,16 +26,18 @@ void MigrationRunner::RunMigrations() {
stmt = Database::CreatePreppedStmt("SELECT name FROM migration_history WHERE name = ?;");
stmt->setString(1, migration.name);
auto res = stmt->executeQuery();
auto* res = stmt->executeQuery();
bool doExit = res->next();
delete res;
delete stmt;
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('\n');
}
stmt = Database::CreatePreppedStmt("INSERT INTO migration_history (name) VALUES (?);");
stmt->setString(1, entry);
@ -42,16 +45,31 @@ void MigrationRunner::RunMigrations() {
delete stmt;
}
if (finalSQL.empty() && !runSd0Migrations) {
Game::logger->Log("MigrationRunner", "Server database is up to date.");
return;
}
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 {
auto simpleStatement = Database::CreateStmt();
simpleStatement->execute(finalSQL);
delete simpleStatement;
if (query.empty()) continue;
simpleStatement->execute(query);
} 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) {
@ -59,8 +77,6 @@ Migration MigrationRunner::LoadMigration(std::string path) {
std::ifstream file("./migrations/" + path);
if (file.is_open()) {
std::hash<std::string> hash;
std::string line;
std::string total = "";

View File

@ -31,6 +31,18 @@ public:
//! Destructor
~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
/*!
\return The table name

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -68,7 +68,7 @@ std::vector<CDSkillBehavior> CDSkillBehaviorTable::Query(std::function<bool(CDSk
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
return data;
}

View File

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

View File

@ -56,4 +56,4 @@ endforeach()
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;
}
void Character::UpdateFromDatabase()
{
void Character::UpdateFromDatabase() {
sql::PreparedStatement* stmt = Database::CreatePreppedStmt(
"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->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 {
Game::logger->Log("Character", "Failed to load xmlData!\n");
Game::logger->Log("Character", "Failed to load xmlData!");
//Server::rakServer->CloseConnection(m_ParentUser->GetSystemAddress(), true);
return;
}
tinyxml2::XMLElement* mf = m_Doc->FirstChildElement("obj")->FirstChildElement("mf");
if (!mf) {
Game::logger->Log("Character", "Failed to find mf tag!\n");
Game::logger->Log("Character", "Failed to find mf tag!");
return;
}
@ -168,19 +167,18 @@ void Character::DoQuickXMLDataParse() {
tinyxml2::XMLElement* inv = m_Doc->FirstChildElement("obj")->FirstChildElement("inv");
if (!inv) {
Game::logger->Log("Character", "Char has no inv!\n");
Game::logger->Log("Character", "Char has no inv!");
return;
}
tinyxml2::XMLElement* bag = inv->FirstChildElement("items")->FirstChildElement("in");
if (!bag) {
Game::logger->Log("Character", "Couldn't find bag0!\n");
Game::logger->Log("Character", "Couldn't find bag0!");
return;
}
while (bag != nullptr)
{
while (bag != nullptr) {
auto* sib = bag->FirstChildElement();
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);
GameMessages::SendSetEmoteLockState(EntityManager::Instance()->GetEntity(m_ObjectID), false, emoteID);
}
void Character::SetBuildMode(bool buildMode)
{
void Character::SetBuildMode(bool buildMode) {
m_BuildMode = buildMode;
auto* controller = dZoneManager::Instance()->GetZoneControlObject();
@ -305,9 +301,9 @@ void Character::SaveXMLToDatabase() {
character->SetAttribute("gm", m_GMLevel);
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();
// lzid garbage, binary concat of zoneID, zoneInstance and zoneClone
if (zoneInfo.GetMapID() != 0 && zoneInfo.GetCloneID() == 0) {
uint64_t lzidConcat = zoneInfo.GetCloneID();
lzidConcat = (lzidConcat << 16) | uint16_t(zoneInfo.GetInstanceID());
lzidConcat = (lzidConcat << 16) | uint16_t(zoneInfo.GetMapID());
@ -359,7 +355,7 @@ void Character::SaveXMLToDatabase() {
//Call upon the entity to update our xmlDoc:
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;
}
@ -380,7 +376,7 @@ void Character::SaveXMLToDatabase() {
//For metrics, log the time it took to save:
auto end = std::chrono::system_clock::now();
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;
}
@ -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 (GetPlayerFlag(flagId) == value) return;
if (value)
{
if (value) {
// Update the mission component:
auto* player = EntityManager::Instance()->GetEntity(m_ObjectID);
if (player != nullptr)
{
if (player != nullptr) {
auto* missionComponent = player->GetComponent<MissionComponent>();
if (missionComponent != nullptr)
{
if (missionComponent != nullptr) {
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);
// Check if flag index exists
if (it != m_PlayerFlags.end())
{
if (it != m_PlayerFlags.end()) {
// Update the value
if (value) {
it->second |= shiftedValue;
@ -458,8 +450,7 @@ void Character::SetRetroactiveFlags() {
}
}
void Character::SaveXmlRespawnCheckpoints()
{
void Character::SaveXmlRespawnCheckpoints() {
//Export our respawn points:
auto* points = m_Doc->FirstChildElement("obj")->FirstChildElement("res");
if (!points) {
@ -480,8 +471,7 @@ void Character::SaveXmlRespawnCheckpoints()
}
}
void Character::LoadXmlRespawnCheckpoints()
{
void Character::LoadXmlRespawnCheckpoints() {
m_WorldRespawnCheckpoints.clear();
auto* points = m_Doc->FirstChildElement("obj")->FirstChildElement("res");
@ -490,8 +480,7 @@ void Character::LoadXmlRespawnCheckpoints()
}
auto* r = points->FirstChildElement("r");
while (r != nullptr)
{
while (r != nullptr) {
int32_t map = 0;
NiPoint3 point = NiPoint3::ZERO;
@ -507,8 +496,7 @@ void Character::LoadXmlRespawnCheckpoints()
}
void Character::OnZoneLoad()
{
void Character::OnZoneLoad() {
if (m_OurEntity == nullptr) {
return;
}
@ -550,23 +538,19 @@ void Character::OnZoneLoad()
}
}
PermissionMap Character::GetPermissionMap() const
{
PermissionMap Character::GetPermissionMap() const {
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;
}
void Character::SetRespawnPoint(LWOMAPID map, const NiPoint3& point)
{
void Character::SetRespawnPoint(LWOMAPID map, const NiPoint3& 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);
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) {
if (newCoins < 0)
{
if (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);
}
bool Character::HasBeenToWorld(LWOMAPID mapID) const
{
bool Character::HasBeenToWorld(LWOMAPID mapID) const {
return m_WorldRespawnCheckpoints.find(mapID) != m_WorldRespawnCheckpoints.end();
}
void Character::SendMuteNotice() const
{
void Character::SendMuteNotice() const {
if (!m_ParentUser->GetIsMuted()) return;
time_t expire = m_ParentUser->GetMuteExpire();
char buffer[32] = "brought up for review.\0";
if (expire != 1)
{
if (expire != 1) {
std::tm* ptm = std::localtime(&expire);
// Format: Mo, 15.06.2009 20:20:00
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; }
/**
* @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:
/**
* The ID of this character. First 32 bits of the ObjectID.
@ -621,6 +633,11 @@ private:
*/
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
* 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>
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);
if (index == m_Components.end())
{
if (index == m_Components.end()) {
component = nullptr;
return false;
@ -355,26 +353,22 @@ bool Entity::TryGetComponent(const int32_t componentId, T*& component) const
}
template <typename T>
T* Entity::GetComponent() const
{
T* Entity::GetComponent() const {
return dynamic_cast<T*>(GetComponent(T::ComponentType));
}
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);
if (data == nullptr)
{
if (data == nullptr) {
return LDFData<T>::Default;
}
auto* typed = dynamic_cast<LDFData<T>*>(data);
if (typed == nullptr)
{
if (typed == nullptr) {
return LDFData<T>::Default;
}
@ -382,14 +376,12 @@ const T& Entity::GetVar(const std::u16string& name) const
}
template<typename T>
T Entity::GetVarAs(const std::u16string& name) const
{
T Entity::GetVarAs(const std::u16string& name) const {
const auto data = GetVarAsString(name);
T value;
if (!GeneralUtils::TryParse(data, value))
{
if (!GeneralUtils::TryParse(data, value)) {
return LDFData<T>::Default;
}
@ -397,12 +389,10 @@ T Entity::GetVarAs(const std::u16string& name) const
}
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);
if (data == nullptr)
{
if (data == nullptr) {
auto* data = new LDFData<T>(name, value);
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);
if (typed == nullptr)
{
if (typed == nullptr) {
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
if (user != nullptr) {
entity = new Player(id, info, user, parentEntity);
}
else {
} else {
entity = new Entity(id, info, parentEntity);
}
@ -165,104 +164,74 @@ void EntityManager::UpdateEntities(const float deltaTime) {
e.second->Update(deltaTime);
}
for (const auto entityId : m_EntitiesToSerialize)
{
auto* entity = GetEntity(entityId);
for (auto entry = m_EntitiesToSerialize.begin(); entry != m_EntitiesToSerialize.end(); entry++) {
auto* entity = GetEntity(*entry);
if (entity == nullptr) continue;
m_SerializationCounter++;
RakNet::BitStream stream;
stream.Write(static_cast<char>(ID_REPLICA_MANAGER_SERIALIZE));
stream.Write(static_cast<unsigned short>(entity->GetNetworkId()));
entity->WriteBaseReplicaData(&stream, PACKET_TYPE_SERIALIZATION);
entity->WriteComponents(&stream, PACKET_TYPE_SERIALIZATION);
if (entity->GetIsGhostingCandidate())
{
for (auto* player : Player::GetAllPlayers())
{
if (player->IsObserved(entityId))
{
if (entity->GetIsGhostingCandidate()) {
for (auto* player : Player::GetAllPlayers()) {
if (player->IsObserved(*entry)) {
Game::server->Send(&stream, player->GetSystemAddress(), false);
}
}
}
else
{
} else {
Game::server->Send(&stream, UNASSIGNED_SYSTEM_ADDRESS, true);
}
}
m_EntitiesToSerialize.clear();
for (const auto& entry : m_EntitiesToKill)
{
auto* entity = GetEntity(entry);
for (auto entry = m_EntitiesToKill.begin(); entry != m_EntitiesToKill.end(); entry++) {
auto* entity = GetEntity(*entry);
if (!entity) continue;
if (entity->GetScheduledKiller())
{
if (entity->GetScheduledKiller()) {
entity->Smash(entity->GetScheduledKiller()->GetObjectID(), SILENT);
}
else
{
} else {
entity->Smash(LWOOBJID_EMPTY, SILENT);
}
}
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.
auto entityToDelete = GetEntity(entry);
auto entityToDelete = GetEntity(*entry);
auto networkIdToErase = entityToDelete->GetNetworkId();
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 (entityToDelete->IsPlayer())
{
if (entityToDelete->IsPlayer()) {
delete dynamic_cast<Player*>(entityToDelete);
}
else
{
} else {
delete entityToDelete;
}
entityToDelete = nullptr;
if (networkIdToErase != 0)
{
m_LostNetworkIds.push(networkIdToErase);
}
if (networkIdToErase != 0) m_LostNetworkIds.push(networkIdToErase);
}
if (ghostingToDelete != m_EntitiesToGhost.end())
{
m_EntitiesToGhost.erase(ghostingToDelete);
if (ghostingToDelete != m_EntitiesToGhost.end()) m_EntitiesToGhost.erase(ghostingToDelete);
m_Entities.erase(*entry);
}
m_Entities.erase(entry);
}
m_EntitiesToDelete.clear();
}
Entity* EntityManager::GetEntity(const LWOOBJID& objectId) const {
const auto& index = m_Entities.find(objectId);
if (index == m_Entities.end())
{
if (index == m_Entities.end()) {
return nullptr;
}
@ -303,18 +272,15 @@ std::vector<Entity *> EntityManager::GetEntitiesByLOT(const LOT &lot) const {
return entities;
}
Entity* EntityManager::GetZoneControlEntity() const
{
Entity* EntityManager::GetZoneControlEntity() const {
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
const auto& spawnPoint = m_SpawnPoints.find(spawnName);
if (spawnPoint == m_SpawnPoints.end())
{
if (spawnPoint == m_SpawnPoints.end()) {
return nullptr;
}
@ -322,23 +288,18 @@ Entity* EntityManager::GetSpawnPointEntity(const std::string& spawnName) const
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;
}
void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr, const bool skipChecks) {
if (entity->GetNetworkId() == 0)
{
if (entity->GetNetworkId() == 0) {
uint16_t networkId;
if (!m_LostNetworkIds.empty())
{
if (!m_LostNetworkIds.empty()) {
networkId = m_LostNetworkIds.top();
m_LostNetworkIds.pop();
}
else
{
} else {
networkId = ++m_NetworkIdCounter;
}
@ -347,18 +308,15 @@ void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr
const auto checkGhosting = entity->GetIsGhostingCandidate();
if (checkGhosting)
{
if (checkGhosting) {
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);
}
}
if (checkGhosting && sysAddr == UNASSIGNED_SYSTEM_ADDRESS)
{
if (checkGhosting && sysAddr == UNASSIGNED_SYSTEM_ADDRESS) {
CheckGhosting(entity);
return;
@ -375,38 +333,26 @@ void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr
entity->WriteBaseReplicaData(&stream, PACKET_TYPE_CONSTRUCTION);
entity->WriteComponents(&stream, PACKET_TYPE_CONSTRUCTION);
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS)
{
if (skipChecks)
{
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) {
if (skipChecks) {
Game::server->Send(&stream, UNASSIGNED_SYSTEM_ADDRESS, true);
}
else
{
for (auto* player : Player::GetAllPlayers())
{
if (player->GetPlayerReadyForUpdates())
{
} else {
for (auto* player : Player::GetAllPlayers()) {
if (player->GetPlayerReadyForUpdates()) {
Game::server->Send(&stream, player->GetSystemAddress(), false);
}
else
{
} else {
player->AddLimboConstruction(entity->GetObjectID());
}
}
}
}
else
{
} else {
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());
if (entity->IsPlayer())
{
if (entity->GetGMLevel() > GAME_MASTER_LEVEL_CIVILIAN)
{
if (entity->IsPlayer()) {
if (entity->GetGMLevel() > GAME_MASTER_LEVEL_CIVILIAN) {
GameMessages::SendToggleGMInvis(entity->GetObjectID(), true, sysAddr);
}
}
@ -426,8 +372,7 @@ void EntityManager::ConstructAllEntities(const SystemAddress& sysAddr) {
}
void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr) {
if (entity->GetNetworkId() == 0)
{
if (entity->GetNetworkId() == 0) {
return;
}
@ -438,23 +383,19 @@ void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr)
Game::server->Send(&stream, sysAddr, sysAddr == UNASSIGNED_SYSTEM_ADDRESS);
for (auto* player : Player::GetAllPlayers())
{
if (!player->GetPlayerReadyForUpdates())
{
for (auto* player : Player::GetAllPlayers()) {
if (!player->GetPlayerReadyForUpdates()) {
player->RemoveLimboConstruction(entity->GetObjectID());
}
}
}
void EntityManager::SerializeEntity(Entity* entity) {
if (entity->GetNetworkId() == 0)
{
if (entity->GetNetworkId() == 0) {
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());
}
@ -467,44 +408,35 @@ void EntityManager::DestructAllEntities(const SystemAddress& sysAddr) {
}
}
void EntityManager::SetGhostDistanceMax(float value)
{
void EntityManager::SetGhostDistanceMax(float value) {
m_GhostDistanceMaxSquared = value * value;
}
float EntityManager::GetGhostDistanceMax() const
{
float EntityManager::GetGhostDistanceMax() const {
return std::sqrt(m_GhostDistanceMaxSquared);
}
void EntityManager::SetGhostDistanceMin(float value)
{
void EntityManager::SetGhostDistanceMin(float value) {
m_GhostDistanceMinSqaured = value * value;
}
float EntityManager::GetGhostDistanceMin() const
{
float EntityManager::GetGhostDistanceMin() const {
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);
if (iter == m_PlayersToUpdateGhosting.end())
{
if (iter == m_PlayersToUpdateGhosting.end()) {
m_PlayersToUpdateGhosting.push_back(playerID);
}
}
void EntityManager::UpdateGhosting()
{
for (const auto playerID : m_PlayersToUpdateGhosting)
{
void EntityManager::UpdateGhosting() {
for (const auto playerID : m_PlayersToUpdateGhosting) {
auto* player = Player::GetPlayer(playerID);
if (player == nullptr)
{
if (player == nullptr) {
continue;
}
@ -514,25 +446,21 @@ void EntityManager::UpdateGhosting()
m_PlayersToUpdateGhosting.clear();
}
void EntityManager::UpdateGhosting(Player* player)
{
if (player == nullptr)
{
void EntityManager::UpdateGhosting(Player* player) {
if (player == nullptr) {
return;
}
auto* missionComponent = player->GetComponent<MissionComponent>();
if (missionComponent == nullptr)
{
if (missionComponent == nullptr) {
return;
}
const auto& referencePoint = player->GetGhostReferencePoint();
const auto isOverride = player->GetGhostOverride();
for (auto* entity : m_EntitiesToGhost)
{
for (auto* entity : m_EntitiesToGhost) {
const auto isAudioEmitter = entity->GetLOT() == 6368;
const auto& entityPoint = entity->GetPosition();
@ -546,30 +474,24 @@ void EntityManager::UpdateGhosting(Player* player)
auto ghostingDistanceMax = m_GhostDistanceMaxSquared;
auto ghostingDistanceMin = m_GhostDistanceMinSqaured;
if (isAudioEmitter)
{
if (isAudioEmitter) {
ghostingDistanceMax = ghostingDistanceMin;
}
if (observed && distance > ghostingDistanceMax && !isOverride)
{
if (observed && distance > ghostingDistanceMax && !isOverride) {
player->GhostEntity(id);
DestructEntity(entity, player->GetSystemAddress());
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
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);
if (missionComponent->HasCollectible(collectionId))
{
if (missionComponent->HasCollectible(collectionId)) {
continue;
}
}
@ -583,10 +505,8 @@ void EntityManager::UpdateGhosting(Player* player)
}
}
void EntityManager::CheckGhosting(Entity* entity)
{
if (entity == nullptr)
{
void EntityManager::CheckGhosting(Entity* entity) {
if (entity == nullptr) {
return;
}
@ -597,8 +517,7 @@ void EntityManager::CheckGhosting(Entity* entity)
const auto isAudioEmitter = entity->GetLOT() == 6368;
for (auto* player : Player::GetAllPlayers())
{
for (auto* player : Player::GetAllPlayers()) {
const auto& entityPoint = player->GetGhostReferencePoint();
const int32_t id = entity->GetObjectID();
@ -607,16 +526,13 @@ void EntityManager::CheckGhosting(Entity* entity)
const auto distance = NiPoint3::DistanceSquared(referencePoint, entityPoint);
if (observed && distance > ghostingDistanceMax)
{
if (observed && distance > ghostingDistanceMax) {
player->GhostEntity(id);
DestructEntity(entity, player->GetSystemAddress());
entity->SetObservers(entity->GetObservers() - 1);
}
else if (!observed && ghostingDistanceMin > distance)
{
} else if (!observed && ghostingDistanceMin > distance) {
player->ObserveEntity(id);
ConstructEntity(entity, player->GetSystemAddress());
@ -626,12 +542,9 @@ void EntityManager::CheckGhosting(Entity* entity)
}
}
Entity* EntityManager::GetGhostCandidate(int32_t id)
{
for (auto* entity : m_EntitiesToGhost)
{
if (entity->GetObjectID() == id)
{
Entity* EntityManager::GetGhostCandidate(int32_t id) {
for (auto* entity : m_EntitiesToGhost) {
if (entity->GetObjectID() == id) {
return entity;
}
}
@ -639,8 +552,7 @@ Entity* EntityManager::GetGhostCandidate(int32_t id)
return nullptr;
}
bool EntityManager::GetGhostingEnabled() const
{
bool EntityManager::GetGhostingEnabled() const {
return m_GhostingEnabled;
}
@ -662,18 +574,15 @@ void EntityManager::ScheduleForKill(Entity* entity) {
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;
}
m_EntitiesToKill.push_back(objectId);
}
void EntityManager::ScheduleForDeletion(LWOOBJID entity)
{
if (std::count(m_EntitiesToDelete.begin(), m_EntitiesToDelete.end(), entity))
{
void EntityManager::ScheduleForDeletion(LWOOBJID entity) {
if (std::count(m_EntitiesToDelete.begin(), m_EntitiesToDelete.end(), entity)) {
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();
}

View File

@ -45,7 +45,7 @@ std::u16string Leaderboard::ToString() const {
index++;
}
return GeneralUtils::ASCIIToUTF16(leaderboard);
return GeneralUtils::UTF8ToUTF16(leaderboard);
}
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)
highscore = false;
}
}
else {
} else {
if (score <= storedScore) // Based on score (DLU)
highscore = false;
}

View File

@ -1,4 +1,4 @@
#include "Player.h"
#include "Player.h"
#include <ctime>
@ -17,8 +17,7 @@
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_Character = m_ParentUser->GetLastUsedChar();
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);
if (iter != m_Players.end())
{
if (iter != m_Players.end()) {
return;
}
m_Players.push_back(this);
}
User* Player::GetParentUser() const
{
User* Player::GetParentUser() const {
return m_ParentUser;
}
SystemAddress Player::GetSystemAddress() const
{
SystemAddress Player::GetSystemAddress() const {
return m_SystemAddress;
}
void Player::SetSystemAddress(const SystemAddress& value)
{
void Player::SetSystemAddress(const SystemAddress& value) {
m_SystemAddress = value;
}
void Player::SetRespawnPos(const NiPoint3 position)
{
void Player::SetRespawnPos(const NiPoint3 position) {
m_respawnPos = position;
m_Character->SetRespawnPoint(dZoneManager::Instance()->GetZone()->GetWorldID(), position);
}
void Player::SetRespawnRot(const NiQuaternion rotation)
{
void Player::SetRespawnRot(const NiQuaternion rotation) {
m_respawnRot = rotation;
}
NiPoint3 Player::GetRespawnPosition() const
{
NiPoint3 Player::GetRespawnPosition() const {
return m_respawnPos;
}
NiQuaternion Player::GetRespawnRotation() const
{
NiQuaternion Player::GetRespawnRotation() const {
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);
}
void Player::SendToZone(LWOMAPID zoneId, LWOCLONEID cloneId)
{
void Player::SendToZone(LWOMAPID zoneId, LWOCLONEID cloneId) {
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) {
@ -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);
if (iter != m_LimboConstructions.end())
{
if (iter != m_LimboConstructions.end()) {
return;
}
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);
if (iter == m_LimboConstructions.end())
{
if (iter == m_LimboConstructions.end()) {
return;
}
m_LimboConstructions.erase(iter);
}
void Player::ConstructLimboEntities()
{
for (const auto objectId : m_LimboConstructions)
{
void Player::ConstructLimboEntities() {
for (const auto objectId : m_LimboConstructions) {
auto* entity = EntityManager::Instance()->GetEntity(objectId);
if (entity == nullptr)
{
if (entity == nullptr) {
continue;
}
@ -162,52 +144,41 @@ void Player::ConstructLimboEntities()
m_LimboConstructions.clear();
}
std::map<LWOOBJID, Loot::Info>& Player::GetDroppedLoot()
{
std::map<LWOOBJID, Loot::Info>& Player::GetDroppedLoot() {
return m_DroppedLoot;
}
const NiPoint3& Player::GetGhostReferencePoint() const
{
const NiPoint3& Player::GetGhostReferencePoint() const {
return m_GhostOverride ? m_GhostOverridePoint : m_GhostReferencePoint;
}
const NiPoint3& Player::GetOriginGhostReferencePoint() const
{
const NiPoint3& Player::GetOriginGhostReferencePoint() const {
return m_GhostReferencePoint;
}
void Player::SetGhostReferencePoint(const NiPoint3& value)
{
void Player::SetGhostReferencePoint(const NiPoint3& value) {
m_GhostReferencePoint = value;
}
void Player::SetGhostOverridePoint(const NiPoint3& value)
{
void Player::SetGhostOverridePoint(const NiPoint3& value) {
m_GhostOverridePoint = value;
}
const NiPoint3& Player::GetGhostOverridePoint() const
{
const NiPoint3& Player::GetGhostOverridePoint() const {
return m_GhostOverridePoint;
}
void Player::SetGhostOverride(bool value)
{
void Player::SetGhostOverride(bool value) {
m_GhostOverride = value;
}
bool Player::GetGhostOverride() const
{
bool Player::GetGhostOverride() const {
return m_GhostOverride;
}
void Player::ObserveEntity(int32_t id)
{
for (int32_t i = 0; i < m_ObservedEntitiesUsed; i++)
{
if (m_ObservedEntities[i] == 0 || m_ObservedEntities[i] == id)
{
void Player::ObserveEntity(int32_t id) {
for (int32_t i = 0; i < m_ObservedEntitiesUsed; i++) {
if (m_ObservedEntities[i] == 0 || m_ObservedEntities[i] == id) {
m_ObservedEntities[i] = id;
return;
@ -216,8 +187,7 @@ void Player::ObserveEntity(int32_t id)
const auto index = m_ObservedEntitiesUsed++;
if (m_ObservedEntitiesUsed > m_ObservedEntitiesLength)
{
if (m_ObservedEntitiesUsed > m_ObservedEntitiesLength) {
m_ObservedEntities.resize(m_ObservedEntitiesLength + m_ObservedEntitiesLength);
m_ObservedEntitiesLength = m_ObservedEntitiesLength + m_ObservedEntitiesLength;
@ -226,12 +196,9 @@ void Player::ObserveEntity(int32_t id)
m_ObservedEntities[index] = id;
}
bool Player::IsObserved(int32_t id)
{
for (int32_t i = 0; i < m_ObservedEntitiesUsed; i++)
{
if (m_ObservedEntities[i] == id)
{
bool Player::IsObserved(int32_t id) {
for (int32_t i = 0; i < m_ObservedEntitiesUsed; i++) {
if (m_ObservedEntities[i] == id) {
return true;
}
}
@ -239,34 +206,27 @@ bool Player::IsObserved(int32_t id)
return false;
}
void Player::GhostEntity(int32_t id)
{
for (int32_t i = 0; i < m_ObservedEntitiesUsed; i++)
{
if (m_ObservedEntities[i] == id)
{
void Player::GhostEntity(int32_t id) {
for (int32_t i = 0; i < m_ObservedEntitiesUsed; i++) {
if (m_ObservedEntities[i] == id) {
m_ObservedEntities[i] = 0;
}
}
}
Player* Player::GetPlayer(const SystemAddress& sysAddr)
{
Player* Player::GetPlayer(const SystemAddress& sysAddr) {
auto* entity = UserManager::Instance()->GetUser(sysAddr)->GetLastUsedChar()->GetEntity();
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);
for (auto* character : characters)
{
for (auto* character : characters) {
if (!character->IsPlayer()) continue;
if (character->GetCharacter()->GetName() == name)
{
if (character->GetCharacter()->GetName() == name) {
return static_cast<Player*>(character);
}
}
@ -274,12 +234,9 @@ Player* Player::GetPlayer(const std::string& name)
return nullptr;
}
Player* Player::GetPlayer(LWOOBJID playerID)
{
for (auto* player : m_Players)
{
if (player->GetObjectID() == playerID)
{
Player* Player::GetPlayer(LWOOBJID playerID) {
for (auto* player : m_Players) {
if (player->GetObjectID() == playerID) {
return player;
}
}
@ -287,8 +244,7 @@ Player* Player::GetPlayer(LWOOBJID playerID)
return nullptr;
}
const std::vector<Player*>& Player::GetAllPlayers()
{
const std::vector<Player*>& Player::GetAllPlayers() {
return m_Players;
}
@ -300,23 +256,19 @@ void Player::SetDroppedCoins(uint64_t value) {
m_DroppedCoins = value;
}
Player::~Player()
{
Game::logger->Log("Player", "Deleted player\n");
Player::~Player() {
Game::logger->Log("Player", "Deleted player");
for (int32_t i = 0; i < m_ObservedEntitiesUsed; i++)
{
for (int32_t i = 0; i < m_ObservedEntitiesUsed; i++) {
const auto id = m_ObservedEntities[i];
if (id == 0)
{
if (id == 0) {
continue;
}
auto* entity = EntityManager::Instance()->GetGhostCandidate(id);
if (entity != nullptr)
{
if (entity != nullptr) {
entity->SetObservers(entity->GetObservers() - 1);
}
}
@ -325,8 +277,7 @@ Player::~Player()
const auto& iter = std::find(m_Players.begin(), m_Players.end(), this);
if (iter == m_Players.end())
{
if (iter == m_Players.end()) {
return;
}

View File

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

View File

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

View File

@ -12,122 +12,93 @@
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_ParticipantA = participantA;
m_ParticipantB = participantB;
}
Trade::~Trade()
{
Trade::~Trade() {
}
LWOOBJID Trade::GetTradeId() const
{
LWOOBJID Trade::GetTradeId() const {
return m_TradeId;
}
bool Trade::IsParticipant(LWOOBJID playerId) const
{
bool Trade::IsParticipant(LWOOBJID playerId) const {
return m_ParticipantA == playerId || m_ParticipantB == playerId;
}
LWOOBJID Trade::GetParticipantA() const
{
LWOOBJID Trade::GetParticipantA() const {
return m_ParticipantA;
}
LWOOBJID Trade::GetParticipantB() const
{
LWOOBJID Trade::GetParticipantB() const {
return m_ParticipantB;
}
Entity* Trade::GetParticipantAEntity() const
{
Entity* Trade::GetParticipantAEntity() const {
return EntityManager::Instance()->GetEntity(m_ParticipantA);
}
Entity* Trade::GetParticipantBEntity() const
{
Entity* Trade::GetParticipantBEntity() const {
return EntityManager::Instance()->GetEntity(m_ParticipantB);
}
void Trade::SetCoins(LWOOBJID participant, uint64_t coins)
{
if (participant == m_ParticipantA)
{
void Trade::SetCoins(LWOOBJID participant, uint64_t coins) {
if (participant == m_ParticipantA) {
m_CoinsA = coins;
}
else if (participant == m_ParticipantB)
{
} else if (participant == m_ParticipantB) {
m_CoinsB = coins;
}
}
void Trade::SetItems(LWOOBJID participant, std::vector<TradeItem> items)
{
if (participant == m_ParticipantA)
{
void Trade::SetItems(LWOOBJID participant, std::vector<TradeItem> items) {
if (participant == m_ParticipantA) {
m_ItemsA = items;
}
else if (participant == m_ParticipantB)
{
} else if (participant == m_ParticipantB) {
m_ItemsB = items;
}
}
void Trade::SetAccepted(LWOOBJID participant, bool value)
{
if (participant == m_ParticipantA)
{
void Trade::SetAccepted(LWOOBJID participant, bool value) {
if (participant == m_ParticipantA) {
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();
if (entityB != nullptr)
{
if (entityB != nullptr) {
GameMessages::SendServerTradeAccept(m_ParticipantB, value, entityB->GetSystemAddress());
}
}
else if (participant == m_ParticipantB)
{
} else if (participant == m_ParticipantB) {
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();
if (entityA != nullptr)
{
if (entityA != nullptr) {
GameMessages::SendServerTradeAccept(m_ParticipantA, value, entityA->GetSystemAddress());
}
}
if (m_AcceptedA && m_AcceptedB)
{
if (m_AcceptedA && m_AcceptedB) {
auto* entityB = GetParticipantBEntity();
if (entityB != nullptr)
{
if (entityB != nullptr) {
GameMessages::SendServerTradeAccept(m_ParticipantB, false, entityB->GetSystemAddress());
}
else
{
} else {
return;
}
auto* entityA = GetParticipantAEntity();
if (entityA != nullptr)
{
if (entityA != nullptr) {
GameMessages::SendServerTradeAccept(m_ParticipantA, false, entityA->GetSystemAddress());
}
else
{
} else {
return;
}
@ -135,8 +106,7 @@ void Trade::SetAccepted(LWOOBJID participant, bool value)
}
}
void Trade::Complete()
{
void Trade::Complete() {
auto* entityA = GetParticipantAEntity();
auto* entityB = GetParticipantBEntity();
@ -154,27 +124,23 @@ void Trade::Complete()
characterA->SetCoins(characterA->GetCoins() - m_CoinsA + m_CoinsB, 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);
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);
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);
}
for (const auto& tradeItem : m_ItemsB)
{
for (const auto& tradeItem : m_ItemsB) {
inventoryA->AddItem(tradeItem.itemLot, tradeItem.itemCount, eLootSourceType::LOOT_SOURCE_TRADE);
}
@ -184,8 +150,7 @@ void Trade::Complete()
characterB->SaveXMLToDatabase();
}
void Trade::Cancel()
{
void Trade::Cancel() {
auto* entityA = GetParticipantAEntity();
auto* entityB = GetParticipantBEntity();
@ -195,31 +160,25 @@ void Trade::Cancel()
GameMessages::SendServerTradeCancel(entityB->GetObjectID(), entityB->GetSystemAddress());
}
void Trade::SendUpdateToOther(LWOOBJID participant)
{
void Trade::SendUpdateToOther(LWOOBJID participant) {
Entity* other = nullptr;
Entity* self = nullptr;
uint64_t coins;
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();
self = GetParticipantAEntity();
coins = m_CoinsA;
itemIds = m_ItemsA;
}
else if (participant == m_ParticipantB)
{
} else if (participant == m_ParticipantB) {
other = GetParticipantAEntity();
self = GetParticipantBEntity();
coins = m_CoinsB;
itemIds = m_ItemsB;
}
else
{
} else {
return;
}
@ -231,8 +190,7 @@ void Trade::SendUpdateToOther(LWOOBJID participant)
if (inventoryComponent == nullptr) return;
for (const auto tradeItem : itemIds)
{
for (const auto tradeItem : itemIds) {
auto* item = inventoryComponent->FindItemById(tradeItem.itemId);
if (item == nullptr) return;
@ -242,27 +200,23 @@ void Trade::SendUpdateToOther(LWOOBJID participant)
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());
}
TradingManager::TradingManager()
{
TradingManager::TradingManager() {
}
TradingManager::~TradingManager()
{
for (const auto& pair : trades)
{
TradingManager::~TradingManager() {
for (const auto& pair : trades) {
delete pair.second;
}
trades.clear();
}
Trade* TradingManager::GetTrade(LWOOBJID tradeId) const
{
Trade* TradingManager::GetTrade(LWOOBJID tradeId) const {
const auto& pair = trades.find(tradeId);
if (pair == trades.end()) return nullptr;
@ -270,12 +224,9 @@ Trade* TradingManager::GetTrade(LWOOBJID tradeId) const
return pair->second;
}
Trade* TradingManager::GetPlayerTrade(LWOOBJID playerId) const
{
for (const auto& pair : trades)
{
if (pair.second->IsParticipant(playerId))
{
Trade* TradingManager::GetPlayerTrade(LWOOBJID playerId) const {
for (const auto& pair : trades) {
if (pair.second->IsParticipant(playerId)) {
return pair.second;
}
}
@ -283,8 +234,7 @@ Trade* TradingManager::GetPlayerTrade(LWOOBJID playerId) const
return nullptr;
}
void TradingManager::CancelTrade(LWOOBJID tradeId)
{
void TradingManager::CancelTrade(LWOOBJID tradeId) {
auto* trade = GetTrade(tradeId);
if (trade == nullptr) return;
@ -294,15 +244,14 @@ void TradingManager::CancelTrade(LWOOBJID tradeId)
trades.erase(tradeId);
}
Trade* TradingManager::NewTrade(LWOOBJID participantA, LWOOBJID participantB)
{
Trade* TradingManager::NewTrade(LWOOBJID participantA, LWOOBJID participantB) {
const LWOOBJID tradeId = ObjectIDManager::Instance()->GenerateObjectID();
auto* trade = new Trade(tradeId, participantA, participantB);
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;
}

View File

@ -19,6 +19,8 @@ User::User(const SystemAddress& sysAddr, const std::string& username, const std:
m_Username = username;
m_LoggedInCharID = 0;
m_IsBestFriendMap = std::unordered_map<std::string, bool>();
//HACK HACK HACK
//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.
@ -48,7 +50,7 @@ User::User(const SystemAddress& sysAddr, const std::string& username, const std:
LWOOBJID objID = res->getUInt64(1);
Character* character = new Character(uint32_t(objID), this);
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);
}
time_t User::GetMuteExpire() const
{
time_t User::GetMuteExpire() const {
return m_MuteExpire;
}
void User::SetMuteExpire(time_t value)
{
void User::SetMuteExpire(time_t value) {
m_MuteExpire = value;
}
@ -126,7 +125,7 @@ void User::UserOutOfSync() {
m_AmountOfTimesOutOfSync++;
if (m_AmountOfTimesOutOfSync > m_MaxDesyncAllowed) {
//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);
}
}

View File

@ -42,6 +42,9 @@ public:
bool GetLastChatMessageApproved() { return m_LastChatMessageApproved; }
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;
time_t GetMuteExpire() const;
@ -63,6 +66,8 @@ private:
std::vector<Character*> m_Characters;
LWOOBJID m_LoggedInCharID;
std::unordered_map<std::string, bool> m_IsBestFriendMap;
bool m_LastChatMessageApproved = false;
int m_AmountOfTimesOutOfSync = 0;
const int m_MaxDesyncAllowed = 12;

View File

@ -109,8 +109,7 @@ User* UserManager::GetUser ( const std::string& username ) {
bool UserManager::DeleteUser(const SystemAddress& 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;
m_UsersToDelete.push_back(it->second);
@ -123,11 +122,9 @@ bool UserManager::DeleteUser ( const SystemAddress& sysAddr ) {
return false;
}
void UserManager::DeletePendingRemovals()
{
for (auto* user : m_UsersToDelete)
{
Game::logger->Log("UserManager", "Deleted user %i\n", user->GetAccountID());
void UserManager::DeletePendingRemovals() {
for (auto* user : m_UsersToDelete) {
Game::logger->Log("UserManager", "Deleted user %i", user->GetAccountID());
delete user;
}
@ -185,8 +182,7 @@ void UserManager::RequestCharacterList ( const SystemAddress& sysAddr ) {
if (res->rowsCount() > 0) {
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
{
delete chars[i];
@ -196,8 +192,7 @@ void UserManager::RequestCharacterList ( const SystemAddress& sysAddr ) {
auto* skillComponent = chars[i]->GetEntity()->GetComponent<SkillComponent>();
if (skillComponent != nullptr)
{
if (skillComponent != nullptr) {
skillComponent->Reset();
}
@ -251,22 +246,21 @@ void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet)
LOT pantsLOT = FindCharPantsID(pantsColor);
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);
return;
}
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);
return;
}
if (name == "") {
Game::logger->Log("UserManager", "AccountID: %i is creating a character with predefined name: %s\n", u->GetAccountID(), predefinedName.c_str());
}
else {
Game::logger->Log("UserManager", "AccountID: %i is creating a character with name: %s (temporary: %s)\n", u->GetAccountID(), name.c_str(), predefinedName.c_str());
Game::logger->Log("UserManager", "AccountID: %i is creating a character with predefined name: %s", u->GetAccountID(), predefinedName.c_str());
} else {
Game::logger->Log("UserManager", "AccountID: %i is creating a character with name: %s (temporary: %s)", u->GetAccountID(), name.c_str(), predefinedName.c_str());
}
//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();
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);
return;
}
@ -364,14 +358,14 @@ void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet)
void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet) {
User* u = GetUser(sysAddr);
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;
}
LWOOBJID objectID = PacketUtils::ReadPacketS64(8, packet);
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:
bool hasCharacter = false;
@ -381,11 +375,10 @@ void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet)
}
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);
}
else {
Game::logger->Log("UserManager", "Deleting character %i\n", charID);
} else {
Game::logger->Log("UserManager", "Deleting character %i", charID);
{
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("DELETE FROM charxml WHERE id=? LIMIT 1;");
stmt->setUInt64(1, charID);
@ -461,7 +454,7 @@ void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet)
void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet) {
User* u = GetUser(sysAddr);
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;
}
@ -470,7 +463,7 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
objectID = GeneralUtils::ClearBit(objectID, OBJECT_BIT_PERSISTENT);
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);
@ -484,7 +477,7 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
}
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);
} else if (hasCharacter && character) {
if (newName == character->GetName()) {
@ -501,7 +494,7 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
stmt->execute();
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);
UserManager::RequestCharacterList(sysAddr);
} else {
@ -512,7 +505,7 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
stmt->execute();
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);
UserManager::RequestCharacterList(sysAddr);
}
@ -520,7 +513,7 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
WorldPackets::SendCharacterRenameResponse(sysAddr, RENAME_RESPONSE_NAME_IN_USE);
}
} 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);
}
}
@ -528,7 +521,7 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
void UserManager::LoginCharacter(const SystemAddress& sysAddr, uint32_t playerID) {
User* u = GetUser(sysAddr);
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;
}
@ -551,7 +544,7 @@ void UserManager::LoginCharacter(const SystemAddress& sysAddr, uint32_t playerID
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) {
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) {
character->SetZoneID(zoneID);
character->SetZoneInstance(zoneInstance);
@ -561,7 +554,7 @@ void UserManager::LoginCharacter(const SystemAddress& sysAddr, uint32_t playerID
return;
});
} 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);
tableData.finalize();
return shirtLOT;
}
catch (const std::exception&){
} catch (const std::exception&) {
Game::logger->Log("Character Create", "Failed to execute query! Using backup...");
// in case of no shirt found in CDServer, return problematic red vest.
return 4069;
@ -591,8 +583,7 @@ uint32_t FindCharPantsID(uint32_t pantsColor) {
auto pantsLOT = tableData.getIntField(0, -1);
tableData.finalize();
return pantsLOT;
}
catch (const std::exception&){
} catch (const std::exception&) {
Game::logger->Log("Character Create", "Failed to execute query! Using backup...");
// in case of no pants color found in CDServer, return red pants.
return 2508;

View File

@ -1,10 +1,9 @@
#include "AirMovementBehavior.h"
#include "AirMovementBehavior.h"
#include "BehaviorBranchContext.h"
#include "BehaviorContext.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;
bitStream->Read(handle);
@ -12,15 +11,13 @@ void AirMovementBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bi
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();
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;
bit_stream->Read(behaviorId);
@ -31,14 +28,12 @@ void AirMovementBehavior::Sync(BehaviorContext* context, RakNet::BitStream* bit_
auto* behavior = CreateBehavior(behaviorId);
if (EntityManager::Instance()->GetEntity(target) != nullptr)
{
if (EntityManager::Instance()->GetEntity(target) != nullptr) {
branch.target = target;
}
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"
class AirMovementBehavior final : public Behavior
@ -9,8 +9,7 @@ public:
* 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;

View File

@ -1,4 +1,4 @@
#include "AndBehavior.h"
#include "AndBehavior.h"
#include "BehaviorBranchContext.h"
#include "Game.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)
{
for (auto* behavior : this->m_behaviors)
{
void AndBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) {
for (auto* behavior : this->m_behaviors) {
behavior->Calculate(context, bitStream, branch);
}
}

View File

@ -1,4 +1,4 @@
#pragma once
#pragma once
#include <vector>
@ -12,8 +12,7 @@ public:
/*
* 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;

View File

@ -5,8 +5,7 @@
#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);
if (entity == nullptr) return;
@ -19,8 +18,7 @@ void ApplyBuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitS
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);
if (entity == nullptr) return;
@ -32,13 +30,11 @@ void ApplyBuffBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext b
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);
}
void ApplyBuffBehavior::Load()
{
void ApplyBuffBehavior::Load() {
m_BuffId = GetInt("buff_id");
m_Duration = GetFloat("duration_secs");
addImmunity = GetBoolean("add_immunity");

View File

@ -21,8 +21,7 @@ public:
/*
* 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;

View File

@ -1,4 +1,4 @@
#include "AreaOfEffectBehavior.h"
#include "AreaOfEffectBehavior.h"
#include <vector>
@ -10,14 +10,12 @@
#include "RebuildComponent.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;
bitStream->Read(targetCount);
if (targetCount > this->m_maxTargets)
{
if (targetCount > this->m_maxTargets) {
return;
}
@ -25,8 +23,7 @@ void AreaOfEffectBehavior::Handle(BehaviorContext* context, RakNet::BitStream* b
targets.reserve(targetCount);
for (auto i = 0u; i < targetCount; ++i)
{
for (auto i = 0u; i < targetCount; ++i) {
LWOOBJID target;
bitStream->Read(target);
@ -34,21 +31,18 @@ void AreaOfEffectBehavior::Handle(BehaviorContext* context, RakNet::BitStream* b
targets.push_back(target);
}
for (auto target : targets)
{
for (auto target : targets) {
branch.target = target;
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);
if (self == nullptr)
{
Game::logger->Log("TacArcBehavior", "Invalid self for (%llu)!\n", context->originator);
if (self == nullptr) {
Game::logger->Log("TacArcBehavior", "Invalid self for (%llu)!", context->originator);
return;
}
@ -59,10 +53,8 @@ void AreaOfEffectBehavior::Calculate(BehaviorContext* context, RakNet::BitStream
auto* presetTarget = EntityManager::Instance()->GetEntity(branch.target);
if (presetTarget != nullptr)
{
if (this->m_radius * this->m_radius >= Vector3::DistanceSquared(reference, presetTarget->GetPosition()))
{
if (presetTarget != nullptr) {
if (this->m_radius * this->m_radius >= Vector3::DistanceSquared(reference, presetTarget->GetPosition())) {
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
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);
if (entity == nullptr)
{
Game::logger->Log("TacArcBehavior", "Invalid target (%llu) for (%llu)!\n", validTarget, context->originator);
if (entity == nullptr) {
Game::logger->Log("TacArcBehavior", "Invalid target (%llu) for (%llu)!", validTarget, context->originator);
continue;
}
if (std::find(targets.begin(), targets.end(), entity) != targets.end())
{
if (std::find(targets.begin(), targets.end(), entity) != targets.end()) {
continue;
}
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
if (destroyableComponent == nullptr)
{
if (destroyableComponent == nullptr) {
continue;
}
if (destroyableComponent->HasFaction(m_ignoreFaction))
{
if (destroyableComponent->HasFaction(m_ignoreFaction)) {
continue;
}
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);
}
}
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 bDistance = Vector3::DistanceSquared(b->GetPosition(), reference);
@ -123,30 +108,26 @@ void AreaOfEffectBehavior::Calculate(BehaviorContext* context, RakNet::BitStream
bitStream->Write(size);
if (size == 0)
{
if (size == 0) {
return;
}
context->foundTarget = true;
for (auto* target : targets)
{
for (auto* target : targets) {
bitStream->Write(target->GetObjectID());
PlayFx(u"cast", context->originator, target->GetObjectID());
}
for (auto* target : targets)
{
for (auto* target : targets) {
branch.target = target->GetObjectID();
this->m_action->Calculate(context, bitStream, branch);
}
}
void AreaOfEffectBehavior::Load()
{
void AreaOfEffectBehavior::Load() {
this->m_action = GetAction("action");
this->m_radius = GetFloat("radius");

View File

@ -1,4 +1,4 @@
#pragma once
#pragma once
#include "Behavior.h"
class AreaOfEffectBehavior final : public Behavior
@ -23,8 +23,7 @@ public:
/*
* 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;

View File

@ -1,51 +1,44 @@
#include "AttackDelayBehavior.h"
#include "AttackDelayBehavior.h"
#include "BehaviorBranchContext.h"
#include "BehaviorContext.h"
#include "Game.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;
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);
}
}
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();
bitStream->Write(handle);
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);
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);
}
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);
this->m_action->Calculate(context, bitStream, branch);
}
void AttackDelayBehavior::Load()
{
void AttackDelayBehavior::Load() {
this->m_numIntervals = GetInt("num_intervals");
this->m_action = GetAction("action");
@ -54,8 +47,7 @@ void AttackDelayBehavior::Load()
this->m_ignoreInterrupts = GetBoolean("ignore_interrupts");
if (this->m_numIntervals == 0)
{
if (this->m_numIntervals == 0) {
this->m_numIntervals = 1;
}
}

View File

@ -1,4 +1,4 @@
#pragma once
#pragma once
#include "Behavior.h"
class AttackDelayBehavior final : public Behavior
@ -16,8 +16,7 @@ public:
* 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;

View File

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

View File

@ -1,4 +1,4 @@
#pragma once
#pragma once
#include "Behavior.h"
class BasicAttackBehavior final : public Behavior
@ -10,8 +10,7 @@ public:
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;

View File

@ -1,4 +1,4 @@
#include <sstream>
#include <sstream>
#include <algorithm>
#include "Behavior.h"
@ -73,34 +73,28 @@
std::unordered_map<uint32_t, Behavior*> Behavior::Cache = {};
CDBehaviorParameterTable* Behavior::BehaviorParameterTable = nullptr;
Behavior* Behavior::GetBehavior(const uint32_t behaviorId)
{
if (BehaviorParameterTable == nullptr)
{
Behavior* Behavior::GetBehavior(const uint32_t behaviorId) {
if (BehaviorParameterTable == nullptr) {
BehaviorParameterTable = CDClientManager::Instance()->GetTable<CDBehaviorParameterTable>("BehaviorParameter");
}
const auto pair = Cache.find(behaviorId);
if (pair == Cache.end())
{
if (pair == Cache.end()) {
return nullptr;
}
return static_cast<Behavior*>(pair->second);
}
Behavior* Behavior::CreateBehavior(const uint32_t behaviorId)
{
Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) {
auto* cached = GetBehavior(behaviorId);
if (cached != nullptr)
{
if (cached != nullptr) {
return cached;
}
if (behaviorId == 0)
{
if (behaviorId == 0) {
return new EmptyBehavior(0);
}
@ -108,8 +102,7 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId)
Behavior* behavior = nullptr;
switch (templateId)
{
switch (templateId) {
case BehaviorTemplates::BEHAVIOR_EMPTY: break;
case BehaviorTemplates::BEHAVIOR_BASIC_ATTACK:
behavior = new BasicAttackBehavior(behaviorId);
@ -269,13 +262,12 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId)
case BehaviorTemplates::BEHAVIOR_MOUNT: break;
case BehaviorTemplates::BEHAVIOR_SKILL_SET: break;
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;
}
if (behavior == nullptr)
{
//Game::logger->Log("Behavior", "Failed to load unimplemented template id (%i)!\n", templateId);
if (behavior == nullptr) {
//Game::logger->Log("Behavior", "Failed to load unimplemented template id (%i)!", templateId);
behavior = new EmptyBehavior(behaviorId);
}
@ -298,26 +290,23 @@ BehaviorTemplates Behavior::GetBehaviorTemplate(const uint32_t behaviorId) {
}
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;
}
// 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);
if (targetEntity == nullptr)
{
if (targetEntity == nullptr) {
return;
}
const auto effectId = this->m_effectId;
if (effectId == 0)
{
if (effectId == 0) {
GameMessages::SendPlayFXEffect(targetEntity, -1, type, "", secondary, 1, 1, true);
return;
@ -327,23 +316,17 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID
const auto typeString = GeneralUtils::UTF16ToWTF8(type);
if (m_effectNames == nullptr)
{
if (m_effectNames == nullptr) {
m_effectNames = new std::unordered_map<std::string, std::string>();
}
else
{
} else {
const auto pair = m_effectNames->find(typeString);
if (type.empty())
{
if (type.empty()) {
type = GeneralUtils::ASCIIToUTF16(*m_effectType);
}
if (pair != m_effectNames->end())
{
if (renderComponent == nullptr)
{
if (pair != m_effectNames->end()) {
if (renderComponent == nullptr) {
GameMessages::SendPlayFXEffect(targetEntity, effectId, type, pair->second, secondary, 1, 1, true);
return;
@ -375,15 +358,13 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID
result = idQuery.execQuery();
}
if (result.eof() || result.fieldIsNull(0))
{
if (result.eof() || result.fieldIsNull(0)) {
return;
}
const auto name = std::string(result.getStringField(0));
if (type.empty())
{
if (type.empty()) {
const auto typeResult = result.getStringField(1);
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);
if (renderComponent == nullptr)
{
if (renderComponent == nullptr) {
GameMessages::SendPlayFXEffect(targetEntity, effectId, type, name, secondary, 1, 1, true);
return;
@ -405,8 +385,7 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID
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");
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
if (templateInDatabase.behaviorID == 0)
{
Game::logger->Log("Behavior", "Failed to load behavior with id (%i)!\n", behaviorId);
if (templateInDatabase.behaviorID == 0) {
Game::logger->Log("Behavior", "Failed to load behavior with id (%i)!", behaviorId);
this->m_effectId = 0;
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.
if (!BehaviorParameterTable) BehaviorParameterTable = CDClientManager::Instance()->GetTable<CDBehaviorParameterTable>("BehaviorParameter");
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;
}
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));
}
Behavior* Behavior::GetAction(const std::string& name) const
{
Behavior* Behavior::GetAction(const std::string& name) const {
const auto id = GetInt(name);
return CreateBehavior(id);
}
Behavior* Behavior::GetAction(float value) const
{
Behavior* Behavior::GetAction(float value) const {
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;
// Find behavior template by its behavior id.
/*if (!BehaviorParameterTable) BehaviorParameterTable = CDClientManager::Instance()->GetTable<CDBehaviorParameterTable>("BehaviorParameter");
@ -493,40 +465,31 @@ std::map<std::string, float> Behavior::GetParameterNames() const
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_effectType;
delete m_effectHandle;

View File

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

View File

@ -1,13 +1,11 @@
#include "BehaviorBranchContext.h"
#include "BehaviorBranchContext.h"
BehaviorBranchContext::BehaviorBranchContext()
{
BehaviorBranchContext::BehaviorBranchContext() {
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->duration = duration;
this->referencePosition = referencePosition;

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
#pragma once
#pragma once
#include "Behavior.h"
class BlockBehavior final : public Behavior
@ -10,8 +10,7 @@ public:
* 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;

View File

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

View File

@ -1,4 +1,4 @@
#pragma once
#pragma once
#include "Behavior.h"
class BuffBehavior final : public Behavior
@ -13,8 +13,7 @@ public:
/*
* 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;

View File

@ -8,18 +8,16 @@
#include "dLogger.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);
auto* entity = EntityManager::Instance()->GetEntity(context->originator);
if (entity == nullptr)
{
if (entity == nullptr) {
return;
}
Game::logger->Log("Car boost", "Activating car boost!\n");
Game::logger->Log("Car boost", "Activating car boost!");
auto* possessableComponent = entity->GetComponent<PossessableComponent>();
if (possessableComponent != nullptr) {
@ -29,7 +27,7 @@ void CarBoostBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitSt
auto* characterComponent = possessor->GetComponent<CharacterComponent>();
if (characterComponent != nullptr) {
Game::logger->Log("Car boost", "Tracking car boost!\n");
Game::logger->Log("Car boost", "Tracking car boost!");
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_Time = GetFloat("time");

View File

@ -14,8 +14,7 @@ public:
* 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;

View File

@ -1,24 +1,21 @@
#include "ChainBehavior.h"
#include "ChainBehavior.h"
#include "BehaviorBranchContext.h"
#include "Game.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;
bitStream->Read(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);
}
}
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);
this->m_behaviors.at(0)->Calculate(context, bitStream, branch);

View File

@ -1,4 +1,4 @@
#pragma once
#pragma once
#include "Behavior.h"
@ -13,8 +13,7 @@ public:
* 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;

View File

@ -4,12 +4,10 @@
#include "EntityManager.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
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 destination = self->GetPosition();
if (m_OrientCaster)
{
if (m_OrientCaster) {
auto* baseCombatAIComponent = self->GetComponent<BaseCombatAIComponent>();
/*if (baseCombatAIComponent != nullptr)
@ -34,17 +31,14 @@ void ChangeOrientationBehavior::Calculate(BehaviorContext* context, RakNet::BitS
}
EntityManager::Instance()->SerializeEntity(self);
}
else
{
} else {
other->SetRotation(NiQuaternion::LookAt(destination, source));
EntityManager::Instance()->SerializeEntity(other);
}
}
void ChangeOrientationBehavior::Load()
{
void ChangeOrientationBehavior::Load() {
m_OrientCaster = GetBoolean("orient_caster");
m_ToTarget = GetBoolean("to_target");
}

View File

@ -14,8 +14,7 @@ public:
* 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;

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