mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-07-07 04:00:02 +00:00
Merge branch 'main' into cdclient-rework
This commit is contained in:
commit
633b87a5e7
76
.editorconfig
Normal file
76
.editorconfig
Normal 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
8
.git-blame-ignore-revs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# format codebase
|
||||||
|
19e77a38d837ce781ba0ca6ea8e78b67a6e3b5a5
|
||||||
|
|
||||||
|
# add semi-colons to macros consistently
|
||||||
|
9e4ce24fd2851e65df776dd9c57bcb0d45f4453a
|
||||||
|
|
||||||
|
# convert to unix line endings
|
||||||
|
72477e01e2711e0f61cdb192ee266e5e21b8846f
|
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -1 +1 @@
|
|||||||
*.sh eol=lf
|
* text=auto eol=lf
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -120,3 +120,5 @@ thirdparty/zlib-1.2.11/
|
|||||||
docker/__pycache__
|
docker/__pycache__
|
||||||
|
|
||||||
docker-compose.override.yml
|
docker-compose.override.yml
|
||||||
|
|
||||||
|
!/tests/TestBitStreams/*.bin
|
||||||
|
@ -42,6 +42,12 @@ set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT
|
|||||||
# Echo the version
|
# Echo the version
|
||||||
message(STATUS "Version: ${PROJECT_VERSION}")
|
message(STATUS "Version: ${PROJECT_VERSION}")
|
||||||
|
|
||||||
|
# Disable demo, tests and examples for recastNavigation. Turn these to ON if you want to use them
|
||||||
|
# This has to be done here to prevent a rare build error due to missing dependencies on the initial generations.
|
||||||
|
set(RECASTNAVIGATION_DEMO OFF CACHE BOOL "" FORCE)
|
||||||
|
set(RECASTNAVIGATION_TESTS OFF CACHE BOOL "" FORCE)
|
||||||
|
set(RECASTNAVIGATION_EXAMPLES OFF CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
# Compiler flags:
|
# Compiler flags:
|
||||||
# Disabled deprecated warnings as the MySQL includes have deprecated code in them.
|
# Disabled deprecated warnings as the MySQL includes have deprecated code in them.
|
||||||
# Disabled misleading indentation as DL_LinkedList from RakNet has a weird indent.
|
# Disabled misleading indentation as DL_LinkedList from RakNet has a weird indent.
|
||||||
@ -54,7 +60,7 @@ if(UNIX)
|
|||||||
else()
|
else()
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17 -O2 -Wuninitialized -D_GLIBCXX_USE_CXX11_ABI=0 -D_GLIBCXX_USE_CXX17_ABI=0 -static-libgcc -fPIC")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17 -O2 -Wuninitialized -D_GLIBCXX_USE_CXX11_ABI=0 -D_GLIBCXX_USE_CXX17_ABI=0 -static-libgcc -fPIC")
|
||||||
endif()
|
endif()
|
||||||
if (__dynamic)
|
if (__dynamic AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -rdynamic")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -rdynamic")
|
||||||
endif()
|
endif()
|
||||||
if (__ggdb)
|
if (__ggdb)
|
||||||
@ -63,7 +69,7 @@ if(UNIX)
|
|||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -O2 -fPIC")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -O2 -fPIC")
|
||||||
elseif(MSVC)
|
elseif(MSVC)
|
||||||
# Skip warning for invalid conversion from size_t to uint32_t for all targets below for now
|
# Skip warning for invalid conversion from size_t to uint32_t for all targets below for now
|
||||||
add_compile_options("/wd4267")
|
add_compile_options("/wd4267" "/utf-8")
|
||||||
elseif(WIN32)
|
elseif(WIN32)
|
||||||
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
|
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
|
||||||
endif()
|
endif()
|
||||||
@ -83,14 +89,15 @@ make_directory(${CMAKE_BINARY_DIR}/locale)
|
|||||||
# Create a /logs directory
|
# Create a /logs directory
|
||||||
make_directory(${CMAKE_BINARY_DIR}/logs)
|
make_directory(${CMAKE_BINARY_DIR}/logs)
|
||||||
|
|
||||||
# Copy ini files on first build
|
# Copy resource files on first build
|
||||||
set(INI_FILES "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini")
|
set(RESOURCE_FILES "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini" "blacklist.dcf")
|
||||||
foreach(ini ${INI_FILES})
|
foreach(resource_file ${RESOURCE_FILES})
|
||||||
if (NOT EXISTS ${PROJECT_BINARY_DIR}/${ini})
|
if (NOT EXISTS ${PROJECT_BINARY_DIR}/${resource_file})
|
||||||
configure_file(
|
configure_file(
|
||||||
${CMAKE_SOURCE_DIR}/resources/${ini} ${PROJECT_BINARY_DIR}/${ini}
|
${CMAKE_SOURCE_DIR}/resources/${resource_file} ${PROJECT_BINARY_DIR}/${resource_file}
|
||||||
COPYONLY
|
COPYONLY
|
||||||
)
|
)
|
||||||
|
message("Moved ${resource_file} to project binary directory")
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
@ -126,6 +133,8 @@ set(INCLUDED_DIRECTORIES
|
|||||||
"dGame/dEntity"
|
"dGame/dEntity"
|
||||||
"dGame/dUtilities"
|
"dGame/dUtilities"
|
||||||
"dPhysics"
|
"dPhysics"
|
||||||
|
"dNavigation"
|
||||||
|
"dNavigation/dTerrain"
|
||||||
"dZoneManager"
|
"dZoneManager"
|
||||||
"dDatabase"
|
"dDatabase"
|
||||||
"dDatabase/Tables"
|
"dDatabase/Tables"
|
||||||
@ -134,8 +143,7 @@ set(INCLUDED_DIRECTORIES
|
|||||||
|
|
||||||
"thirdparty/raknet/Source"
|
"thirdparty/raknet/Source"
|
||||||
"thirdparty/tinyxml2"
|
"thirdparty/tinyxml2"
|
||||||
"thirdparty/recastnavigation/Recast/Include"
|
"thirdparty/recastnavigation"
|
||||||
"thirdparty/recastnavigation/Detour/Include"
|
|
||||||
"thirdparty/SQLite"
|
"thirdparty/SQLite"
|
||||||
"thirdparty/cpplinq"
|
"thirdparty/cpplinq"
|
||||||
)
|
)
|
||||||
@ -152,7 +160,6 @@ elseif (UNIX)
|
|||||||
set(INCLUDED_DIRECTORIES ${INCLUDED_DIRECTORIES} "thirdparty/libbcrypt/include/bcrypt")
|
set(INCLUDED_DIRECTORIES ${INCLUDED_DIRECTORIES} "thirdparty/libbcrypt/include/bcrypt")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
|
||||||
# Add binary directory as an include directory
|
# Add binary directory as an include directory
|
||||||
include_directories(${PROJECT_BINARY_DIR})
|
include_directories(${PROJECT_BINARY_DIR})
|
||||||
|
|
||||||
@ -205,6 +212,7 @@ add_subdirectory(dNet)
|
|||||||
add_subdirectory(dScripts) # Add for dGame to use
|
add_subdirectory(dScripts) # Add for dGame to use
|
||||||
add_subdirectory(dGame)
|
add_subdirectory(dGame)
|
||||||
add_subdirectory(dZoneManager)
|
add_subdirectory(dZoneManager)
|
||||||
|
add_subdirectory(dNavigation)
|
||||||
add_subdirectory(dPhysics)
|
add_subdirectory(dPhysics)
|
||||||
|
|
||||||
# Create a list of common libraries shared between all binaries
|
# Create a list of common libraries shared between all binaries
|
||||||
|
@ -118,6 +118,11 @@
|
|||||||
"execution": {
|
"execution": {
|
||||||
"jobs": 2
|
"jobs": 2
|
||||||
},
|
},
|
||||||
|
"filter": {
|
||||||
|
"exclude": {
|
||||||
|
"name": "((example)|(minigzip))+"
|
||||||
|
}
|
||||||
|
},
|
||||||
"output": {
|
"output": {
|
||||||
"outputOnFailure": true
|
"outputOnFailure": true
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
PROJECT_VERSION_MAJOR=1
|
PROJECT_VERSION_MAJOR=1
|
||||||
PROJECT_VERSION_MINOR=0
|
PROJECT_VERSION_MINOR=0
|
||||||
PROJECT_VERSION_PATCH=3
|
PROJECT_VERSION_PATCH=4
|
||||||
# LICENSE
|
# LICENSE
|
||||||
LICENSE=AGPL-3.0
|
LICENSE=AGPL-3.0
|
||||||
# The network version.
|
# The network version.
|
||||||
@ -8,7 +8,7 @@ LICENSE=AGPL-3.0
|
|||||||
# 171022 - Unmodded client
|
# 171022 - Unmodded client
|
||||||
NET_VERSION=171022
|
NET_VERSION=171022
|
||||||
# Debugging
|
# Debugging
|
||||||
# __dynamic=1
|
__dynamic=1
|
||||||
# Set __dynamic to 1 to enable the -rdynamic flag for the linker, yielding some symbols in crashlogs.
|
# Set __dynamic to 1 to enable the -rdynamic flag for the linker, yielding some symbols in crashlogs.
|
||||||
# __ggdb=1
|
# __ggdb=1
|
||||||
# Set __ggdb to 1 to enable the -ggdb flag for the linker, including more debug info.
|
# Set __ggdb to 1 to enable the -ggdb flag for the linker, including more debug info.
|
||||||
|
@ -123,6 +123,15 @@ added, which produced InvalidScript errors.
|
|||||||
|
|
||||||
Check out a compiled list of development resources and tools [here](https://lu-dev.net/).
|
Check out a compiled list of development resources and tools [here](https://lu-dev.net/).
|
||||||
|
|
||||||
|
|
||||||
|
Please use [.editorconfig](https://editorconfig.org/#pre-installed) with your preferred IDE.
|
||||||
|
|
||||||
|
And run:
|
||||||
|
```bash
|
||||||
|
git config blame.ignoreRevsFile .git-blame-ignore-revs
|
||||||
|
```
|
||||||
|
to ignore the gitblame of mass formatting commits
|
||||||
|
|
||||||
## Coding Style
|
## Coding Style
|
||||||
|
|
||||||
This project has gone through multiple iterations of coding style. In the code you'll find a number of different coding styles in use. What follows is the preferred style for this project.
|
This project has gone through multiple iterations of coding style. In the code you'll find a number of different coding styles in use. What follows is the preferred style for this project.
|
||||||
|
@ -25,8 +25,7 @@
|
|||||||
|
|
||||||
**NOTE #4**: Make sure to run the following in the repo root directory after cloning so submodules are also downloaded.
|
**NOTE #4**: Make sure to run the following in the repo root directory after cloning so submodules are also downloaded.
|
||||||
```
|
```
|
||||||
git submodule init
|
git submodule update --init --recursive
|
||||||
git submodule update
|
|
||||||
```
|
```
|
||||||
**NOTE #5**: If DarkflameSetup fails due to not having cdclient.fdb, rename CDClient.fdb (in the same folder) to cdclient.fdb
|
**NOTE #5**: If DarkflameSetup fails due to not having cdclient.fdb, rename CDClient.fdb (in the same folder) to cdclient.fdb
|
||||||
|
|
||||||
|
61
README.md
61
README.md
@ -27,11 +27,11 @@ Darkflame Universe is a server emulator and does not distribute any LEGO® Unive
|
|||||||
Development of the latest iteration of Darkflame Universe has been done primarily in a Unix-like environment and is where it has been tested and designed for deployment. It is therefore highly recommended that Darkflame Universe be built and deployed using a Unix-like environment for the most streamlined experience.
|
Development of the latest iteration of Darkflame Universe has been done primarily in a Unix-like environment and is where it has been tested and designed for deployment. It is therefore highly recommended that Darkflame Universe be built and deployed using a Unix-like environment for the most streamlined experience.
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
**Clone the repository**
|
#### Clone the repository
|
||||||
```bash
|
```bash
|
||||||
git clone --recursive https://github.com/DarkflameUniverse/DarkflameServer
|
git clone --recursive https://github.com/DarkflameUniverse/DarkflameServer
|
||||||
```
|
```
|
||||||
**Python**
|
#### Python
|
||||||
|
|
||||||
Some tools utilized to streamline the setup process require Python 3, make sure you have it installed.
|
Some tools utilized to streamline the setup process require Python 3, make sure you have it installed.
|
||||||
|
|
||||||
@ -42,12 +42,17 @@ This was done make sure that older and incomplete clients wouldn't produce false
|
|||||||
|
|
||||||
If you're using a DLU client you'll have to go into the "CMakeVariables.txt" file and change the NET_VERSION variable to 171023 to match the modified client's version number.
|
If you're using a DLU client you'll have to go into the "CMakeVariables.txt" file and change the NET_VERSION variable to 171023 to match the modified client's version number.
|
||||||
|
|
||||||
|
### Using Docker
|
||||||
|
Refer to [Docker.md](/Docker.md).
|
||||||
|
|
||||||
|
For Windows, refer to [Docker_Windows.md](/Docker_Windows.md).
|
||||||
|
|
||||||
### Linux builds
|
### Linux builds
|
||||||
Make sure packages like `gcc`, `cmake`, and `zlib` are installed. Depending on the distribution, these packages might already be installed. Note that on systems like Ubuntu, you will need the `zlib1g-dev` package so that the header files are available. `libssl-dev` will also be required as well as `openssl`.
|
Make sure packages like `gcc`, `cmake`, and `zlib` are installed. Depending on the distribution, these packages might already be installed. Note that on systems like Ubuntu, you will need the `zlib1g-dev` package so that the header files are available. `libssl-dev` will also be required as well as `openssl`.
|
||||||
|
|
||||||
CMake must be version 3.14 or higher!
|
CMake must be version 3.14 or higher!
|
||||||
|
|
||||||
**Build the repository**
|
#### Build the repository
|
||||||
|
|
||||||
You can either run `build.sh` when in the root folder of the repository:
|
You can either run `build.sh` when in the root folder of the repository:
|
||||||
|
|
||||||
@ -65,8 +70,8 @@ cd build
|
|||||||
# Run CMake to generate make files
|
# Run CMake to generate make files
|
||||||
cmake ..
|
cmake ..
|
||||||
|
|
||||||
# Run make to build the project. To build utilizing multiple cores, append `-j` and the amount of cores to utilize, for example `make -j8`
|
# To build utilizing multiple cores, append `-j` and the amount of cores to utilize, for example `cmake --build . --config Release -j8'
|
||||||
make
|
cmake --build . --config Release
|
||||||
```
|
```
|
||||||
|
|
||||||
### MacOS builds
|
### MacOS builds
|
||||||
@ -88,7 +93,7 @@ cmake --build . --config Release
|
|||||||
### Windows builds (native)
|
### Windows builds (native)
|
||||||
Ensure that you have either the [MSVC](https://visualstudio.microsoft.com/vs/) or the [Clang](https://github.com/llvm/llvm-project/releases/) (recommended) compiler installed. You will also need to install [CMake](https://cmake.org/download/). Currently on native Windows the server will only work in Release mode.
|
Ensure that you have either the [MSVC](https://visualstudio.microsoft.com/vs/) or the [Clang](https://github.com/llvm/llvm-project/releases/) (recommended) compiler installed. You will also need to install [CMake](https://cmake.org/download/). Currently on native Windows the server will only work in Release mode.
|
||||||
|
|
||||||
**Build the repository**
|
#### Build the repository
|
||||||
```batch
|
```batch
|
||||||
:: Create the build directory
|
:: Create the build directory
|
||||||
mkdir build
|
mkdir build
|
||||||
@ -100,7 +105,7 @@ cmake ..
|
|||||||
:: Run CMake with build flag to build
|
:: Run CMake with build flag to build
|
||||||
cmake --build . --config Release
|
cmake --build . --config Release
|
||||||
```
|
```
|
||||||
**Windows for ARM** has not been tested but should build by doing the following
|
#### Windows for ARM has not been tested but should build by doing the following
|
||||||
```batch
|
```batch
|
||||||
:: Create the build directory
|
:: Create the build directory
|
||||||
mkdir build
|
mkdir build
|
||||||
@ -116,13 +121,13 @@ cmake --build . --config Release
|
|||||||
### Windows builds (WSL)
|
### Windows builds (WSL)
|
||||||
This section will go through how to install [WSL](https://docs.microsoft.com/en-us/windows/wsl/install) and building in a Linux environment under Windows. WSL requires Windows 10 version 2004 and higher (Build 19041 and higher) or Windows 11.
|
This section will go through how to install [WSL](https://docs.microsoft.com/en-us/windows/wsl/install) and building in a Linux environment under Windows. WSL requires Windows 10 version 2004 and higher (Build 19041 and higher) or Windows 11.
|
||||||
|
|
||||||
**Open the Command Prompt application with Administrator permissions and run the following:**
|
#### Open the Command Prompt application with Administrator permissions and run the following:
|
||||||
```bash
|
```bash
|
||||||
# Installing Windows Subsystem for Linux
|
# Installing Windows Subsystem for Linux
|
||||||
wsl --install
|
wsl --install
|
||||||
```
|
```
|
||||||
|
|
||||||
**Open the Ubuntu application and run the following:**
|
#### Open the Ubuntu application and run the following:
|
||||||
```bash
|
```bash
|
||||||
# Make sure the install is up to date
|
# Make sure the install is up to date
|
||||||
apt update && apt upgrade
|
apt update && apt upgrade
|
||||||
@ -154,7 +159,7 @@ now follow the build section for your system
|
|||||||
|
|
||||||
### Resources
|
### Resources
|
||||||
|
|
||||||
**LEGO® Universe 1.10.64**
|
#### LEGO® Universe 1.10.64
|
||||||
|
|
||||||
This repository does not distribute any LEGO® Universe files. A full install of LEGO® Universe version 1.10.64 (latest) is required to finish setting up Darkflame Universe.
|
This repository does not distribute any LEGO® Universe files. A full install of LEGO® Universe version 1.10.64 (latest) is required to finish setting up Darkflame Universe.
|
||||||
|
|
||||||
@ -177,20 +182,20 @@ shasum -a 256 <file>
|
|||||||
certutil -hashfile <file> SHA256
|
certutil -hashfile <file> SHA256
|
||||||
```
|
```
|
||||||
|
|
||||||
**Unpacking the client**
|
#### Unpacking the client
|
||||||
* Clone lcdr's utilities repository [here](https://github.com/lcdr/utils)
|
* Clone lcdr's utilities repository [here](https://github.com/lcdr/utils)
|
||||||
* Use `pkextractor.pyw` to unpack the client files if they are not already unpacked
|
* Use `pkextractor.pyw` to unpack the client files if they are not already unpacked
|
||||||
|
|
||||||
**Setup resource directory**
|
#### Setup resource directory
|
||||||
* In the `build` directory create a `res` directory if it does not already exist.
|
* In the `build` directory create a `res` directory if it does not already exist.
|
||||||
* Copy over or create symlinks from `macros`, `BrickModels`, `chatplus_en_us.txt`, `names`, and `maps` in your client `res` directory to the server `build/res` directory
|
* Copy over or create symlinks from `macros`, `BrickModels`, `chatplus_en_us.txt`, `names`, and `maps` in your client `res` directory to the server `build/res` directory
|
||||||
* Unzip the navmeshes [here](./resources/navmeshes.zip) and place them in `build/res/maps/navmeshes`
|
* Unzip the navmeshes [here](./resources/navmeshes.zip) and place them in `build/res/maps/navmeshes`
|
||||||
|
|
||||||
**Setup locale**
|
#### Setup locale
|
||||||
* In the `build` directory create a `locale` directory if it does not already exist
|
* In the `build` directory create a `locale` directory if it does not already exist
|
||||||
* Copy over or create symlinks from `locale.xml` in your client `locale` directory to the `build/locale` directory
|
* Copy over or create symlinks from `locale.xml` in your client `locale` directory to the `build/locale` directory
|
||||||
|
|
||||||
**Client database**
|
#### Client database
|
||||||
* Use `fdb_to_sqlite.py` in lcdr's utilities on `res/cdclient.fdb` in the unpacked client to convert the client database to `cdclient.sqlite`
|
* Use `fdb_to_sqlite.py` in lcdr's utilities on `res/cdclient.fdb` in the unpacked client to convert the client database to `cdclient.sqlite`
|
||||||
* Move and rename `cdclient.sqlite` into `build/res/CDServer.sqlite`
|
* Move and rename `cdclient.sqlite` into `build/res/CDServer.sqlite`
|
||||||
* Run each SQL file in the order at which they appear [here](migrations/cdserver/) on the SQLite database
|
* Run each SQL file in the order at which they appear [here](migrations/cdserver/) on the SQLite database
|
||||||
@ -199,14 +204,18 @@ certutil -hashfile <file> SHA256
|
|||||||
Darkflame Universe utilizes a MySQL/MariaDB database for account and character information.
|
Darkflame Universe utilizes a MySQL/MariaDB database for account and character information.
|
||||||
|
|
||||||
Initial setup can vary drastically based on which operating system or distribution you are running; there are instructions out there for most setups, follow those and come back here when you have a database up and running.
|
Initial setup can vary drastically based on which operating system or distribution you are running; there are instructions out there for most setups, follow those and come back here when you have a database up and running.
|
||||||
* Create a database for Darkflame Universe to use
|
|
||||||
* Use the command `./MasterServer -m` to automatically run them.
|
|
||||||
|
|
||||||
**Configuration**
|
* All that you need to do is create a database to connect to. As long as the server can connect to the database, the schema will always be kept up to date when you start the server.
|
||||||
|
|
||||||
|
#### Configuration
|
||||||
|
|
||||||
After the server has been built there should be four `ini` files in the build director: `authconfig.ini`, `chatconfig.ini`, `masterconfig.ini`, and `worldconfig.ini`. Go through them and fill in the database credentials and configure other settings if necessary.
|
After the server has been built there should be four `ini` files in the build director: `authconfig.ini`, `chatconfig.ini`, `masterconfig.ini`, and `worldconfig.ini`. Go through them and fill in the database credentials and configure other settings if necessary.
|
||||||
|
|
||||||
**Verify**
|
#### Migrations
|
||||||
|
|
||||||
|
The database is automatically setup and migrated to what it should look like for the latest commit whenever you start the server.
|
||||||
|
|
||||||
|
#### Verify
|
||||||
|
|
||||||
Your build directory should now look like this:
|
Your build directory should now look like this:
|
||||||
* AuthServer
|
* AuthServer
|
||||||
@ -417,10 +426,11 @@ Here is a summary of the commands available in-game. All commands are prefixed b
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
## Credits
|
# Credits
|
||||||
## Active Contributors
|
## Active Contributors
|
||||||
* [EmosewaMC](https://github.com/EmosewaMC)
|
* [EmosewaMC](https://github.com/EmosewaMC)
|
||||||
* [Jettford](https://github.com/Jettford)
|
* [Jettford](https://github.com/Jettford)
|
||||||
|
* [Aaron K.](https://github.com/aronwk-aaron)
|
||||||
|
|
||||||
## DLU Team
|
## DLU Team
|
||||||
* [DarwinAnim8or](https://github.com/DarwinAnim8or)
|
* [DarwinAnim8or](https://github.com/DarwinAnim8or)
|
||||||
@ -429,10 +439,6 @@ Here is a summary of the commands available in-game. All commands are prefixed b
|
|||||||
* [averysumner](https://github.com/codeshaunted)
|
* [averysumner](https://github.com/codeshaunted)
|
||||||
* [Jon002](https://github.com/jaller200)
|
* [Jon002](https://github.com/jaller200)
|
||||||
* [Jonny](https://github.com/cuzitsjonny)
|
* [Jonny](https://github.com/cuzitsjonny)
|
||||||
* TheMachine
|
|
||||||
* Matthew
|
|
||||||
* [Raine](https://github.com/Rainebannister)
|
|
||||||
* Bricknave
|
|
||||||
|
|
||||||
### Research and tools
|
### Research and tools
|
||||||
* [lcdr](https://github.com/lcdr)
|
* [lcdr](https://github.com/lcdr)
|
||||||
@ -444,11 +450,14 @@ Here is a summary of the commands available in-game. All commands are prefixed b
|
|||||||
### Former contributors
|
### Former contributors
|
||||||
* TheMachine
|
* TheMachine
|
||||||
* Matthew
|
* Matthew
|
||||||
* Raine
|
* [Raine](https://github.com/Rainebannister)
|
||||||
* Bricknave
|
* Bricknave
|
||||||
|
|
||||||
### Special thanks
|
### Logo
|
||||||
|
* Cole Peterson (BlasterBuilder)
|
||||||
|
|
||||||
|
## Special thanks
|
||||||
* humanoid24
|
* humanoid24
|
||||||
* pwjones1969
|
* pwjones1969
|
||||||
* BlasterBuilder for the logo
|
* [Simon](https://github.com/SimonNitzsche)
|
||||||
* ALL OF THE NETDEVIL AND LEGO TEAMS!
|
* ALL OF THE NETDEVIL AND LEGO TEAMS!
|
||||||
|
51
SECURITY.md
Normal file
51
SECURITY.md
Normal 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
|
5
build.sh
5
build.sh
@ -5,5 +5,6 @@ cd build
|
|||||||
# Run cmake to generate make files
|
# Run cmake to generate make files
|
||||||
cmake ..
|
cmake ..
|
||||||
|
|
||||||
# Run make to build the project. To build utilizing multiple cores, append `-j` and the amount of cores to utilize, for example `make -j8`
|
# To build utilizing multiple cores, append `-j` and the amount of cores to utilize, for example `cmake --build . --config Release -j8'
|
||||||
make
|
cmake --build . --config Release
|
||||||
|
|
||||||
|
@ -37,9 +37,9 @@ int main(int argc, char** argv) {
|
|||||||
//Create all the objects we need to run our service:
|
//Create all the objects we need to run our service:
|
||||||
Game::logger = SetupLogger();
|
Game::logger = SetupLogger();
|
||||||
if (!Game::logger) return 0;
|
if (!Game::logger) return 0;
|
||||||
Game::logger->Log("AuthServer", "Starting Auth server...\n");
|
Game::logger->Log("AuthServer", "Starting Auth server...");
|
||||||
Game::logger->Log("AuthServer", "Version: %i.%i\n", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
|
Game::logger->Log("AuthServer", "Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
|
||||||
Game::logger->Log("AuthServer", "Compiled on: %s\n", __TIMESTAMP__);
|
Game::logger->Log("AuthServer", "Compiled on: %s", __TIMESTAMP__);
|
||||||
|
|
||||||
//Read our config:
|
//Read our config:
|
||||||
dConfig config("authconfig.ini");
|
dConfig config("authconfig.ini");
|
||||||
@ -56,7 +56,7 @@ int main(int argc, char** argv) {
|
|||||||
try {
|
try {
|
||||||
Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password);
|
Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password);
|
||||||
} catch (sql::SQLException& ex) {
|
} catch (sql::SQLException& ex) {
|
||||||
Game::logger->Log("AuthServer", "Got an error while connecting to the database: %s\n", ex.what());
|
Game::logger->Log("AuthServer", "Got an error while connecting to the database: %s", ex.what());
|
||||||
Database::Destroy("AuthServer");
|
Database::Destroy("AuthServer");
|
||||||
delete Game::server;
|
delete Game::server;
|
||||||
delete Game::logger;
|
delete Game::logger;
|
||||||
@ -98,8 +98,7 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
if (framesSinceMasterDisconnect >= 30)
|
if (framesSinceMasterDisconnect >= 30)
|
||||||
break; //Exit our loop, shut down.
|
break; //Exit our loop, shut down.
|
||||||
}
|
} else framesSinceMasterDisconnect = 0;
|
||||||
else framesSinceMasterDisconnect = 0;
|
|
||||||
|
|
||||||
//In world we'd update our other systems here.
|
//In world we'd update our other systems here.
|
||||||
|
|
||||||
@ -134,8 +133,7 @@ int main(int argc, char** argv) {
|
|||||||
delete stmt;
|
delete stmt;
|
||||||
|
|
||||||
framesSinceLastSQLPing = 0;
|
framesSinceLastSQLPing = 0;
|
||||||
}
|
} else framesSinceLastSQLPing++;
|
||||||
else framesSinceLastSQLPing++;
|
|
||||||
|
|
||||||
//Sleep our thread since auth can afford to.
|
//Sleep our thread since auth can afford to.
|
||||||
t += std::chrono::milliseconds(mediumFramerate); //Auth can run at a lower "fps"
|
t += std::chrono::milliseconds(mediumFramerate); //Auth can run at a lower "fps"
|
||||||
@ -151,7 +149,7 @@ int main(int argc, char** argv) {
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
dLogger * SetupLogger() {
|
dLogger* SetupLogger() {
|
||||||
std::string logPath = "./logs/AuthServer_" + std::to_string(time(nullptr)) + ".log";
|
std::string logPath = "./logs/AuthServer_" + std::to_string(time(nullptr)) + ".log";
|
||||||
bool logToConsole = false;
|
bool logToConsole = false;
|
||||||
bool logDebugStatements = false;
|
bool logDebugStatements = false;
|
||||||
|
@ -8,8 +8,9 @@
|
|||||||
#include <regex>
|
#include <regex>
|
||||||
|
|
||||||
#include "dCommonVars.h"
|
#include "dCommonVars.h"
|
||||||
#include "Database.h"
|
|
||||||
#include "dLogger.h"
|
#include "dLogger.h"
|
||||||
|
#include "dConfig.h"
|
||||||
|
#include "Database.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
|
|
||||||
using namespace dChatFilterDCF;
|
using namespace dChatFilterDCF;
|
||||||
@ -18,12 +19,15 @@ dChatFilter::dChatFilter(const std::string& filepath, bool dontGenerateDCF) {
|
|||||||
m_DontGenerateDCF = dontGenerateDCF;
|
m_DontGenerateDCF = dontGenerateDCF;
|
||||||
|
|
||||||
if (!BinaryIO::DoesFileExist(filepath + ".dcf") || m_DontGenerateDCF) {
|
if (!BinaryIO::DoesFileExist(filepath + ".dcf") || m_DontGenerateDCF) {
|
||||||
ReadWordlistPlaintext(filepath + ".txt");
|
ReadWordlistPlaintext(filepath + ".txt", true);
|
||||||
if (!m_DontGenerateDCF) ExportWordlistToDCF(filepath + ".dcf");
|
if (!m_DontGenerateDCF) ExportWordlistToDCF(filepath + ".dcf", true);
|
||||||
|
} else if (!ReadWordlistDCF(filepath + ".dcf", true)) {
|
||||||
|
ReadWordlistPlaintext(filepath + ".txt", true);
|
||||||
|
ExportWordlistToDCF(filepath + ".dcf", true);
|
||||||
}
|
}
|
||||||
else if (!ReadWordlistDCF(filepath + ".dcf")) {
|
|
||||||
ReadWordlistPlaintext(filepath + ".txt");
|
if (BinaryIO::DoesFileExist("blacklist.dcf")) {
|
||||||
ExportWordlistToDCF(filepath + ".dcf");
|
ReadWordlistDCF("blacklist.dcf", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Read player names that are ok as well:
|
//Read player names that are ok as well:
|
||||||
@ -32,29 +36,31 @@ dChatFilter::dChatFilter(const std::string& filepath, bool dontGenerateDCF) {
|
|||||||
while (res->next()) {
|
while (res->next()) {
|
||||||
std::string line = res->getString(1).c_str();
|
std::string line = res->getString(1).c_str();
|
||||||
std::transform(line.begin(), line.end(), line.begin(), ::tolower); //Transform to lowercase
|
std::transform(line.begin(), line.end(), line.begin(), ::tolower); //Transform to lowercase
|
||||||
m_Words.push_back(CalculateHash(line));
|
m_ApprovedWords.push_back(CalculateHash(line));
|
||||||
}
|
}
|
||||||
delete res;
|
delete res;
|
||||||
delete stmt;
|
delete stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
dChatFilter::~dChatFilter() {
|
dChatFilter::~dChatFilter() {
|
||||||
m_Words.clear();
|
m_ApprovedWords.clear();
|
||||||
|
m_DeniedWords.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void dChatFilter::ReadWordlistPlaintext(const std::string& filepath) {
|
void dChatFilter::ReadWordlistPlaintext(const std::string& filepath, bool whiteList) {
|
||||||
std::ifstream file(filepath);
|
std::ifstream file(filepath);
|
||||||
if (file) {
|
if (file) {
|
||||||
std::string line;
|
std::string line;
|
||||||
while (std::getline(file, line)) {
|
while (std::getline(file, line)) {
|
||||||
line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
|
line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
|
||||||
std::transform(line.begin(), line.end(), line.begin(), ::tolower); //Transform to lowercase
|
std::transform(line.begin(), line.end(), line.begin(), ::tolower); //Transform to lowercase
|
||||||
m_Words.push_back(CalculateHash(line));
|
if (whiteList) m_ApprovedWords.push_back(CalculateHash(line));
|
||||||
|
else m_DeniedWords.push_back(CalculateHash(line));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dChatFilter::ReadWordlistDCF(const std::string& filepath) {
|
bool dChatFilter::ReadWordlistDCF(const std::string& filepath, bool whiteList) {
|
||||||
std::ifstream file(filepath, std::ios::binary);
|
std::ifstream file(filepath, std::ios::binary);
|
||||||
if (file) {
|
if (file) {
|
||||||
fileHeader hdr;
|
fileHeader hdr;
|
||||||
@ -67,17 +73,18 @@ bool dChatFilter::ReadWordlistDCF(const std::string& filepath) {
|
|||||||
if (hdr.formatVersion == formatVersion) {
|
if (hdr.formatVersion == formatVersion) {
|
||||||
size_t wordsToRead = 0;
|
size_t wordsToRead = 0;
|
||||||
BinaryIO::BinaryRead(file, wordsToRead);
|
BinaryIO::BinaryRead(file, wordsToRead);
|
||||||
m_Words.reserve(wordsToRead);
|
if (whiteList) m_ApprovedWords.reserve(wordsToRead);
|
||||||
|
else m_DeniedWords.reserve(wordsToRead);
|
||||||
|
|
||||||
size_t word = 0;
|
size_t word = 0;
|
||||||
for (size_t i = 0; i < wordsToRead; ++i) {
|
for (size_t i = 0; i < wordsToRead; ++i) {
|
||||||
BinaryIO::BinaryRead(file, word);
|
BinaryIO::BinaryRead(file, word);
|
||||||
m_Words.push_back(word);
|
if (whiteList) m_ApprovedWords.push_back(word);
|
||||||
|
else m_DeniedWords.push_back(word);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
file.close();
|
file.close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -86,14 +93,14 @@ bool dChatFilter::ReadWordlistDCF(const std::string& filepath) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dChatFilter::ExportWordlistToDCF(const std::string& filepath) {
|
void dChatFilter::ExportWordlistToDCF(const std::string& filepath, bool whiteList) {
|
||||||
std::ofstream file(filepath, std::ios::binary | std::ios_base::out);
|
std::ofstream file(filepath, std::ios::binary | std::ios_base::out);
|
||||||
if (file) {
|
if (file) {
|
||||||
BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::header));
|
BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::header));
|
||||||
BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::formatVersion));
|
BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::formatVersion));
|
||||||
BinaryIO::BinaryWrite(file, size_t(m_Words.size()));
|
BinaryIO::BinaryWrite(file, size_t(whiteList ? m_ApprovedWords.size() : m_DeniedWords.size()));
|
||||||
|
|
||||||
for (size_t word : m_Words) {
|
for (size_t word : whiteList ? m_ApprovedWords : m_DeniedWords) {
|
||||||
BinaryIO::BinaryWrite(file, word);
|
BinaryIO::BinaryWrite(file, word);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,31 +108,45 @@ void dChatFilter::ExportWordlistToDCF(const std::string& filepath) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dChatFilter::IsSentenceOkay(const std::string& message, int gmLevel) {
|
std::vector<std::pair<uint8_t, uint8_t>> dChatFilter::IsSentenceOkay(const std::string& message, int gmLevel, bool whiteList) {
|
||||||
if (gmLevel > GAME_MASTER_LEVEL_FORUM_MODERATOR) return true; //If anything but a forum mod, return true.
|
if (gmLevel > GAME_MASTER_LEVEL_FORUM_MODERATOR) return { }; //If anything but a forum mod, return true.
|
||||||
if (message.empty()) return true;
|
if (message.empty()) return { };
|
||||||
|
if (!whiteList && m_DeniedWords.empty()) return { { 0, message.length() } };
|
||||||
|
|
||||||
std::stringstream sMessage(message);
|
std::stringstream sMessage(message);
|
||||||
std::string segment;
|
std::string segment;
|
||||||
std::regex reg("(!*|\\?*|\\;*|\\.*|\\,*)");
|
std::regex reg("(!*|\\?*|\\;*|\\.*|\\,*)");
|
||||||
|
|
||||||
|
std::vector<std::pair<uint8_t, uint8_t>> listOfBadSegments = std::vector<std::pair<uint8_t, uint8_t>>();
|
||||||
|
|
||||||
|
uint32_t position = 0;
|
||||||
|
|
||||||
while (std::getline(sMessage, segment, ' ')) {
|
while (std::getline(sMessage, segment, ' ')) {
|
||||||
|
std::string originalSegment = segment;
|
||||||
|
|
||||||
std::transform(segment.begin(), segment.end(), segment.begin(), ::tolower); //Transform to lowercase
|
std::transform(segment.begin(), segment.end(), segment.begin(), ::tolower); //Transform to lowercase
|
||||||
segment = std::regex_replace(segment, reg, "");
|
segment = std::regex_replace(segment, reg, "");
|
||||||
|
|
||||||
size_t hash = CalculateHash(segment);
|
size_t hash = CalculateHash(segment);
|
||||||
|
|
||||||
if (std::find(m_UserUnapprovedWordCache.begin(), m_UserUnapprovedWordCache.end(), hash) != m_UserUnapprovedWordCache.end()) {
|
if (std::find(m_UserUnapprovedWordCache.begin(), m_UserUnapprovedWordCache.end(), hash) != m_UserUnapprovedWordCache.end() && whiteList) {
|
||||||
return false;
|
listOfBadSegments.emplace_back(position, originalSegment.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsInWordlist(hash)) {
|
if (std::find(m_ApprovedWords.begin(), m_ApprovedWords.end(), hash) == m_ApprovedWords.end() && whiteList) {
|
||||||
m_UserUnapprovedWordCache.push_back(hash);
|
m_UserUnapprovedWordCache.push_back(hash);
|
||||||
return false;
|
listOfBadSegments.emplace_back(position, originalSegment.length());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
if (std::find(m_DeniedWords.begin(), m_DeniedWords.end(), hash) != m_DeniedWords.end() && !whiteList) {
|
||||||
|
m_UserUnapprovedWordCache.push_back(hash);
|
||||||
|
listOfBadSegments.emplace_back(position, originalSegment.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
position += segment.length() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return listOfBadSegments;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t dChatFilter::CalculateHash(const std::string& word) {
|
size_t dChatFilter::CalculateHash(const std::string& word) {
|
||||||
@ -135,7 +156,3 @@ size_t dChatFilter::CalculateHash(const std::string& word) {
|
|||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dChatFilter::IsInWordlist(size_t word) {
|
|
||||||
return std::find(m_Words.begin(), m_Words.end(), word) != m_Words.end();
|
|
||||||
}
|
|
||||||
|
@ -20,17 +20,17 @@ public:
|
|||||||
dChatFilter(const std::string& filepath, bool dontGenerateDCF);
|
dChatFilter(const std::string& filepath, bool dontGenerateDCF);
|
||||||
~dChatFilter();
|
~dChatFilter();
|
||||||
|
|
||||||
void ReadWordlistPlaintext(const std::string & filepath);
|
void ReadWordlistPlaintext(const std::string& filepath, bool whiteList);
|
||||||
bool ReadWordlistDCF(const std::string & filepath);
|
bool ReadWordlistDCF(const std::string& filepath, bool whiteList);
|
||||||
void ExportWordlistToDCF(const std::string & filepath);
|
void ExportWordlistToDCF(const std::string& filepath, bool whiteList);
|
||||||
bool IsSentenceOkay(const std::string& message, int gmLevel);
|
std::vector<std::pair<uint8_t, uint8_t>> IsSentenceOkay(const std::string& message, int gmLevel, bool whiteList = true);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_DontGenerateDCF;
|
bool m_DontGenerateDCF;
|
||||||
std::vector<size_t> m_Words;
|
std::vector<size_t> m_DeniedWords;
|
||||||
|
std::vector<size_t> m_ApprovedWords;
|
||||||
std::vector<size_t> m_UserUnapprovedWordCache;
|
std::vector<size_t> m_UserUnapprovedWordCache;
|
||||||
|
|
||||||
//Private functions:
|
//Private functions:
|
||||||
size_t CalculateHash(const std::string& word);
|
size_t CalculateHash(const std::string& word);
|
||||||
bool IsInWordlist(size_t word);
|
|
||||||
};
|
};
|
||||||
|
@ -33,9 +33,10 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
|||||||
"WHEN friend_id = ? THEN player_id "
|
"WHEN friend_id = ? THEN player_id "
|
||||||
"END AS requested_player, best_friend FROM friends) AS fr "
|
"END AS requested_player, best_friend FROM friends) AS fr "
|
||||||
"JOIN charinfo AS ci ON ci.id = fr.requested_player "
|
"JOIN charinfo AS ci ON ci.id = fr.requested_player "
|
||||||
"WHERE fr.requested_player IS NOT NULL;"));
|
"WHERE fr.requested_player IS NOT NULL AND fr.requested_player != ?;"));
|
||||||
stmt->setUInt(1, static_cast<uint32_t>(playerID));
|
stmt->setUInt(1, static_cast<uint32_t>(playerID));
|
||||||
stmt->setUInt(2, static_cast<uint32_t>(playerID));
|
stmt->setUInt(2, static_cast<uint32_t>(playerID));
|
||||||
|
stmt->setUInt(3, static_cast<uint32_t>(playerID));
|
||||||
|
|
||||||
std::vector<FriendData> friends;
|
std::vector<FriendData> friends;
|
||||||
|
|
||||||
@ -48,7 +49,7 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
|||||||
GeneralUtils::SetBit(fd.friendID, static_cast<size_t>(eObjectBits::OBJECT_BIT_CHARACTER));
|
GeneralUtils::SetBit(fd.friendID, static_cast<size_t>(eObjectBits::OBJECT_BIT_CHARACTER));
|
||||||
|
|
||||||
fd.isBestFriend = res->getInt(2) == 3; //0 = friends, 1 = left_requested, 2 = right_requested, 3 = both_accepted - are now bffs
|
fd.isBestFriend = res->getInt(2) == 3; //0 = friends, 1 = left_requested, 2 = right_requested, 3 = both_accepted - are now bffs
|
||||||
if (fd.isBestFriend) player->countOfBestFriends+=1;
|
if (fd.isBestFriend) player->countOfBestFriends += 1;
|
||||||
fd.friendName = res->getString(3);
|
fd.friendName = res->getString(3);
|
||||||
|
|
||||||
//Now check if they're online:
|
//Now check if they're online:
|
||||||
@ -60,8 +61,7 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
|||||||
|
|
||||||
//Since this friend is online, we need to update them on the fact that we've just logged in:
|
//Since this friend is online, we need to update them on the fact that we've just logged in:
|
||||||
SendFriendUpdate(fr, player, 1, fd.isBestFriend);
|
SendFriendUpdate(fr, player, 1, fd.isBestFriend);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
fd.isOnline = false;
|
fd.isOnline = false;
|
||||||
fd.zoneID = LWOZONEID();
|
fd.zoneID = LWOZONEID();
|
||||||
}
|
}
|
||||||
@ -114,6 +114,10 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
|||||||
inStream.Read(isBestFriendRequest);
|
inStream.Read(isBestFriendRequest);
|
||||||
|
|
||||||
auto requestor = playerContainer.GetPlayerData(requestorPlayerID);
|
auto requestor = playerContainer.GetPlayerData(requestorPlayerID);
|
||||||
|
if (requestor->playerName == playerName) {
|
||||||
|
SendFriendResponse(requestor, requestor, AddFriendResponseType::MYTHRAN);
|
||||||
|
return;
|
||||||
|
};
|
||||||
std::unique_ptr<PlayerData> requestee(playerContainer.GetPlayerData(playerName));
|
std::unique_ptr<PlayerData> requestee(playerContainer.GetPlayerData(playerName));
|
||||||
|
|
||||||
// Check if player is online first
|
// Check if player is online first
|
||||||
@ -209,8 +213,8 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
|||||||
updateQuery->executeUpdate();
|
updateQuery->executeUpdate();
|
||||||
// Sent the best friend update here if the value is 3
|
// Sent the best friend update here if the value is 3
|
||||||
if (bestFriendStatus == 3U) {
|
if (bestFriendStatus == 3U) {
|
||||||
requestee->countOfBestFriends+=1;
|
requestee->countOfBestFriends += 1;
|
||||||
requestor->countOfBestFriends+=1;
|
requestor->countOfBestFriends += 1;
|
||||||
if (requestee->sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestee.get(), requestor, AddFriendResponseType::ACCEPTED, false, true);
|
if (requestee->sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestee.get(), requestor, AddFriendResponseType::ACCEPTED, false, true);
|
||||||
if (requestor->sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestor, requestee.get(), AddFriendResponseType::ACCEPTED, false, true);
|
if (requestor->sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestor, requestee.get(), AddFriendResponseType::ACCEPTED, false, true);
|
||||||
for (auto& friendData : requestor->friends) {
|
for (auto& friendData : requestor->friends) {
|
||||||
@ -371,8 +375,7 @@ void ChatPacketHandler::HandleRemoveFriend(Packet* packet) {
|
|||||||
SendRemoveFriend(goonB, goonAName, true);
|
SendRemoveFriend(goonB, goonAName, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleChatMessage(Packet* packet)
|
void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
||||||
{
|
|
||||||
CINSTREAM;
|
CINSTREAM;
|
||||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
@ -393,7 +396,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet)
|
|||||||
|
|
||||||
std::string message = PacketUtils::ReadString(0x66, packet, true);
|
std::string message = PacketUtils::ReadString(0x66, packet, true);
|
||||||
|
|
||||||
Game::logger->Log("ChatPacketHandler", "Got a message from (%s) [%d]: %s\n", senderName.c_str(), channel, message.c_str());
|
Game::logger->Log("ChatPacketHandler", "Got a message from (%s) [%d]: %s", senderName.c_str(), channel, message.c_str());
|
||||||
|
|
||||||
if (channel != 8) return;
|
if (channel != 8) return;
|
||||||
|
|
||||||
@ -401,8 +404,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet)
|
|||||||
|
|
||||||
if (team == nullptr) return;
|
if (team == nullptr) return;
|
||||||
|
|
||||||
for (const auto memberId : team->memberIDs)
|
for (const auto memberId : team->memberIDs) {
|
||||||
{
|
|
||||||
auto* otherMember = playerContainer.GetPlayerData(memberId);
|
auto* otherMember = playerContainer.GetPlayerData(memberId);
|
||||||
|
|
||||||
if (otherMember == nullptr) return;
|
if (otherMember == nullptr) return;
|
||||||
@ -493,8 +495,7 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleTeamInvite(Packet* packet)
|
void ChatPacketHandler::HandleTeamInvite(Packet* packet) {
|
||||||
{
|
|
||||||
CINSTREAM;
|
CINSTREAM;
|
||||||
LWOOBJID playerID;
|
LWOOBJID playerID;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
@ -503,44 +504,39 @@ void ChatPacketHandler::HandleTeamInvite(Packet* packet)
|
|||||||
|
|
||||||
auto* player = playerContainer.GetPlayerData(playerID);
|
auto* player = playerContainer.GetPlayerData(playerID);
|
||||||
|
|
||||||
if (player == nullptr)
|
if (player == nullptr) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* team = playerContainer.GetTeam(playerID);
|
auto* team = playerContainer.GetTeam(playerID);
|
||||||
|
|
||||||
if (team == nullptr)
|
if (team == nullptr) {
|
||||||
{
|
|
||||||
team = playerContainer.CreateTeam(playerID);
|
team = playerContainer.CreateTeam(playerID);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* other = playerContainer.GetPlayerData(invitedPlayer);
|
auto* other = playerContainer.GetPlayerData(invitedPlayer);
|
||||||
|
|
||||||
if (other == nullptr)
|
if (other == nullptr) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (playerContainer.GetTeam(other->playerID) != nullptr)
|
if (playerContainer.GetTeam(other->playerID) != nullptr) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (team->memberIDs.size() > 3) {
|
if (team->memberIDs.size() > 3) {
|
||||||
// no more teams greater than 4
|
// no more teams greater than 4
|
||||||
|
|
||||||
Game::logger->Log("ChatPacketHandler", "Someone tried to invite a 5th player to a team\n");
|
Game::logger->Log("ChatPacketHandler", "Someone tried to invite a 5th player to a team");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SendTeamInvite(other, player);
|
SendTeamInvite(other, player);
|
||||||
|
|
||||||
Game::logger->Log("ChatPacketHandler", "Got team invite: %llu -> %s\n", playerID, invitedPlayer.c_str());
|
Game::logger->Log("ChatPacketHandler", "Got team invite: %llu -> %s", playerID, invitedPlayer.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet)
|
void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet) {
|
||||||
{
|
|
||||||
CINSTREAM;
|
CINSTREAM;
|
||||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
@ -552,33 +548,29 @@ void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet)
|
|||||||
LWOOBJID leaderID = LWOOBJID_EMPTY;
|
LWOOBJID leaderID = LWOOBJID_EMPTY;
|
||||||
inStream.Read(leaderID);
|
inStream.Read(leaderID);
|
||||||
|
|
||||||
Game::logger->Log("ChatPacketHandler", "Accepted invite: %llu -> %llu (%d)\n", playerID, leaderID, declined);
|
Game::logger->Log("ChatPacketHandler", "Accepted invite: %llu -> %llu (%d)", playerID, leaderID, declined);
|
||||||
|
|
||||||
if (declined)
|
if (declined) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* team = playerContainer.GetTeam(leaderID);
|
auto* team = playerContainer.GetTeam(leaderID);
|
||||||
|
|
||||||
if (team == nullptr)
|
if (team == nullptr) {
|
||||||
{
|
Game::logger->Log("ChatPacketHandler", "Failed to find team for leader (%llu)", leaderID);
|
||||||
Game::logger->Log("ChatPacketHandler", "Failed to find team for leader (%llu)\n", leaderID);
|
|
||||||
|
|
||||||
team = playerContainer.GetTeam(playerID);
|
team = playerContainer.GetTeam(playerID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (team == nullptr)
|
if (team == nullptr) {
|
||||||
{
|
Game::logger->Log("ChatPacketHandler", "Failed to find team for player (%llu)", playerID);
|
||||||
Game::logger->Log("ChatPacketHandler", "Failed to find team for player (%llu)\n", playerID);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
playerContainer.AddMember(team, playerID);
|
playerContainer.AddMember(team, playerID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleTeamLeave(Packet* packet)
|
void ChatPacketHandler::HandleTeamLeave(Packet* packet) {
|
||||||
{
|
|
||||||
CINSTREAM;
|
CINSTREAM;
|
||||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
@ -588,16 +580,14 @@ void ChatPacketHandler::HandleTeamLeave(Packet* packet)
|
|||||||
|
|
||||||
auto* team = playerContainer.GetTeam(playerID);
|
auto* team = playerContainer.GetTeam(playerID);
|
||||||
|
|
||||||
Game::logger->Log("ChatPacketHandler", "(%llu) leaving team\n", playerID);
|
Game::logger->Log("ChatPacketHandler", "(%llu) leaving team", playerID);
|
||||||
|
|
||||||
if (team != nullptr)
|
if (team != nullptr) {
|
||||||
{
|
|
||||||
playerContainer.RemoveMember(team, playerID, false, false, true);
|
playerContainer.RemoveMember(team, playerID, false, false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleTeamKick(Packet* packet)
|
void ChatPacketHandler::HandleTeamKick(Packet* packet) {
|
||||||
{
|
|
||||||
CINSTREAM;
|
CINSTREAM;
|
||||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
@ -605,35 +595,30 @@ void ChatPacketHandler::HandleTeamKick(Packet* packet)
|
|||||||
|
|
||||||
std::string kickedPlayer = PacketUtils::ReadString(0x14, packet, true);
|
std::string kickedPlayer = PacketUtils::ReadString(0x14, packet, true);
|
||||||
|
|
||||||
Game::logger->Log("ChatPacketHandler", "(%llu) kicking (%s) from team\n", playerID, kickedPlayer.c_str());
|
Game::logger->Log("ChatPacketHandler", "(%llu) kicking (%s) from team", playerID, kickedPlayer.c_str());
|
||||||
|
|
||||||
auto* kicked = playerContainer.GetPlayerData(kickedPlayer);
|
auto* kicked = playerContainer.GetPlayerData(kickedPlayer);
|
||||||
|
|
||||||
LWOOBJID kickedId = LWOOBJID_EMPTY;
|
LWOOBJID kickedId = LWOOBJID_EMPTY;
|
||||||
|
|
||||||
if (kicked != nullptr)
|
if (kicked != nullptr) {
|
||||||
{
|
|
||||||
kickedId = kicked->playerID;
|
kickedId = kicked->playerID;
|
||||||
}
|
} else {
|
||||||
else
|
kickedId = playerContainer.GetId(GeneralUtils::UTF8ToUTF16(kickedPlayer));
|
||||||
{
|
|
||||||
kickedId = playerContainer.GetId(GeneralUtils::ASCIIToUTF16(kickedPlayer));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kickedId == LWOOBJID_EMPTY) return;
|
if (kickedId == LWOOBJID_EMPTY) return;
|
||||||
|
|
||||||
auto* team = playerContainer.GetTeam(playerID);
|
auto* team = playerContainer.GetTeam(playerID);
|
||||||
|
|
||||||
if (team != nullptr)
|
if (team != nullptr) {
|
||||||
{
|
|
||||||
if (team->leaderID != playerID || team->leaderID == kickedId) return;
|
if (team->leaderID != playerID || team->leaderID == kickedId) return;
|
||||||
|
|
||||||
playerContainer.RemoveMember(team, kickedId, false, true, false);
|
playerContainer.RemoveMember(team, kickedId, false, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleTeamPromote(Packet* packet)
|
void ChatPacketHandler::HandleTeamPromote(Packet* packet) {
|
||||||
{
|
|
||||||
CINSTREAM;
|
CINSTREAM;
|
||||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
@ -641,7 +626,7 @@ void ChatPacketHandler::HandleTeamPromote(Packet* packet)
|
|||||||
|
|
||||||
std::string promotedPlayer = PacketUtils::ReadString(0x14, packet, true);
|
std::string promotedPlayer = PacketUtils::ReadString(0x14, packet, true);
|
||||||
|
|
||||||
Game::logger->Log("ChatPacketHandler", "(%llu) promoting (%s) to team leader\n", playerID, promotedPlayer.c_str());
|
Game::logger->Log("ChatPacketHandler", "(%llu) promoting (%s) to team leader", playerID, promotedPlayer.c_str());
|
||||||
|
|
||||||
auto* promoted = playerContainer.GetPlayerData(promotedPlayer);
|
auto* promoted = playerContainer.GetPlayerData(promotedPlayer);
|
||||||
|
|
||||||
@ -649,16 +634,14 @@ void ChatPacketHandler::HandleTeamPromote(Packet* packet)
|
|||||||
|
|
||||||
auto* team = playerContainer.GetTeam(playerID);
|
auto* team = playerContainer.GetTeam(playerID);
|
||||||
|
|
||||||
if (team != nullptr)
|
if (team != nullptr) {
|
||||||
{
|
|
||||||
if (team->leaderID != playerID) return;
|
if (team->leaderID != playerID) return;
|
||||||
|
|
||||||
playerContainer.PromoteMember(team, promoted->playerID);
|
playerContainer.PromoteMember(team, promoted->playerID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleTeamLootOption(Packet* packet)
|
void ChatPacketHandler::HandleTeamLootOption(Packet* packet) {
|
||||||
{
|
|
||||||
CINSTREAM;
|
CINSTREAM;
|
||||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
@ -671,8 +654,7 @@ void ChatPacketHandler::HandleTeamLootOption(Packet* packet)
|
|||||||
|
|
||||||
auto* team = playerContainer.GetTeam(playerID);
|
auto* team = playerContainer.GetTeam(playerID);
|
||||||
|
|
||||||
if (team != nullptr)
|
if (team != nullptr) {
|
||||||
{
|
|
||||||
if (team->leaderID != playerID) return;
|
if (team->leaderID != playerID) return;
|
||||||
|
|
||||||
team->lootFlag = option;
|
team->lootFlag = option;
|
||||||
@ -683,8 +665,7 @@ void ChatPacketHandler::HandleTeamLootOption(Packet* packet)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet)
|
void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
|
||||||
{
|
|
||||||
CINSTREAM;
|
CINSTREAM;
|
||||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
@ -693,45 +674,37 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet)
|
|||||||
auto* team = playerContainer.GetTeam(playerID);
|
auto* team = playerContainer.GetTeam(playerID);
|
||||||
auto* data = playerContainer.GetPlayerData(playerID);
|
auto* data = playerContainer.GetPlayerData(playerID);
|
||||||
|
|
||||||
if (team != nullptr && data != nullptr)
|
if (team != nullptr && data != nullptr) {
|
||||||
{
|
if (team->local && data->zoneID.GetMapID() != team->zoneId.GetMapID() && data->zoneID.GetCloneID() != team->zoneId.GetCloneID()) {
|
||||||
if (team->local && data->zoneID.GetMapID() != team->zoneId.GetMapID() && data->zoneID.GetCloneID() != team->zoneId.GetCloneID())
|
|
||||||
{
|
|
||||||
playerContainer.RemoveMember(team, playerID, false, false, true, true);
|
playerContainer.RemoveMember(team, playerID, false, false, true, true);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (team->memberIDs.size() <= 1 && !team->local)
|
if (team->memberIDs.size() <= 1 && !team->local) {
|
||||||
{
|
|
||||||
playerContainer.DisbandTeam(team);
|
playerContainer.DisbandTeam(team);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!team->local)
|
if (!team->local) {
|
||||||
{
|
|
||||||
ChatPacketHandler::SendTeamSetLeader(data, team->leaderID);
|
ChatPacketHandler::SendTeamSetLeader(data, team->leaderID);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
ChatPacketHandler::SendTeamSetLeader(data, LWOOBJID_EMPTY);
|
ChatPacketHandler::SendTeamSetLeader(data, LWOOBJID_EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
playerContainer.TeamStatusUpdate(team);
|
playerContainer.TeamStatusUpdate(team);
|
||||||
|
|
||||||
const auto leaderName = GeneralUtils::ASCIIToUTF16(std::string(data->playerName.c_str()));
|
const auto leaderName = GeneralUtils::UTF8ToUTF16(data->playerName);
|
||||||
|
|
||||||
for (const auto memberId : team->memberIDs)
|
for (const auto memberId : team->memberIDs) {
|
||||||
{
|
|
||||||
auto* otherMember = playerContainer.GetPlayerData(memberId);
|
auto* otherMember = playerContainer.GetPlayerData(memberId);
|
||||||
|
|
||||||
if (memberId == playerID) continue;
|
if (memberId == playerID) continue;
|
||||||
|
|
||||||
const auto memberName = playerContainer.GetName(memberId);
|
const auto memberName = playerContainer.GetName(memberId);
|
||||||
|
|
||||||
if (otherMember != nullptr)
|
if (otherMember != nullptr) {
|
||||||
{
|
|
||||||
ChatPacketHandler::SendTeamSetOffWorldFlag(otherMember, data->playerID, data->zoneID);
|
ChatPacketHandler::SendTeamSetOffWorldFlag(otherMember, data->playerID, data->zoneID);
|
||||||
}
|
}
|
||||||
ChatPacketHandler::SendTeamAddPlayer(data, false, team->local, false, memberId, memberName, otherMember != nullptr ? otherMember->zoneID : LWOZONEID(0, 0, 0));
|
ChatPacketHandler::SendTeamAddPlayer(data, false, team->local, false, memberId, memberName, otherMember != nullptr ? otherMember->zoneID : LWOZONEID(0, 0, 0));
|
||||||
@ -741,8 +714,7 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender)
|
void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender) {
|
||||||
{
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
|
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
@ -757,14 +729,13 @@ void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender)
|
|||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::SendTeamInviteConfirm(PlayerData* receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName)
|
void ChatPacketHandler::SendTeamInviteConfirm(PlayerData* receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName) {
|
||||||
{
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
|
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
CMSGHEADER
|
CMSGHEADER;
|
||||||
|
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
bitStream.Write(GAME_MSG::GAME_MSG_TEAM_INVITE_CONFIRM);
|
bitStream.Write(GAME_MSG::GAME_MSG_TEAM_INVITE_CONFIRM);
|
||||||
@ -777,8 +748,7 @@ void ChatPacketHandler::SendTeamInviteConfirm(PlayerData* receiver, bool bLeader
|
|||||||
bitStream.Write(ucNumOfOtherPlayers);
|
bitStream.Write(ucNumOfOtherPlayers);
|
||||||
bitStream.Write(ucResponseCode);
|
bitStream.Write(ucResponseCode);
|
||||||
bitStream.Write(static_cast<uint32_t>(wsLeaderName.size()));
|
bitStream.Write(static_cast<uint32_t>(wsLeaderName.size()));
|
||||||
for (const auto character : wsLeaderName)
|
for (const auto character : wsLeaderName) {
|
||||||
{
|
|
||||||
bitStream.Write(character);
|
bitStream.Write(character);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -786,14 +756,13 @@ void ChatPacketHandler::SendTeamInviteConfirm(PlayerData* receiver, bool bLeader
|
|||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName)
|
void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName) {
|
||||||
{
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
|
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
CMSGHEADER
|
CMSGHEADER;
|
||||||
|
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
bitStream.Write(GAME_MSG::GAME_MSG_TEAM_GET_STATUS_RESPONSE);
|
bitStream.Write(GAME_MSG::GAME_MSG_TEAM_GET_STATUS_RESPONSE);
|
||||||
@ -804,8 +773,7 @@ void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderI
|
|||||||
bitStream.Write(ucLootFlag);
|
bitStream.Write(ucLootFlag);
|
||||||
bitStream.Write(ucNumOfOtherPlayers);
|
bitStream.Write(ucNumOfOtherPlayers);
|
||||||
bitStream.Write(static_cast<uint32_t>(wsLeaderName.size()));
|
bitStream.Write(static_cast<uint32_t>(wsLeaderName.size()));
|
||||||
for (const auto character : wsLeaderName)
|
for (const auto character : wsLeaderName) {
|
||||||
{
|
|
||||||
bitStream.Write(character);
|
bitStream.Write(character);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -813,14 +781,13 @@ void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderI
|
|||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64PlayerID)
|
void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64PlayerID) {
|
||||||
{
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
|
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
CMSGHEADER
|
CMSGHEADER;
|
||||||
|
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
bitStream.Write(GAME_MSG::GAME_MSG_TEAM_SET_LEADER);
|
bitStream.Write(GAME_MSG::GAME_MSG_TEAM_SET_LEADER);
|
||||||
@ -831,14 +798,13 @@ void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64Play
|
|||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID)
|
void ChatPacketHandler::SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID) {
|
||||||
{
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
|
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
CMSGHEADER
|
CMSGHEADER;
|
||||||
|
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
bitStream.Write(GAME_MSG::GAME_MSG_TEAM_ADD_PLAYER);
|
bitStream.Write(GAME_MSG::GAME_MSG_TEAM_ADD_PLAYER);
|
||||||
@ -848,13 +814,11 @@ void ChatPacketHandler::SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTria
|
|||||||
bitStream.Write(bNoLootOnDeath);
|
bitStream.Write(bNoLootOnDeath);
|
||||||
bitStream.Write(i64PlayerID);
|
bitStream.Write(i64PlayerID);
|
||||||
bitStream.Write(static_cast<uint32_t>(wsPlayerName.size()));
|
bitStream.Write(static_cast<uint32_t>(wsPlayerName.size()));
|
||||||
for (const auto character : wsPlayerName)
|
for (const auto character : wsPlayerName) {
|
||||||
{
|
|
||||||
bitStream.Write(character);
|
bitStream.Write(character);
|
||||||
}
|
}
|
||||||
bitStream.Write1();
|
bitStream.Write1();
|
||||||
if (receiver->zoneID.GetCloneID() == zoneID.GetCloneID())
|
if (receiver->zoneID.GetCloneID() == zoneID.GetCloneID()) {
|
||||||
{
|
|
||||||
zoneID = LWOZONEID(zoneID.GetMapID(), zoneID.GetInstanceID(), 0);
|
zoneID = LWOZONEID(zoneID.GetMapID(), zoneID.GetInstanceID(), 0);
|
||||||
}
|
}
|
||||||
bitStream.Write(zoneID);
|
bitStream.Write(zoneID);
|
||||||
@ -863,14 +827,13 @@ void ChatPacketHandler::SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTria
|
|||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::SendTeamRemovePlayer(PlayerData* receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName)
|
void ChatPacketHandler::SendTeamRemovePlayer(PlayerData* receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName) {
|
||||||
{
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
|
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
CMSGHEADER
|
CMSGHEADER;
|
||||||
|
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
bitStream.Write(GAME_MSG::GAME_MSG_TEAM_REMOVE_PLAYER);
|
bitStream.Write(GAME_MSG::GAME_MSG_TEAM_REMOVE_PLAYER);
|
||||||
@ -882,8 +845,7 @@ void ChatPacketHandler::SendTeamRemovePlayer(PlayerData* receiver, bool bDisband
|
|||||||
bitStream.Write(i64LeaderID);
|
bitStream.Write(i64LeaderID);
|
||||||
bitStream.Write(i64PlayerID);
|
bitStream.Write(i64PlayerID);
|
||||||
bitStream.Write(static_cast<uint32_t>(wsPlayerName.size()));
|
bitStream.Write(static_cast<uint32_t>(wsPlayerName.size()));
|
||||||
for (const auto character : wsPlayerName)
|
for (const auto character : wsPlayerName) {
|
||||||
{
|
|
||||||
bitStream.Write(character);
|
bitStream.Write(character);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -891,21 +853,19 @@ void ChatPacketHandler::SendTeamRemovePlayer(PlayerData* receiver, bool bDisband
|
|||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::SendTeamSetOffWorldFlag(PlayerData* receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID)
|
void ChatPacketHandler::SendTeamSetOffWorldFlag(PlayerData* receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID) {
|
||||||
{
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
|
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
CMSGHEADER
|
CMSGHEADER;
|
||||||
|
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
bitStream.Write(GAME_MSG::GAME_MSG_TEAM_SET_OFF_WORLD_FLAG);
|
bitStream.Write(GAME_MSG::GAME_MSG_TEAM_SET_OFF_WORLD_FLAG);
|
||||||
|
|
||||||
bitStream.Write(i64PlayerID);
|
bitStream.Write(i64PlayerID);
|
||||||
if (receiver->zoneID.GetCloneID() == zoneID.GetCloneID())
|
if (receiver->zoneID.GetCloneID() == zoneID.GetCloneID()) {
|
||||||
{
|
|
||||||
zoneID = LWOZONEID(zoneID.GetMapID(), zoneID.GetInstanceID(), 0);
|
zoneID = LWOZONEID(zoneID.GetMapID(), zoneID.GetInstanceID(), 0);
|
||||||
}
|
}
|
||||||
bitStream.Write(zoneID);
|
bitStream.Write(zoneID);
|
||||||
@ -943,12 +903,9 @@ void ChatPacketHandler::SendFriendUpdate(PlayerData* friendData, PlayerData* pla
|
|||||||
bitStream.Write(playerData->zoneID.GetMapID());
|
bitStream.Write(playerData->zoneID.GetMapID());
|
||||||
bitStream.Write(playerData->zoneID.GetInstanceID());
|
bitStream.Write(playerData->zoneID.GetInstanceID());
|
||||||
|
|
||||||
if (playerData->zoneID.GetCloneID() == friendData->zoneID.GetCloneID())
|
if (playerData->zoneID.GetCloneID() == friendData->zoneID.GetCloneID()) {
|
||||||
{
|
|
||||||
bitStream.Write(0);
|
bitStream.Write(0);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
bitStream.Write(playerData->zoneID.GetCloneID());
|
bitStream.Write(playerData->zoneID.GetCloneID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,9 +40,9 @@ int main(int argc, char** argv) {
|
|||||||
//Create all the objects we need to run our service:
|
//Create all the objects we need to run our service:
|
||||||
Game::logger = SetupLogger();
|
Game::logger = SetupLogger();
|
||||||
if (!Game::logger) return 0;
|
if (!Game::logger) return 0;
|
||||||
Game::logger->Log("ChatServer", "Starting Chat server...\n");
|
Game::logger->Log("ChatServer", "Starting Chat server...");
|
||||||
Game::logger->Log("ChatServer", "Version: %i.%i\n", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
|
Game::logger->Log("ChatServer", "Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
|
||||||
Game::logger->Log("ChatServer", "Compiled on: %s\n", __TIMESTAMP__);
|
Game::logger->Log("ChatServer", "Compiled on: %s", __TIMESTAMP__);
|
||||||
|
|
||||||
//Read our config:
|
//Read our config:
|
||||||
dConfig config("chatconfig.ini");
|
dConfig config("chatconfig.ini");
|
||||||
@ -58,9 +58,8 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password);
|
Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password);
|
||||||
}
|
} catch (sql::SQLException& ex) {
|
||||||
catch (sql::SQLException& ex) {
|
Game::logger->Log("ChatServer", "Got an error while connecting to the database: %s", ex.what());
|
||||||
Game::logger->Log("ChatServer", "Got an error while connecting to the database: %s\n", ex.what());
|
|
||||||
Database::Destroy("ChatServer");
|
Database::Destroy("ChatServer");
|
||||||
delete Game::server;
|
delete Game::server;
|
||||||
delete Game::logger;
|
delete Game::logger;
|
||||||
@ -104,8 +103,7 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
if (framesSinceMasterDisconnect >= 30)
|
if (framesSinceMasterDisconnect >= 30)
|
||||||
break; //Exit our loop, shut down.
|
break; //Exit our loop, shut down.
|
||||||
}
|
} else framesSinceMasterDisconnect = 0;
|
||||||
else framesSinceMasterDisconnect = 0;
|
|
||||||
|
|
||||||
//In world we'd update our other systems here.
|
//In world we'd update our other systems here.
|
||||||
|
|
||||||
@ -122,8 +120,7 @@ int main(int argc, char** argv) {
|
|||||||
if (framesSinceLastFlush >= 900) {
|
if (framesSinceLastFlush >= 900) {
|
||||||
Game::logger->Flush();
|
Game::logger->Flush();
|
||||||
framesSinceLastFlush = 0;
|
framesSinceLastFlush = 0;
|
||||||
}
|
} else framesSinceLastFlush++;
|
||||||
else framesSinceLastFlush++;
|
|
||||||
|
|
||||||
//Every 10 min we ping our sql server to keep it alive hopefully:
|
//Every 10 min we ping our sql server to keep it alive hopefully:
|
||||||
if (framesSinceLastSQLPing >= 40000) {
|
if (framesSinceLastSQLPing >= 40000) {
|
||||||
@ -141,8 +138,7 @@ int main(int argc, char** argv) {
|
|||||||
delete stmt;
|
delete stmt;
|
||||||
|
|
||||||
framesSinceLastSQLPing = 0;
|
framesSinceLastSQLPing = 0;
|
||||||
}
|
} else framesSinceLastSQLPing++;
|
||||||
else framesSinceLastSQLPing++;
|
|
||||||
|
|
||||||
//Sleep our thread since auth can afford to.
|
//Sleep our thread since auth can afford to.
|
||||||
t += std::chrono::milliseconds(mediumFramerate); //Chat can run at a lower "fps"
|
t += std::chrono::milliseconds(mediumFramerate); //Chat can run at a lower "fps"
|
||||||
@ -158,7 +154,7 @@ int main(int argc, char** argv) {
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
dLogger * SetupLogger() {
|
dLogger* SetupLogger() {
|
||||||
std::string logPath = "./logs/ChatServer_" + std::to_string(time(nullptr)) + ".log";
|
std::string logPath = "./logs/ChatServer_" + std::to_string(time(nullptr)) + ".log";
|
||||||
bool logToConsole = false;
|
bool logToConsole = false;
|
||||||
bool logDebugStatements = false;
|
bool logDebugStatements = false;
|
||||||
@ -172,11 +168,11 @@ dLogger * SetupLogger() {
|
|||||||
|
|
||||||
void HandlePacket(Packet* packet) {
|
void HandlePacket(Packet* packet) {
|
||||||
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
|
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
|
||||||
Game::logger->Log("ChatServer", "A server has disconnected, erasing their connected players from the list.\n");
|
Game::logger->Log("ChatServer", "A server has disconnected, erasing their connected players from the list.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet->data[0] == ID_NEW_INCOMING_CONNECTION) {
|
if (packet->data[0] == ID_NEW_INCOMING_CONNECTION) {
|
||||||
Game::logger->Log("ChatServer", "A server is connecting, awaiting user list.\n");
|
Game::logger->Log("ChatServer", "A server is connecting, awaiting user list.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet->data[1] == CHAT_INTERNAL) {
|
if (packet->data[1] == CHAT_INTERNAL) {
|
||||||
@ -205,7 +201,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Game::logger->Log("ChatServer", "Unknown CHAT_INTERNAL id: %i\n", int(packet->data[3]));
|
Game::logger->Log("ChatServer", "Unknown CHAT_INTERNAL id: %i", int(packet->data[3]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,7 +212,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MSG_CHAT_GET_IGNORE_LIST:
|
case MSG_CHAT_GET_IGNORE_LIST:
|
||||||
Game::logger->Log("ChatServer", "Asked for ignore list, but is unimplemented right now.\n");
|
Game::logger->Log("ChatServer", "Asked for ignore list, but is unimplemented right now.");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MSG_CHAT_TEAM_GET_STATUS:
|
case MSG_CHAT_TEAM_GET_STATUS:
|
||||||
@ -274,19 +270,19 @@ void HandlePacket(Packet* packet) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Game::logger->Log("ChatServer", "Unknown CHAT id: %i\n", int(packet->data[3]));
|
Game::logger->Log("ChatServer", "Unknown CHAT id: %i", int(packet->data[3]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet->data[1] == WORLD) {
|
if (packet->data[1] == WORLD) {
|
||||||
switch (packet->data[3]) {
|
switch (packet->data[3]) {
|
||||||
case MSG_WORLD_CLIENT_ROUTE_PACKET: {
|
case MSG_WORLD_CLIENT_ROUTE_PACKET: {
|
||||||
printf("routing packet from world\n");
|
Game::logger->Log("ChatServer", "Routing packet from world");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Game::logger->Log("ChatServer", "Unknown World id: %i\n", int(packet->data[3]));
|
Game::logger->Log("ChatServer", "Unknown World id: %i", int(packet->data[3]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,10 +35,10 @@ void PlayerContainer::InsertPlayer(Packet* packet) {
|
|||||||
inStream.Read(data->muteExpire);
|
inStream.Read(data->muteExpire);
|
||||||
data->sysAddr = packet->systemAddress;
|
data->sysAddr = packet->systemAddress;
|
||||||
|
|
||||||
mNames[data->playerID] = GeneralUtils::ASCIIToUTF16(std::string(data->playerName.c_str()));
|
mNames[data->playerID] = GeneralUtils::UTF8ToUTF16(data->playerName);
|
||||||
|
|
||||||
mPlayers.insert(std::make_pair(data->playerID, data));
|
mPlayers.insert(std::make_pair(data->playerID, data));
|
||||||
Game::logger->Log("PlayerContainer", "Added user: %s (%llu), zone: %i\n", data->playerName.c_str(), data->playerID, data->zoneID.GetMapID());
|
Game::logger->Log("PlayerContainer", "Added user: %s (%llu), zone: %i", data->playerName.c_str(), data->playerID, data->zoneID.GetMapID());
|
||||||
|
|
||||||
auto* insertLog = Database::CreatePreppedStmt("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);");
|
auto* insertLog = Database::CreatePreppedStmt("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);");
|
||||||
|
|
||||||
@ -70,21 +70,19 @@ void PlayerContainer::RemovePlayer(Packet* packet) {
|
|||||||
|
|
||||||
auto* team = GetTeam(playerID);
|
auto* team = GetTeam(playerID);
|
||||||
|
|
||||||
if (team != nullptr)
|
if (team != nullptr) {
|
||||||
{
|
const auto memberName = GeneralUtils::UTF8ToUTF16(std::string(player->playerName.c_str()));
|
||||||
const auto memberName = GeneralUtils::ASCIIToUTF16(std::string(player->playerName.c_str()));
|
|
||||||
|
|
||||||
for (const auto memberId : team->memberIDs)
|
for (const auto memberId : team->memberIDs) {
|
||||||
{
|
|
||||||
auto* otherMember = GetPlayerData(memberId);
|
auto* otherMember = GetPlayerData(memberId);
|
||||||
|
|
||||||
if (otherMember == nullptr) continue;
|
if (otherMember == nullptr) continue;
|
||||||
|
|
||||||
ChatPacketHandler::SendTeamSetOffWorldFlag(otherMember, playerID, {0, 0, 0});
|
ChatPacketHandler::SendTeamSetOffWorldFlag(otherMember, playerID, { 0, 0, 0 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Game::logger->Log("PlayerContainer", "Removed user: %llu\n", playerID);
|
Game::logger->Log("PlayerContainer", "Removed user: %llu", playerID);
|
||||||
mPlayers.erase(playerID);
|
mPlayers.erase(playerID);
|
||||||
|
|
||||||
auto* insertLog = Database::CreatePreppedStmt("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);");
|
auto* insertLog = Database::CreatePreppedStmt("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);");
|
||||||
@ -97,8 +95,7 @@ void PlayerContainer::RemovePlayer(Packet* packet) {
|
|||||||
insertLog->executeUpdate();
|
insertLog->executeUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerContainer::MuteUpdate(Packet* packet)
|
void PlayerContainer::MuteUpdate(Packet* packet) {
|
||||||
{
|
|
||||||
CINSTREAM;
|
CINSTREAM;
|
||||||
LWOOBJID playerID;
|
LWOOBJID playerID;
|
||||||
inStream.Read(playerID); //skip header
|
inStream.Read(playerID); //skip header
|
||||||
@ -108,9 +105,8 @@ void PlayerContainer::MuteUpdate(Packet* packet)
|
|||||||
|
|
||||||
auto* player = this->GetPlayerData(playerID);
|
auto* player = this->GetPlayerData(playerID);
|
||||||
|
|
||||||
if (player == nullptr)
|
if (player == nullptr) {
|
||||||
{
|
Game::logger->Log("PlayerContainer", "Failed to find user: %llu", playerID);
|
||||||
Game::logger->Log("PlayerContainer", "Failed to find user: %llu\n", playerID);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -120,8 +116,7 @@ void PlayerContainer::MuteUpdate(Packet* packet)
|
|||||||
BroadcastMuteUpdate(playerID, expire);
|
BroadcastMuteUpdate(playerID, expire);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerContainer::CreateTeamServer(Packet* packet)
|
void PlayerContainer::CreateTeamServer(Packet* packet) {
|
||||||
{
|
|
||||||
CINSTREAM;
|
CINSTREAM;
|
||||||
LWOOBJID playerID;
|
LWOOBJID playerID;
|
||||||
inStream.Read(playerID); //skip header
|
inStream.Read(playerID); //skip header
|
||||||
@ -133,8 +128,7 @@ void PlayerContainer::CreateTeamServer(Packet* packet)
|
|||||||
|
|
||||||
members.reserve(membersSize);
|
members.reserve(membersSize);
|
||||||
|
|
||||||
for (size_t i = 0; i < membersSize; i++)
|
for (size_t i = 0; i < membersSize; i++) {
|
||||||
{
|
|
||||||
LWOOBJID member;
|
LWOOBJID member;
|
||||||
inStream.Read(member);
|
inStream.Read(member);
|
||||||
members.push_back(member);
|
members.push_back(member);
|
||||||
@ -146,16 +140,14 @@ void PlayerContainer::CreateTeamServer(Packet* packet)
|
|||||||
|
|
||||||
auto* team = CreateLocalTeam(members);
|
auto* team = CreateLocalTeam(members);
|
||||||
|
|
||||||
if (team != nullptr)
|
if (team != nullptr) {
|
||||||
{
|
|
||||||
team->zoneId = zoneId;
|
team->zoneId = zoneId;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateTeamsOnWorld(team, false);
|
UpdateTeamsOnWorld(team, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time)
|
void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time) {
|
||||||
{
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_MUTE_UPDATE);
|
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_MUTE_UPDATE);
|
||||||
|
|
||||||
@ -165,30 +157,23 @@ void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time)
|
|||||||
Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
|
Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
TeamData* PlayerContainer::CreateLocalTeam(std::vector<LWOOBJID> members)
|
TeamData* PlayerContainer::CreateLocalTeam(std::vector<LWOOBJID> members) {
|
||||||
{
|
if (members.empty()) {
|
||||||
if (members.empty())
|
|
||||||
{
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
TeamData* newTeam = nullptr;
|
TeamData* newTeam = nullptr;
|
||||||
|
|
||||||
for (const auto member : members)
|
for (const auto member : members) {
|
||||||
{
|
|
||||||
auto* team = GetTeam(member);
|
auto* team = GetTeam(member);
|
||||||
|
|
||||||
if (team != nullptr)
|
if (team != nullptr) {
|
||||||
{
|
|
||||||
RemoveMember(team, member, false, false, true);
|
RemoveMember(team, member, false, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newTeam == nullptr)
|
if (newTeam == nullptr) {
|
||||||
{
|
|
||||||
newTeam = CreateTeam(member, true);
|
newTeam = CreateTeam(member, true);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
AddMember(newTeam, member);
|
AddMember(newTeam, member);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -200,8 +185,7 @@ TeamData* PlayerContainer::CreateLocalTeam(std::vector<LWOOBJID> members)
|
|||||||
return newTeam;
|
return newTeam;
|
||||||
}
|
}
|
||||||
|
|
||||||
TeamData* PlayerContainer::CreateTeam(LWOOBJID leader, bool local)
|
TeamData* PlayerContainer::CreateTeam(LWOOBJID leader, bool local) {
|
||||||
{
|
|
||||||
auto* team = new TeamData();
|
auto* team = new TeamData();
|
||||||
|
|
||||||
team->teamID = ++mTeamIDCounter;
|
team->teamID = ++mTeamIDCounter;
|
||||||
@ -215,10 +199,8 @@ TeamData* PlayerContainer::CreateTeam(LWOOBJID leader, bool local)
|
|||||||
return team;
|
return team;
|
||||||
}
|
}
|
||||||
|
|
||||||
TeamData* PlayerContainer::GetTeam(LWOOBJID playerID)
|
TeamData* PlayerContainer::GetTeam(LWOOBJID playerID) {
|
||||||
{
|
for (auto* team : mTeams) {
|
||||||
for (auto* team : mTeams)
|
|
||||||
{
|
|
||||||
if (std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID) == team->memberIDs.end()) continue;
|
if (std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID) == team->memberIDs.end()) continue;
|
||||||
|
|
||||||
return team;
|
return team;
|
||||||
@ -227,8 +209,7 @@ TeamData* PlayerContainer::GetTeam(LWOOBJID playerID)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID)
|
void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID) {
|
||||||
{
|
|
||||||
const auto index = std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID);
|
const auto index = std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID);
|
||||||
|
|
||||||
if (index != team->memberIDs.end()) return;
|
if (index != team->memberIDs.end()) return;
|
||||||
@ -240,24 +221,20 @@ void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID)
|
|||||||
|
|
||||||
if (leader == nullptr || member == nullptr) return;
|
if (leader == nullptr || member == nullptr) return;
|
||||||
|
|
||||||
const auto leaderName = GeneralUtils::ASCIIToUTF16(std::string(leader->playerName.c_str()));
|
const auto leaderName = GeneralUtils::UTF8ToUTF16(leader->playerName);
|
||||||
const auto memberName = GeneralUtils::ASCIIToUTF16(std::string(member->playerName.c_str()));
|
const auto memberName = GeneralUtils::UTF8ToUTF16(member->playerName);
|
||||||
|
|
||||||
ChatPacketHandler::SendTeamInviteConfirm(member, false, leader->playerID, leader->zoneID, team->lootFlag, 0, 0, leaderName);
|
ChatPacketHandler::SendTeamInviteConfirm(member, false, leader->playerID, leader->zoneID, team->lootFlag, 0, 0, leaderName);
|
||||||
|
|
||||||
if (!team->local)
|
if (!team->local) {
|
||||||
{
|
|
||||||
ChatPacketHandler::SendTeamSetLeader(member, leader->playerID);
|
ChatPacketHandler::SendTeamSetLeader(member, leader->playerID);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
ChatPacketHandler::SendTeamSetLeader(member, LWOOBJID_EMPTY);
|
ChatPacketHandler::SendTeamSetLeader(member, LWOOBJID_EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateTeamsOnWorld(team, false);
|
UpdateTeamsOnWorld(team, false);
|
||||||
|
|
||||||
for (const auto memberId : team->memberIDs)
|
for (const auto memberId : team->memberIDs) {
|
||||||
{
|
|
||||||
auto* otherMember = GetPlayerData(memberId);
|
auto* otherMember = GetPlayerData(memberId);
|
||||||
|
|
||||||
if (otherMember == member) continue;
|
if (otherMember == member) continue;
|
||||||
@ -266,32 +243,27 @@ void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID)
|
|||||||
|
|
||||||
ChatPacketHandler::SendTeamAddPlayer(member, false, team->local, false, memberId, otherMemberName, otherMember != nullptr ? otherMember->zoneID : LWOZONEID(0, 0, 0));
|
ChatPacketHandler::SendTeamAddPlayer(member, false, team->local, false, memberId, otherMemberName, otherMember != nullptr ? otherMember->zoneID : LWOZONEID(0, 0, 0));
|
||||||
|
|
||||||
if (otherMember != nullptr)
|
if (otherMember != nullptr) {
|
||||||
{
|
|
||||||
ChatPacketHandler::SendTeamAddPlayer(otherMember, false, team->local, false, member->playerID, memberName, member->zoneID);
|
ChatPacketHandler::SendTeamAddPlayer(otherMember, false, team->local, false, member->playerID, memberName, member->zoneID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerContainer::RemoveMember(TeamData* team, LWOOBJID playerID, bool disband, bool kicked, bool leaving, bool silent)
|
void PlayerContainer::RemoveMember(TeamData* team, LWOOBJID playerID, bool disband, bool kicked, bool leaving, bool silent) {
|
||||||
{
|
|
||||||
const auto index = std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID);
|
const auto index = std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID);
|
||||||
|
|
||||||
if (index == team->memberIDs.end()) return;
|
if (index == team->memberIDs.end()) return;
|
||||||
|
|
||||||
auto* member = GetPlayerData(playerID);
|
auto* member = GetPlayerData(playerID);
|
||||||
|
|
||||||
if (member != nullptr && !silent)
|
if (member != nullptr && !silent) {
|
||||||
{
|
|
||||||
ChatPacketHandler::SendTeamSetLeader(member, LWOOBJID_EMPTY);
|
ChatPacketHandler::SendTeamSetLeader(member, LWOOBJID_EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto memberName = GetName(playerID);
|
const auto memberName = GetName(playerID);
|
||||||
|
|
||||||
for (const auto memberId : team->memberIDs)
|
for (const auto memberId : team->memberIDs) {
|
||||||
{
|
if (silent && memberId == playerID) {
|
||||||
if (silent && memberId == playerID)
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,25 +278,19 @@ void PlayerContainer::RemoveMember(TeamData* team, LWOOBJID playerID, bool disba
|
|||||||
|
|
||||||
UpdateTeamsOnWorld(team, false);
|
UpdateTeamsOnWorld(team, false);
|
||||||
|
|
||||||
if (team->memberIDs.size() <= 1)
|
if (team->memberIDs.size() <= 1) {
|
||||||
{
|
|
||||||
DisbandTeam(team);
|
DisbandTeam(team);
|
||||||
}
|
} else {
|
||||||
else
|
if (playerID == team->leaderID) {
|
||||||
{
|
|
||||||
if (playerID == team->leaderID)
|
|
||||||
{
|
|
||||||
PromoteMember(team, team->memberIDs[0]);
|
PromoteMember(team, team->memberIDs[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerContainer::PromoteMember(TeamData* team, LWOOBJID newLeader)
|
void PlayerContainer::PromoteMember(TeamData* team, LWOOBJID newLeader) {
|
||||||
{
|
|
||||||
team->leaderID = newLeader;
|
team->leaderID = newLeader;
|
||||||
|
|
||||||
for (const auto memberId : team->memberIDs)
|
for (const auto memberId : team->memberIDs) {
|
||||||
{
|
|
||||||
auto* otherMember = GetPlayerData(memberId);
|
auto* otherMember = GetPlayerData(memberId);
|
||||||
|
|
||||||
if (otherMember == nullptr) continue;
|
if (otherMember == nullptr) continue;
|
||||||
@ -333,19 +299,17 @@ void PlayerContainer::PromoteMember(TeamData* team, LWOOBJID newLeader)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerContainer::DisbandTeam(TeamData* team)
|
void PlayerContainer::DisbandTeam(TeamData* team) {
|
||||||
{
|
|
||||||
const auto index = std::find(mTeams.begin(), mTeams.end(), team);
|
const auto index = std::find(mTeams.begin(), mTeams.end(), team);
|
||||||
|
|
||||||
if (index == mTeams.end()) return;
|
if (index == mTeams.end()) return;
|
||||||
|
|
||||||
for (const auto memberId : team->memberIDs)
|
for (const auto memberId : team->memberIDs) {
|
||||||
{
|
|
||||||
auto* otherMember = GetPlayerData(memberId);
|
auto* otherMember = GetPlayerData(memberId);
|
||||||
|
|
||||||
if (otherMember == nullptr) continue;
|
if (otherMember == nullptr) continue;
|
||||||
|
|
||||||
const auto memberName = GeneralUtils::ASCIIToUTF16(std::string(otherMember->playerName.c_str()));
|
const auto memberName = GeneralUtils::UTF8ToUTF16(otherMember->playerName);
|
||||||
|
|
||||||
ChatPacketHandler::SendTeamSetLeader(otherMember, LWOOBJID_EMPTY);
|
ChatPacketHandler::SendTeamSetLeader(otherMember, LWOOBJID_EMPTY);
|
||||||
ChatPacketHandler::SendTeamRemovePlayer(otherMember, true, false, false, team->local, team->leaderID, otherMember->playerID, memberName);
|
ChatPacketHandler::SendTeamRemovePlayer(otherMember, true, false, false, team->local, team->leaderID, otherMember->playerID, memberName);
|
||||||
@ -358,8 +322,7 @@ void PlayerContainer::DisbandTeam(TeamData* team)
|
|||||||
delete team;
|
delete team;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerContainer::TeamStatusUpdate(TeamData* team)
|
void PlayerContainer::TeamStatusUpdate(TeamData* team) {
|
||||||
{
|
|
||||||
const auto index = std::find(mTeams.begin(), mTeams.end(), team);
|
const auto index = std::find(mTeams.begin(), mTeams.end(), team);
|
||||||
|
|
||||||
if (index == mTeams.end()) return;
|
if (index == mTeams.end()) return;
|
||||||
@ -368,16 +331,14 @@ void PlayerContainer::TeamStatusUpdate(TeamData* team)
|
|||||||
|
|
||||||
if (leader == nullptr) return;
|
if (leader == nullptr) return;
|
||||||
|
|
||||||
const auto leaderName = GeneralUtils::ASCIIToUTF16(std::string(leader->playerName.c_str()));
|
const auto leaderName = GeneralUtils::UTF8ToUTF16(leader->playerName);
|
||||||
|
|
||||||
for (const auto memberId : team->memberIDs)
|
for (const auto memberId : team->memberIDs) {
|
||||||
{
|
|
||||||
auto* otherMember = GetPlayerData(memberId);
|
auto* otherMember = GetPlayerData(memberId);
|
||||||
|
|
||||||
if (otherMember == nullptr) continue;
|
if (otherMember == nullptr) continue;
|
||||||
|
|
||||||
if (!team->local)
|
if (!team->local) {
|
||||||
{
|
|
||||||
ChatPacketHandler::SendTeamStatus(otherMember, team->leaderID, leader->zoneID, team->lootFlag, 0, leaderName);
|
ChatPacketHandler::SendTeamStatus(otherMember, team->leaderID, leader->zoneID, team->lootFlag, 0, leaderName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -385,20 +346,17 @@ void PlayerContainer::TeamStatusUpdate(TeamData* team)
|
|||||||
UpdateTeamsOnWorld(team, false);
|
UpdateTeamsOnWorld(team, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam)
|
void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) {
|
||||||
{
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_TEAM_UPDATE);
|
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_TEAM_UPDATE);
|
||||||
|
|
||||||
bitStream.Write(team->teamID);
|
bitStream.Write(team->teamID);
|
||||||
bitStream.Write(deleteTeam);
|
bitStream.Write(deleteTeam);
|
||||||
|
|
||||||
if (!deleteTeam)
|
if (!deleteTeam) {
|
||||||
{
|
|
||||||
bitStream.Write(team->lootFlag);
|
bitStream.Write(team->lootFlag);
|
||||||
bitStream.Write(static_cast<char>(team->memberIDs.size()));
|
bitStream.Write(static_cast<char>(team->memberIDs.size()));
|
||||||
for (const auto memberID : team->memberIDs)
|
for (const auto memberID : team->memberIDs) {
|
||||||
{
|
|
||||||
bitStream.Write(memberID);
|
bitStream.Write(memberID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -406,8 +364,7 @@ void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam)
|
|||||||
Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
|
Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::u16string PlayerContainer::GetName(LWOOBJID playerID)
|
std::u16string PlayerContainer::GetName(LWOOBJID playerID) {
|
||||||
{
|
|
||||||
const auto& pair = mNames.find(playerID);
|
const auto& pair = mNames.find(playerID);
|
||||||
|
|
||||||
if (pair == mNames.end()) return u"";
|
if (pair == mNames.end()) return u"";
|
||||||
@ -415,12 +372,9 @@ std::u16string PlayerContainer::GetName(LWOOBJID playerID)
|
|||||||
return pair->second;
|
return pair->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
LWOOBJID PlayerContainer::GetId(const std::u16string& playerName)
|
LWOOBJID PlayerContainer::GetId(const std::u16string& playerName) {
|
||||||
{
|
for (const auto& pair : mNames) {
|
||||||
for (const auto& pair : mNames)
|
if (pair.second == playerName) {
|
||||||
{
|
|
||||||
if (pair.second == playerName)
|
|
||||||
{
|
|
||||||
return pair.first;
|
return pair.first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -428,7 +382,6 @@ LWOOBJID PlayerContainer::GetId(const std::u16string& playerName)
|
|||||||
return LWOOBJID_EMPTY;
|
return LWOOBJID_EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PlayerContainer::GetIsMuted(PlayerData* data)
|
bool PlayerContainer::GetIsMuted(PlayerData* data) {
|
||||||
{
|
|
||||||
return data->muteExpire == 1 || data->muteExpire > time(NULL);
|
return data->muteExpire == 1 || data->muteExpire > time(NULL);
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ struct PlayerData {
|
|||||||
struct TeamData {
|
struct TeamData {
|
||||||
LWOOBJID teamID = LWOOBJID_EMPTY; // Internal use
|
LWOOBJID teamID = LWOOBJID_EMPTY; // Internal use
|
||||||
LWOOBJID leaderID = LWOOBJID_EMPTY;
|
LWOOBJID leaderID = LWOOBJID_EMPTY;
|
||||||
std::vector<LWOOBJID> memberIDs {};
|
std::vector<LWOOBJID> memberIDs{};
|
||||||
uint8_t lootFlag = 0;
|
uint8_t lootFlag = 0;
|
||||||
bool local = false;
|
bool local = false;
|
||||||
LWOZONEID zoneId = {};
|
LWOZONEID zoneId = {};
|
||||||
|
160
dCommon/AMFDeserialize.cpp
Normal file
160
dCommon/AMFDeserialize.cpp
Normal 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
71
dCommon/AMFDeserialize.h
Normal 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;
|
||||||
|
};
|
@ -108,6 +108,14 @@ _AMFArrayList_::iterator AMFArrayValue::GetDenseIteratorEnd() {
|
|||||||
return this->dense.end();
|
return this->dense.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AMFArrayValue::~AMFArrayValue() {
|
||||||
|
for (auto valueToDelete : GetDenseArray()) {
|
||||||
|
if (valueToDelete) delete valueToDelete;
|
||||||
|
}
|
||||||
|
for (auto valueToDelete : GetAssociativeMap()) {
|
||||||
|
if (valueToDelete.second) delete valueToDelete.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// AMFObject Constructor
|
// AMFObject Constructor
|
||||||
AMFObjectValue::AMFObjectValue(std::vector<std::pair<std::string, AMFValueType>> traits) {
|
AMFObjectValue::AMFObjectValue(std::vector<std::pair<std::string, AMFValueType>> traits) {
|
||||||
@ -155,3 +163,9 @@ _AMFObjectTraits_::iterator AMFObjectValue::GetTraitsIteratorEnd() {
|
|||||||
uint32_t AMFObjectValue::GetTraitArrayCount() {
|
uint32_t AMFObjectValue::GetTraitArrayCount() {
|
||||||
return (uint32_t)this->traits.size();
|
return (uint32_t)this->traits.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AMFObjectValue::~AMFObjectValue() {
|
||||||
|
for (auto valueToDelete = GetTraitsIteratorBegin(); valueToDelete != GetTraitsIteratorEnd(); valueToDelete++) {
|
||||||
|
if (valueToDelete->second.second) delete valueToDelete->second.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -59,6 +59,7 @@ public:
|
|||||||
\return The AMF value type
|
\return The AMF value type
|
||||||
*/
|
*/
|
||||||
virtual AMFValueType GetValueType() = 0;
|
virtual AMFValueType GetValueType() = 0;
|
||||||
|
virtual ~AMFValue() {};
|
||||||
};
|
};
|
||||||
|
|
||||||
//! A typedef for a pointer to an AMF value
|
//! A typedef for a pointer to an AMF value
|
||||||
@ -233,6 +234,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
//! The array value AMF type
|
//! The array value AMF type
|
||||||
|
// This object will manage it's own memory map and list. Do not delete its values.
|
||||||
class AMFArrayValue : public AMFValue {
|
class AMFArrayValue : public AMFValue {
|
||||||
private:
|
private:
|
||||||
_AMFArrayMap_ associative; //!< The array map (associative part)
|
_AMFArrayMap_ associative; //!< The array map (associative part)
|
||||||
@ -245,6 +247,7 @@ private:
|
|||||||
AMFValueType GetValueType() { return AMFArray; }
|
AMFValueType GetValueType() { return AMFArray; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
~AMFArrayValue() override;
|
||||||
//! Inserts an item into the array map for a specific key
|
//! Inserts an item into the array map for a specific key
|
||||||
/*!
|
/*!
|
||||||
\param key The key to set
|
\param key The key to set
|
||||||
@ -308,6 +311,18 @@ public:
|
|||||||
\return Where the iterator ends
|
\return Where the iterator ends
|
||||||
*/
|
*/
|
||||||
_AMFArrayList_::iterator GetDenseIteratorEnd();
|
_AMFArrayList_::iterator GetDenseIteratorEnd();
|
||||||
|
|
||||||
|
//! Returns the associative map
|
||||||
|
/*!
|
||||||
|
\return The associative map
|
||||||
|
*/
|
||||||
|
_AMFArrayMap_ GetAssociativeMap() { return this->associative; };
|
||||||
|
|
||||||
|
//! Returns the dense array
|
||||||
|
/*!
|
||||||
|
\return The dense array
|
||||||
|
*/
|
||||||
|
_AMFArrayList_ GetDenseArray() { return this->dense; };
|
||||||
};
|
};
|
||||||
|
|
||||||
//! The anonymous object value AMF type
|
//! The anonymous object value AMF type
|
||||||
@ -320,6 +335,7 @@ private:
|
|||||||
\return The AMF value type
|
\return The AMF value type
|
||||||
*/
|
*/
|
||||||
AMFValueType GetValueType() { return AMFObject; }
|
AMFValueType GetValueType() { return AMFObject; }
|
||||||
|
~AMFObjectValue() override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//! Constructor
|
//! Constructor
|
||||||
|
@ -37,6 +37,12 @@ void RakNet::BitStream::Write<AMFValue*>(AMFValue* value) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case AMFDouble: {
|
||||||
|
AMFDoubleValue* v = (AMFDoubleValue*)value;
|
||||||
|
this->Write(*v);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case AMFString: {
|
case AMFString: {
|
||||||
AMFStringValue* v = (AMFStringValue*)value;
|
AMFStringValue* v = (AMFStringValue*)value;
|
||||||
this->Write(*v);
|
this->Write(*v);
|
||||||
@ -56,15 +62,17 @@ void RakNet::BitStream::Write<AMFValue*>(AMFValue* value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case AMFArray: {
|
case AMFArray: {
|
||||||
AMFArrayValue* v = (AMFArrayValue*)value;
|
this->Write((AMFArrayValue*)value);
|
||||||
this->Write(*v);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A private function to write an value to a RakNet::BitStream
|
/**
|
||||||
|
* A private function to write an value to a RakNet::BitStream
|
||||||
|
* RakNet writes in the correct byte order - do not reverse this.
|
||||||
|
*/
|
||||||
void WriteUInt29(RakNet::BitStream* bs, uint32_t v) {
|
void WriteUInt29(RakNet::BitStream* bs, uint32_t v) {
|
||||||
unsigned char b4 = (unsigned char)v;
|
unsigned char b4 = (unsigned char)v;
|
||||||
if (v < 0x00200000) {
|
if (v < 0x00200000) {
|
||||||
@ -102,79 +110,50 @@ void WriteUInt29(RakNet::BitStream* bs, uint32_t v) {
|
|||||||
bs->Write(b4);
|
bs->Write(b4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes a flag number to a RakNet::BitStream
|
/**
|
||||||
|
* Writes a flag number to a RakNet::BitStream
|
||||||
|
* RakNet writes in the correct byte order - do not reverse this.
|
||||||
|
*/
|
||||||
void WriteFlagNumber(RakNet::BitStream* bs, uint32_t v) {
|
void WriteFlagNumber(RakNet::BitStream* bs, uint32_t v) {
|
||||||
v = (v << 1) | 0x01;
|
v = (v << 1) | 0x01;
|
||||||
WriteUInt29(bs, v);
|
WriteUInt29(bs, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes an AMFString to a RakNet::BitStream
|
/**
|
||||||
|
* Writes an AMFString to a RakNet::BitStream
|
||||||
|
*
|
||||||
|
* RakNet writes in the correct byte order - do not reverse this.
|
||||||
|
*/
|
||||||
void WriteAMFString(RakNet::BitStream* bs, const std::string& str) {
|
void WriteAMFString(RakNet::BitStream* bs, const std::string& str) {
|
||||||
WriteFlagNumber(bs, (uint32_t)str.size());
|
WriteFlagNumber(bs, (uint32_t)str.size());
|
||||||
bs->Write(str.c_str(), (uint32_t)str.size());
|
bs->Write(str.c_str(), (uint32_t)str.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes an AMF U16 to a RakNet::BitStream
|
/**
|
||||||
|
* Writes an U16 to a bitstream
|
||||||
|
*
|
||||||
|
* RakNet writes in the correct byte order - do not reverse this.
|
||||||
|
*/
|
||||||
void WriteAMFU16(RakNet::BitStream* bs, uint16_t value) {
|
void WriteAMFU16(RakNet::BitStream* bs, uint16_t value) {
|
||||||
unsigned char b2;
|
bs->Write(value);
|
||||||
b2 = (unsigned char)value;
|
|
||||||
value = value >> 8;
|
|
||||||
bs->Write((unsigned char)value);
|
|
||||||
bs->Write(b2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes an AMF U32 to RakNet::BitStream
|
/**
|
||||||
|
* Writes an U32 to a bitstream
|
||||||
|
*
|
||||||
|
* RakNet writes in the correct byte order - do not reverse this.
|
||||||
|
*/
|
||||||
void WriteAMFU32(RakNet::BitStream* bs, uint32_t value) {
|
void WriteAMFU32(RakNet::BitStream* bs, uint32_t value) {
|
||||||
unsigned char b2;
|
bs->Write(value);
|
||||||
unsigned char b3;
|
|
||||||
unsigned char b4;
|
|
||||||
|
|
||||||
b4 = (unsigned char)value;
|
|
||||||
value = value >> 8;
|
|
||||||
b3 = (unsigned char)value;
|
|
||||||
value = value >> 8;
|
|
||||||
b2 = (unsigned char)value;
|
|
||||||
value = value >> 8;
|
|
||||||
|
|
||||||
bs->Write((unsigned char)value);
|
|
||||||
bs->Write(b2);
|
|
||||||
bs->Write(b3);
|
|
||||||
bs->Write(b4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes an AMF U64 to RakNet::BitStream
|
/**
|
||||||
|
* Writes an U64 to a bitstream
|
||||||
|
*
|
||||||
|
* RakNet writes in the correct byte order - do not reverse this.
|
||||||
|
*/
|
||||||
void WriteAMFU64(RakNet::BitStream* bs, uint64_t value) {
|
void WriteAMFU64(RakNet::BitStream* bs, uint64_t value) {
|
||||||
unsigned char b2;
|
bs->Write(value);
|
||||||
unsigned char b3;
|
|
||||||
unsigned char b4;
|
|
||||||
unsigned char b5;
|
|
||||||
unsigned char b6;
|
|
||||||
unsigned char b7;
|
|
||||||
unsigned char b8;
|
|
||||||
|
|
||||||
b8 = (unsigned char)value;
|
|
||||||
value = value >> 8;
|
|
||||||
b7 = (unsigned char)value;
|
|
||||||
value = value >> 8;
|
|
||||||
b6 = (unsigned char)value;
|
|
||||||
value = value >> 8;
|
|
||||||
b5 = (unsigned char)value;
|
|
||||||
value = value >> 8;
|
|
||||||
b4 = (unsigned char)value;
|
|
||||||
value = value >> 8;
|
|
||||||
b3 = (unsigned char)value;
|
|
||||||
value = value >> 8;
|
|
||||||
b2 = (unsigned char)value;
|
|
||||||
value = value >> 8;
|
|
||||||
|
|
||||||
bs->Write((unsigned char)value);
|
|
||||||
bs->Write(b2);
|
|
||||||
bs->Write(b3);
|
|
||||||
bs->Write(b4);
|
|
||||||
bs->Write(b5);
|
|
||||||
bs->Write(b6);
|
|
||||||
bs->Write(b7);
|
|
||||||
bs->Write(b8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -214,7 +193,7 @@ template<>
|
|||||||
void RakNet::BitStream::Write<AMFDoubleValue>(AMFDoubleValue value) {
|
void RakNet::BitStream::Write<AMFDoubleValue>(AMFDoubleValue value) {
|
||||||
this->Write(AMFDouble);
|
this->Write(AMFDouble);
|
||||||
double d = value.GetDoubleValue();
|
double d = value.GetDoubleValue();
|
||||||
WriteAMFU64(this, *((unsigned long long*)&d));
|
WriteAMFU64(this, *((unsigned long long*) & d));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes an AMFStringValue to BitStream
|
// Writes an AMFStringValue to BitStream
|
||||||
@ -243,13 +222,13 @@ void RakNet::BitStream::Write<AMFDateValue>(AMFDateValue value) {
|
|||||||
|
|
||||||
// Writes an AMFArrayValue to BitStream
|
// Writes an AMFArrayValue to BitStream
|
||||||
template<>
|
template<>
|
||||||
void RakNet::BitStream::Write<AMFArrayValue>(AMFArrayValue value) {
|
void RakNet::BitStream::Write<AMFArrayValue*>(AMFArrayValue* value) {
|
||||||
this->Write(AMFArray);
|
this->Write(AMFArray);
|
||||||
uint32_t denseSize = value.GetDenseValueSize();
|
uint32_t denseSize = value->GetDenseValueSize();
|
||||||
WriteFlagNumber(this, denseSize);
|
WriteFlagNumber(this, denseSize);
|
||||||
|
|
||||||
_AMFArrayMap_::iterator it = value.GetAssociativeIteratorValueBegin();
|
_AMFArrayMap_::iterator it = value->GetAssociativeIteratorValueBegin();
|
||||||
_AMFArrayMap_::iterator end = value.GetAssociativeIteratorValueEnd();
|
_AMFArrayMap_::iterator end = value->GetAssociativeIteratorValueEnd();
|
||||||
|
|
||||||
while (it != end) {
|
while (it != end) {
|
||||||
WriteAMFString(this, it->first);
|
WriteAMFString(this, it->first);
|
||||||
@ -260,8 +239,8 @@ void RakNet::BitStream::Write<AMFArrayValue>(AMFArrayValue value) {
|
|||||||
this->Write(AMFNull);
|
this->Write(AMFNull);
|
||||||
|
|
||||||
if (denseSize > 0) {
|
if (denseSize > 0) {
|
||||||
_AMFArrayList_::iterator it2 = value.GetDenseIteratorBegin();
|
_AMFArrayList_::iterator it2 = value->GetDenseIteratorBegin();
|
||||||
_AMFArrayList_::iterator end2 = value.GetDenseIteratorEnd();
|
_AMFArrayList_::iterator end2 = value->GetDenseIteratorEnd();
|
||||||
|
|
||||||
while (it2 != end2) {
|
while (it2 != end2) {
|
||||||
this->Write(*it2);
|
this->Write(*it2);
|
||||||
|
@ -7,86 +7,86 @@
|
|||||||
#include <BitStream.h>
|
#include <BitStream.h>
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\file AMFBitStream.hpp
|
\file AMFFormat_BitStream.h
|
||||||
\brief A class that implements native writing of AMF values to RakNet::BitStream
|
\brief A class that implements native writing of AMF values to RakNet::BitStream
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// We are using the RakNet namespace
|
// We are using the RakNet namespace
|
||||||
namespace RakNet {
|
namespace RakNet {
|
||||||
//! Writes an AMFValue pointer to a RakNet::BitStream
|
//! Writes an AMFValue pointer to a RakNet::BitStream
|
||||||
/*!
|
/*!
|
||||||
\param value The value to write
|
\param value The value to write
|
||||||
*/
|
*/
|
||||||
template<>
|
template <>
|
||||||
void RakNet::BitStream::Write<AMFValue*>(AMFValue* value);
|
void RakNet::BitStream::Write<AMFValue*>(AMFValue* value);
|
||||||
|
|
||||||
//! Writes an AMFUndefinedValue to a RakNet::BitStream
|
//! Writes an AMFUndefinedValue to a RakNet::BitStream
|
||||||
/*!
|
/*!
|
||||||
\param value The value to write
|
\param value The value to write
|
||||||
*/
|
*/
|
||||||
template<>
|
template <>
|
||||||
void RakNet::BitStream::Write<AMFUndefinedValue>(AMFUndefinedValue value);
|
void RakNet::BitStream::Write<AMFUndefinedValue>(AMFUndefinedValue value);
|
||||||
|
|
||||||
//! Writes an AMFNullValue to a RakNet::BitStream
|
//! Writes an AMFNullValue to a RakNet::BitStream
|
||||||
/*!
|
/*!
|
||||||
\param value The value to write
|
\param value The value to write
|
||||||
*/
|
*/
|
||||||
template<>
|
template <>
|
||||||
void RakNet::BitStream::Write<AMFNullValue>(AMFNullValue value);
|
void RakNet::BitStream::Write<AMFNullValue>(AMFNullValue value);
|
||||||
|
|
||||||
//! Writes an AMFFalseValue to a RakNet::BitStream
|
//! Writes an AMFFalseValue to a RakNet::BitStream
|
||||||
/*!
|
/*!
|
||||||
\param value The value to write
|
\param value The value to write
|
||||||
*/
|
*/
|
||||||
template<>
|
template <>
|
||||||
void RakNet::BitStream::Write<AMFFalseValue>(AMFFalseValue value);
|
void RakNet::BitStream::Write<AMFFalseValue>(AMFFalseValue value);
|
||||||
|
|
||||||
//! Writes an AMFTrueValue to a RakNet::BitStream
|
//! Writes an AMFTrueValue to a RakNet::BitStream
|
||||||
/*!
|
/*!
|
||||||
\param value The value to write
|
\param value The value to write
|
||||||
*/
|
*/
|
||||||
template<>
|
template <>
|
||||||
void RakNet::BitStream::Write<AMFTrueValue>(AMFTrueValue value);
|
void RakNet::BitStream::Write<AMFTrueValue>(AMFTrueValue value);
|
||||||
|
|
||||||
//! Writes an AMFIntegerValue to a RakNet::BitStream
|
//! Writes an AMFIntegerValue to a RakNet::BitStream
|
||||||
/*!
|
/*!
|
||||||
\param value The value to write
|
\param value The value to write
|
||||||
*/
|
*/
|
||||||
template<>
|
template <>
|
||||||
void RakNet::BitStream::Write<AMFIntegerValue>(AMFIntegerValue value);
|
void RakNet::BitStream::Write<AMFIntegerValue>(AMFIntegerValue value);
|
||||||
|
|
||||||
//! Writes an AMFDoubleValue to a RakNet::BitStream
|
//! Writes an AMFDoubleValue to a RakNet::BitStream
|
||||||
/*!
|
/*!
|
||||||
\param value The value to write
|
\param value The value to write
|
||||||
*/
|
*/
|
||||||
template<>
|
template <>
|
||||||
void RakNet::BitStream::Write<AMFDoubleValue>(AMFDoubleValue value);
|
void RakNet::BitStream::Write<AMFDoubleValue>(AMFDoubleValue value);
|
||||||
|
|
||||||
//! Writes an AMFStringValue to a RakNet::BitStream
|
//! Writes an AMFStringValue to a RakNet::BitStream
|
||||||
/*!
|
/*!
|
||||||
\param value The value to write
|
\param value The value to write
|
||||||
*/
|
*/
|
||||||
template<>
|
template <>
|
||||||
void RakNet::BitStream::Write<AMFStringValue>(AMFStringValue value);
|
void RakNet::BitStream::Write<AMFStringValue>(AMFStringValue value);
|
||||||
|
|
||||||
//! Writes an AMFXMLDocValue to a RakNet::BitStream
|
//! Writes an AMFXMLDocValue to a RakNet::BitStream
|
||||||
/*!
|
/*!
|
||||||
\param value The value to write
|
\param value The value to write
|
||||||
*/
|
*/
|
||||||
template<>
|
template <>
|
||||||
void RakNet::BitStream::Write<AMFXMLDocValue>(AMFXMLDocValue value);
|
void RakNet::BitStream::Write<AMFXMLDocValue>(AMFXMLDocValue value);
|
||||||
|
|
||||||
//! Writes an AMFDateValue to a RakNet::BitStream
|
//! Writes an AMFDateValue to a RakNet::BitStream
|
||||||
/*!
|
/*!
|
||||||
\param value The value to write
|
\param value The value to write
|
||||||
*/
|
*/
|
||||||
template<>
|
template <>
|
||||||
void RakNet::BitStream::Write<AMFDateValue>(AMFDateValue value);
|
void RakNet::BitStream::Write<AMFDateValue>(AMFDateValue value);
|
||||||
|
|
||||||
//! Writes an AMFArrayValue to a RakNet::BitStream
|
//! Writes an AMFArrayValue to a RakNet::BitStream
|
||||||
/*!
|
/*!
|
||||||
\param value The value to write
|
\param value The value to write
|
||||||
*/
|
*/
|
||||||
template<>
|
template <>
|
||||||
void RakNet::BitStream::Write<AMFArrayValue>(AMFArrayValue value);
|
void RakNet::BitStream::Write<AMFArrayValue*>(AMFArrayValue* value);
|
||||||
}
|
} // namespace RakNet
|
||||||
|
@ -10,7 +10,7 @@ void BinaryIO::WriteString(const std::string& stringToWrite, std::ofstream& outs
|
|||||||
}
|
}
|
||||||
|
|
||||||
//For reading null-terminated strings
|
//For reading null-terminated strings
|
||||||
std::string BinaryIO::ReadString(std::ifstream & instream) {
|
std::string BinaryIO::ReadString(std::ifstream& instream) {
|
||||||
std::string toReturn;
|
std::string toReturn;
|
||||||
char buffer;
|
char buffer;
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ std::string BinaryIO::ReadString(std::ifstream& instream, size_t size) {
|
|||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string BinaryIO::ReadWString(std::ifstream & instream) {
|
std::string BinaryIO::ReadWString(std::ifstream& instream) {
|
||||||
size_t size;
|
size_t size;
|
||||||
BinaryRead(instream, size);
|
BinaryRead(instream, size);
|
||||||
//toReturn.resize(size);
|
//toReturn.resize(size);
|
||||||
|
@ -9,7 +9,7 @@ namespace BinaryIO {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::istream & BinaryRead(std::istream& stream, T& value) {
|
std::istream& BinaryRead(std::istream& stream, T& value) {
|
||||||
if (!stream.good())
|
if (!stream.good())
|
||||||
printf("bla");
|
printf("bla");
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ namespace BinaryIO {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WriteString(const std::string& stringToWrite, std::ofstream& outstream);
|
void WriteString(const std::string& stringToWrite, std::ofstream& outstream);
|
||||||
std::string ReadString(std::ifstream & instream);
|
std::string ReadString(std::ifstream& instream);
|
||||||
std::string ReadString(std::ifstream& instream, size_t size);
|
std::string ReadString(std::ifstream& instream, size_t size);
|
||||||
std::string ReadWString(std::ifstream& instream);
|
std::string ReadWString(std::ifstream& instream);
|
||||||
|
|
||||||
|
180
dCommon/BrickByBrickFix.cpp
Normal file
180
dCommon/BrickByBrickFix.cpp
Normal 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
26
dCommon/BrickByBrickFix.h
Normal 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;
|
||||||
|
};
|
@ -1,4 +1,5 @@
|
|||||||
set(DCOMMON_SOURCES "AMFFormat.cpp"
|
set(DCOMMON_SOURCES "AMFFormat.cpp"
|
||||||
|
"AMFDeserialize.cpp"
|
||||||
"AMFFormat_BitStream.cpp"
|
"AMFFormat_BitStream.cpp"
|
||||||
"BinaryIO.cpp"
|
"BinaryIO.cpp"
|
||||||
"dConfig.cpp"
|
"dConfig.cpp"
|
||||||
@ -12,15 +13,43 @@ set(DCOMMON_SOURCES "AMFFormat.cpp"
|
|||||||
"NiQuaternion.cpp"
|
"NiQuaternion.cpp"
|
||||||
"SHA512.cpp"
|
"SHA512.cpp"
|
||||||
"Type.cpp"
|
"Type.cpp"
|
||||||
"ZCompression.cpp")
|
"ZCompression.cpp"
|
||||||
|
"BrickByBrickFix.cpp"
|
||||||
|
)
|
||||||
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/dCommon/)
|
include_directories(${PROJECT_SOURCE_DIR}/dCommon/)
|
||||||
|
|
||||||
add_library(dCommon STATIC ${DCOMMON_SOURCES})
|
add_library(dCommon STATIC ${DCOMMON_SOURCES})
|
||||||
|
|
||||||
target_link_libraries(dCommon libbcrypt)
|
target_link_libraries(dCommon bcrypt dDatabase tinyxml2)
|
||||||
|
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
find_package(ZLIB REQUIRED)
|
find_package(ZLIB REQUIRED)
|
||||||
target_link_libraries(dCommon ZLIB::ZLIB)
|
elseif (WIN32)
|
||||||
endif()
|
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)
|
||||||
|
@ -142,12 +142,12 @@ void CatchUnhandled(int sig) {
|
|||||||
demangled = demangle(functionName.c_str());
|
demangled = demangle(functionName.c_str());
|
||||||
|
|
||||||
if (demangled.empty()) {
|
if (demangled.empty()) {
|
||||||
printf("[%02d] %s\n", i, demangled.c_str());
|
printf("[%02zu] %s\n", i, demangled.c_str());
|
||||||
} else {
|
} else {
|
||||||
printf("[%02d] %s\n", i, functionName.c_str());
|
printf("[%02zu] %s\n", i, functionName.c_str());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printf("[%02d] %s\n", i, functionName.c_str());
|
printf("[%02zu] %s\n", i, functionName.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@ -171,10 +171,7 @@ void CatchUnhandled(int sig) {
|
|||||||
ErrorCallback,
|
ErrorCallback,
|
||||||
nullptr);
|
nullptr);
|
||||||
|
|
||||||
// Print error code
|
struct bt_ctx ctx = { state, 0 };
|
||||||
printf("Error code: %d\n", sig);
|
|
||||||
|
|
||||||
struct bt_ctx ctx = {state, 0};
|
|
||||||
Bt(state);
|
Bt(state);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline size_t MinSize(size_t size, const std::basic_string<T>& string) {
|
inline size_t MinSize(size_t size, const std::basic_string_view<T>& string) {
|
||||||
if (size == size_t(-1) || size > string.size()) {
|
if (size == size_t(-1) || size > string.size()) {
|
||||||
return string.size();
|
return string.size();
|
||||||
} else {
|
} else {
|
||||||
@ -24,7 +24,7 @@ inline bool IsTrailSurrogate(char16_t c) {
|
|||||||
|
|
||||||
inline void PushUTF8CodePoint(std::string& ret, char32_t cp) {
|
inline void PushUTF8CodePoint(std::string& ret, char32_t cp) {
|
||||||
if (cp <= 0x007F) {
|
if (cp <= 0x007F) {
|
||||||
ret.push_back(cp);
|
ret.push_back(static_cast<uint8_t>(cp));
|
||||||
} else if (cp <= 0x07FF) {
|
} else if (cp <= 0x07FF) {
|
||||||
ret.push_back(0xC0 | (cp >> 6));
|
ret.push_back(0xC0 | (cp >> 6));
|
||||||
ret.push_back(0x80 | (cp & 0x3F));
|
ret.push_back(0x80 | (cp & 0x3F));
|
||||||
@ -42,16 +42,123 @@ inline void PushUTF8CodePoint(std::string& ret, char32_t cp) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr const char16_t REPLACEMENT_CHARACTER = 0xFFFD;
|
||||||
|
|
||||||
|
bool _IsSuffixChar(uint8_t c) {
|
||||||
|
return (c & 0xC0) == 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GeneralUtils::_NextUTF8Char(std::string_view& slice, uint32_t& out) {
|
||||||
|
size_t rem = slice.length();
|
||||||
|
const uint8_t* bytes = (const uint8_t*)&slice.front();
|
||||||
|
if (rem > 0) {
|
||||||
|
uint8_t first = bytes[0];
|
||||||
|
if (first < 0x80) { // 1 byte character
|
||||||
|
out = static_cast<uint32_t>(first & 0x7F);
|
||||||
|
slice.remove_prefix(1);
|
||||||
|
return true;
|
||||||
|
} else if (first < 0xC0) {
|
||||||
|
// middle byte, not valid at start, fall through
|
||||||
|
} else if (first < 0xE0) { // two byte character
|
||||||
|
if (rem > 1) {
|
||||||
|
uint8_t second = bytes[1];
|
||||||
|
if (_IsSuffixChar(second)) {
|
||||||
|
out = (static_cast<uint32_t>(first & 0x1F) << 6)
|
||||||
|
+ static_cast<uint32_t>(second & 0x3F);
|
||||||
|
slice.remove_prefix(2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (first < 0xF0) { // three byte character
|
||||||
|
if (rem > 2) {
|
||||||
|
uint8_t second = bytes[1];
|
||||||
|
uint8_t third = bytes[2];
|
||||||
|
if (_IsSuffixChar(second) && _IsSuffixChar(third)) {
|
||||||
|
out = (static_cast<uint32_t>(first & 0x0F) << 12)
|
||||||
|
+ (static_cast<uint32_t>(second & 0x3F) << 6)
|
||||||
|
+ static_cast<uint32_t>(third & 0x3F);
|
||||||
|
slice.remove_prefix(3);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (first < 0xF8) { // four byte character
|
||||||
|
if (rem > 3) {
|
||||||
|
uint8_t second = bytes[1];
|
||||||
|
uint8_t third = bytes[2];
|
||||||
|
uint8_t fourth = bytes[3];
|
||||||
|
if (_IsSuffixChar(second) && _IsSuffixChar(third) && _IsSuffixChar(fourth)) {
|
||||||
|
out = (static_cast<uint32_t>(first & 0x07) << 18)
|
||||||
|
+ (static_cast<uint32_t>(second & 0x3F) << 12)
|
||||||
|
+ (static_cast<uint32_t>(third & 0x3F) << 6)
|
||||||
|
+ static_cast<uint32_t>(fourth & 0x3F);
|
||||||
|
slice.remove_prefix(4);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out = static_cast<uint32_t>(REPLACEMENT_CHARACTER);
|
||||||
|
slice.remove_prefix(1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See <https://www.ietf.org/rfc/rfc2781.html#section-2.1>
|
||||||
|
bool PushUTF16CodePoint(std::u16string& output, uint32_t U, size_t size) {
|
||||||
|
if (output.length() >= size) return false;
|
||||||
|
if (U < 0x10000) {
|
||||||
|
// If U < 0x10000, encode U as a 16-bit unsigned integer and terminate.
|
||||||
|
output.push_back(static_cast<uint16_t>(U));
|
||||||
|
return true;
|
||||||
|
} else if (U > 0x10FFFF) {
|
||||||
|
output.push_back(REPLACEMENT_CHARACTER);
|
||||||
|
return true;
|
||||||
|
} else if (output.length() + 1 < size) {
|
||||||
|
// Let U' = U - 0x10000. Because U is less than or equal to 0x10FFFF,
|
||||||
|
// U' must be less than or equal to 0xFFFFF. That is, U' can be
|
||||||
|
// represented in 20 bits.
|
||||||
|
uint32_t Ut = U - 0x10000;
|
||||||
|
|
||||||
|
// Initialize two 16-bit unsigned integers, W1 and W2, to 0xD800 and
|
||||||
|
// 0xDC00, respectively. These integers each have 10 bits free to
|
||||||
|
// encode the character value, for a total of 20 bits.
|
||||||
|
uint16_t W1 = 0xD800;
|
||||||
|
uint16_t W2 = 0xDC00;
|
||||||
|
|
||||||
|
// Assign the 10 high-order bits of the 20-bit U' to the 10 low-order
|
||||||
|
// bits of W1 and the 10 low-order bits of U' to the 10 low-order
|
||||||
|
// bits of W2.
|
||||||
|
W1 += static_cast<uint16_t>((Ut & 0x3FC00) >> 10);
|
||||||
|
W2 += static_cast<uint16_t>((Ut & 0x3FF) >> 0);
|
||||||
|
|
||||||
|
// Terminate.
|
||||||
|
output.push_back(W1); // high surrogate
|
||||||
|
output.push_back(W2); // low surrogate
|
||||||
|
return true;
|
||||||
|
} else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::u16string GeneralUtils::UTF8ToUTF16(const std::string_view& string, size_t size) {
|
||||||
|
size_t newSize = MinSize(size, string);
|
||||||
|
std::u16string output;
|
||||||
|
output.reserve(newSize);
|
||||||
|
std::string_view iterator = string;
|
||||||
|
|
||||||
|
uint32_t c;
|
||||||
|
while (_NextUTF8Char(iterator, c) && PushUTF16CodePoint(output, c, size)) {}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
//! Converts an std::string (ASCII) to UCS-2 / UTF-16
|
//! Converts an std::string (ASCII) to UCS-2 / UTF-16
|
||||||
std::u16string GeneralUtils::ASCIIToUTF16(const std::string& string, size_t size) {
|
std::u16string GeneralUtils::ASCIIToUTF16(const std::string_view& string, size_t size) {
|
||||||
size_t newSize = MinSize(size, string);
|
size_t newSize = MinSize(size, string);
|
||||||
std::u16string ret;
|
std::u16string ret;
|
||||||
ret.reserve(newSize);
|
ret.reserve(newSize);
|
||||||
|
|
||||||
for (size_t i = 0; i < newSize; i++) {
|
for (size_t i = 0; i < newSize; i++) {
|
||||||
char c = string[i];
|
char c = string[i];
|
||||||
assert(c > 0 && c <= 127);
|
// Note: both 7-bit ascii characters and REPLACEMENT_CHARACTER fit in one char16_t
|
||||||
ret.push_back(static_cast<char16_t>(c));
|
ret.push_back((c > 0 && c <= 127) ? static_cast<char16_t>(c) : REPLACEMENT_CHARACTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -59,7 +166,7 @@ std::u16string GeneralUtils::ASCIIToUTF16(const std::string& string, size_t size
|
|||||||
|
|
||||||
//! Converts a (potentially-ill-formed) UTF-16 string to UTF-8
|
//! Converts a (potentially-ill-formed) UTF-16 string to UTF-8
|
||||||
//! See: <http://simonsapin.github.io/wtf-8/#decoding-ill-formed-utf-16>
|
//! See: <http://simonsapin.github.io/wtf-8/#decoding-ill-formed-utf-16>
|
||||||
std::string GeneralUtils::UTF16ToWTF8(const std::u16string& string, size_t size) {
|
std::string GeneralUtils::UTF16ToWTF8(const std::u16string_view& string, size_t size) {
|
||||||
size_t newSize = MinSize(size, string);
|
size_t newSize = MinSize(size, string);
|
||||||
std::string ret;
|
std::string ret;
|
||||||
ret.reserve(newSize);
|
ret.reserve(newSize);
|
||||||
@ -86,7 +193,7 @@ std::string GeneralUtils::UTF16ToWTF8(const std::u16string& string, size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool GeneralUtils::CaseInsensitiveStringCompare(const std::string& a, const std::string& b) {
|
bool GeneralUtils::CaseInsensitiveStringCompare(const std::string& a, const std::string& b) {
|
||||||
return std::equal(a.begin(), a.end (), b.begin(), b.end(),[](char a, char b) { return tolower(a) == tolower(b); });
|
return std::equal(a.begin(), a.end(), b.begin(), b.end(), [](char a, char b) { return tolower(a) == tolower(b); });
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Bits
|
// MARK: Bits
|
||||||
@ -108,14 +215,13 @@ bool GeneralUtils::CheckBit(int64_t value, uint32_t index) {
|
|||||||
|
|
||||||
bool GeneralUtils::ReplaceInString(std::string& str, const std::string& from, const std::string& to) {
|
bool GeneralUtils::ReplaceInString(std::string& str, const std::string& from, const std::string& to) {
|
||||||
size_t start_pos = str.find(from);
|
size_t start_pos = str.find(from);
|
||||||
if(start_pos == std::string::npos)
|
if (start_pos == std::string::npos)
|
||||||
return false;
|
return false;
|
||||||
str.replace(start_pos, from.length(), to);
|
str.replace(start_pos, from.length(), to);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::wstring> GeneralUtils::SplitString(std::wstring& str, wchar_t delimiter)
|
std::vector<std::wstring> GeneralUtils::SplitString(std::wstring& str, wchar_t delimiter) {
|
||||||
{
|
|
||||||
std::vector<std::wstring> vector = std::vector<std::wstring>();
|
std::vector<std::wstring> vector = std::vector<std::wstring>();
|
||||||
std::wstring current;
|
std::wstring current;
|
||||||
|
|
||||||
@ -132,8 +238,7 @@ std::vector<std::wstring> GeneralUtils::SplitString(std::wstring& str, wchar_t d
|
|||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::u16string> GeneralUtils::SplitString(std::u16string& str, char16_t delimiter)
|
std::vector<std::u16string> GeneralUtils::SplitString(std::u16string& str, char16_t delimiter) {
|
||||||
{
|
|
||||||
std::vector<std::u16string> vector = std::vector<std::u16string>();
|
std::vector<std::u16string> vector = std::vector<std::u16string>();
|
||||||
std::u16string current;
|
std::u16string current;
|
||||||
|
|
||||||
@ -150,22 +255,17 @@ std::vector<std::u16string> GeneralUtils::SplitString(std::u16string& str, char1
|
|||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> GeneralUtils::SplitString(const std::string& str, char delimiter)
|
std::vector<std::string> GeneralUtils::SplitString(const std::string& str, char delimiter) {
|
||||||
{
|
|
||||||
std::vector<std::string> vector = std::vector<std::string>();
|
std::vector<std::string> vector = std::vector<std::string>();
|
||||||
std::string current = "";
|
std::string current = "";
|
||||||
|
|
||||||
for (size_t i = 0; i < str.length(); i++)
|
for (size_t i = 0; i < str.length(); i++) {
|
||||||
{
|
|
||||||
char c = str[i];
|
char c = str[i];
|
||||||
|
|
||||||
if (c == delimiter)
|
if (c == delimiter) {
|
||||||
{
|
|
||||||
vector.push_back(current);
|
vector.push_back(current);
|
||||||
current = "";
|
current = "";
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
current += c;
|
current += c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -175,7 +275,7 @@ std::vector<std::string> GeneralUtils::SplitString(const std::string& str, char
|
|||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::u16string GeneralUtils::ReadWString(RakNet::BitStream *inStream) {
|
std::u16string GeneralUtils::ReadWString(RakNet::BitStream* inStream) {
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
inStream->Read<uint32_t>(length);
|
inStream->Read<uint32_t>(length);
|
||||||
|
|
||||||
@ -193,8 +293,7 @@ std::u16string GeneralUtils::ReadWString(RakNet::BitStream *inStream) {
|
|||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
std::vector<std::string> GeneralUtils::GetFileNamesFromFolder(const std::string& folder)
|
std::vector<std::string> GeneralUtils::GetFileNamesFromFolder(const std::string& folder) {
|
||||||
{
|
|
||||||
std::vector<std::string> names;
|
std::vector<std::string> names;
|
||||||
std::string search_path = folder + "/*.*";
|
std::string search_path = folder + "/*.*";
|
||||||
WIN32_FIND_DATA fd;
|
WIN32_FIND_DATA fd;
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
\brief A namespace containing general utility functions
|
\brief A namespace containing general utility functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! The general utils namespace
|
//! The general utils namespace
|
||||||
namespace GeneralUtils {
|
namespace GeneralUtils {
|
||||||
//! Converts a plain ASCII string to a UTF-16 string
|
//! Converts a plain ASCII string to a UTF-16 string
|
||||||
/*!
|
/*!
|
||||||
@ -26,7 +26,18 @@ namespace GeneralUtils {
|
|||||||
\param size A size to trim the string to. Default is -1 (No trimming)
|
\param size A size to trim the string to. Default is -1 (No trimming)
|
||||||
\return An UTF-16 representation of the string
|
\return An UTF-16 representation of the string
|
||||||
*/
|
*/
|
||||||
std::u16string ASCIIToUTF16(const std::string& string, size_t size = -1);
|
std::u16string ASCIIToUTF16(const std::string_view& string, size_t size = -1);
|
||||||
|
|
||||||
|
//! Converts a UTF-8 String to a UTF-16 string
|
||||||
|
/*!
|
||||||
|
\param string The string to convert
|
||||||
|
\param size A size to trim the string to. Default is -1 (No trimming)
|
||||||
|
\return An UTF-16 representation of the string
|
||||||
|
*/
|
||||||
|
std::u16string UTF8ToUTF16(const std::string_view& string, size_t size = -1);
|
||||||
|
|
||||||
|
//! Internal, do not use
|
||||||
|
bool _NextUTF8Char(std::string_view& slice, uint32_t& out);
|
||||||
|
|
||||||
//! Converts a UTF-16 string to a UTF-8 string
|
//! Converts a UTF-16 string to a UTF-8 string
|
||||||
/*!
|
/*!
|
||||||
@ -34,7 +45,7 @@ namespace GeneralUtils {
|
|||||||
\param size A size to trim the string to. Default is -1 (No trimming)
|
\param size A size to trim the string to. Default is -1 (No trimming)
|
||||||
\return An UTF-8 representation of the string
|
\return An UTF-8 representation of the string
|
||||||
*/
|
*/
|
||||||
std::string UTF16ToWTF8(const std::u16string& string, size_t size = -1);
|
std::string UTF16ToWTF8(const std::u16string_view& string, size_t size = -1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compares two basic strings but does so ignoring case sensitivity
|
* Compares two basic strings but does so ignoring case sensitivity
|
||||||
@ -109,8 +120,7 @@ namespace GeneralUtils {
|
|||||||
if constexpr (std::is_integral_v<T>) { // constexpr only necessary on first statement
|
if constexpr (std::is_integral_v<T>) { // constexpr only necessary on first statement
|
||||||
std::uniform_int_distribution<T> distribution(min, max);
|
std::uniform_int_distribution<T> distribution(min, max);
|
||||||
return distribution(Game::randomEngine);
|
return distribution(Game::randomEngine);
|
||||||
}
|
} else if (std::is_floating_point_v<T>) {
|
||||||
else if (std::is_floating_point_v<T>) {
|
|
||||||
std::uniform_real_distribution<T> distribution(min, max);
|
std::uniform_real_distribution<T> distribution(min, max);
|
||||||
return distribution(Game::randomEngine);
|
return distribution(Game::randomEngine);
|
||||||
}
|
}
|
||||||
@ -120,7 +130,7 @@ namespace GeneralUtils {
|
|||||||
|
|
||||||
bool ReplaceInString(std::string& str, const std::string& from, const std::string& to);
|
bool ReplaceInString(std::string& str, const std::string& from, const std::string& to);
|
||||||
|
|
||||||
std::u16string ReadWString(RakNet::BitStream *inStream);
|
std::u16string ReadWString(RakNet::BitStream* inStream);
|
||||||
|
|
||||||
std::vector<std::wstring> SplitString(std::wstring& str, wchar_t delimiter);
|
std::vector<std::wstring> SplitString(std::wstring& str, wchar_t delimiter);
|
||||||
|
|
||||||
@ -134,78 +144,64 @@ namespace GeneralUtils {
|
|||||||
T Parse(const char* value);
|
T Parse(const char* value);
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline int32_t Parse(const char* value)
|
inline int32_t Parse(const char* value) {
|
||||||
{
|
|
||||||
return std::stoi(value);
|
return std::stoi(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline int64_t Parse(const char* value)
|
inline int64_t Parse(const char* value) {
|
||||||
{
|
|
||||||
return std::stoll(value);
|
return std::stoll(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline float Parse(const char* value)
|
inline float Parse(const char* value) {
|
||||||
{
|
|
||||||
return std::stof(value);
|
return std::stof(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline double Parse(const char* value)
|
inline double Parse(const char* value) {
|
||||||
{
|
|
||||||
return std::stod(value);
|
return std::stod(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline uint32_t Parse(const char* value)
|
inline uint32_t Parse(const char* value) {
|
||||||
{
|
|
||||||
return std::stoul(value);
|
return std::stoul(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline uint64_t Parse(const char* value)
|
inline uint64_t Parse(const char* value) {
|
||||||
{
|
|
||||||
return std::stoull(value);
|
return std::stoull(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool TryParse(const char* value, T& dst)
|
bool TryParse(const char* value, T& dst) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
dst = Parse<T>(value);
|
dst = Parse<T>(value);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
} catch (...) {
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T Parse(const std::string& value)
|
T Parse(const std::string& value) {
|
||||||
{
|
|
||||||
return Parse<T>(value.c_str());
|
return Parse<T>(value.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool TryParse(const std::string& value, T& dst)
|
bool TryParse(const std::string& value, T& dst) {
|
||||||
{
|
|
||||||
return TryParse<T>(value.c_str(), dst);
|
return TryParse<T>(value.c_str(), dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::u16string to_u16string(T value)
|
std::u16string to_u16string(T value) {
|
||||||
{
|
|
||||||
return GeneralUtils::ASCIIToUTF16(std::to_string(value));
|
return GeneralUtils::ASCIIToUTF16(std::to_string(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
// From boost::hash_combine
|
// From boost::hash_combine
|
||||||
template <class T>
|
template <class T>
|
||||||
void hash_combine(std::size_t& s, const T& v)
|
void hash_combine(std::size_t& s, const T& v) {
|
||||||
{
|
|
||||||
std::hash<T> h;
|
std::hash<T> h;
|
||||||
s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2);
|
s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
//! Returns a pointer to a LDFData value based on string format
|
//! Returns a pointer to a LDFData value based on string format
|
||||||
LDFBaseData * LDFBaseData::DataFromString(const std::string& format) {
|
LDFBaseData* LDFBaseData::DataFromString(const std::string& format) {
|
||||||
|
|
||||||
// First, check the format
|
// First, check the format
|
||||||
std::istringstream ssFormat(format);
|
std::istringstream ssFormat(format);
|
||||||
@ -49,7 +49,7 @@ LDFBaseData * LDFBaseData::DataFromString(const std::string& format) {
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case LDF_TYPE_UTF_16: {
|
case LDF_TYPE_UTF_16: {
|
||||||
std::u16string data = GeneralUtils::ASCIIToUTF16(dataArray[1]);
|
std::u16string data = GeneralUtils::UTF8ToUTF16(dataArray[1]);
|
||||||
return new LDFData<std::u16string>(key, data);
|
return new LDFData<std::u16string>(key, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,16 +72,11 @@ LDFBaseData * LDFBaseData::DataFromString(const std::string& format) {
|
|||||||
{
|
{
|
||||||
uint32_t data;
|
uint32_t data;
|
||||||
|
|
||||||
if (dataArray[1] == "true")
|
if (dataArray[1] == "true") {
|
||||||
{
|
|
||||||
data = 1;
|
data = 1;
|
||||||
}
|
} else if (dataArray[1] == "false") {
|
||||||
else if (dataArray[1] == "false")
|
|
||||||
{
|
|
||||||
data = 0;
|
data = 0;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
data = static_cast<uint32_t>(stoul(dataArray[1]));
|
data = static_cast<uint32_t>(stoul(dataArray[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,16 +86,11 @@ LDFBaseData * LDFBaseData::DataFromString(const std::string& format) {
|
|||||||
case LDF_TYPE_BOOLEAN: {
|
case LDF_TYPE_BOOLEAN: {
|
||||||
bool data;
|
bool data;
|
||||||
|
|
||||||
if (dataArray[1] == "true")
|
if (dataArray[1] == "true") {
|
||||||
{
|
|
||||||
data = true;
|
data = true;
|
||||||
}
|
} else if (dataArray[1] == "false") {
|
||||||
else if (dataArray[1] == "false")
|
|
||||||
{
|
|
||||||
data = false;
|
data = false;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
data = static_cast<bool>(stoi(dataArray[1]));
|
data = static_cast<bool>(stoi(dataArray[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
\brief A collection of LDF format classes
|
\brief A collection of LDF format classes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! An enum for LDF Data Types
|
//! An enum for LDF Data Types
|
||||||
enum eLDFType {
|
enum eLDFType {
|
||||||
LDF_TYPE_UNKNOWN = -1, //!< Unknown data type
|
LDF_TYPE_UNKNOWN = -1, //!< Unknown data type
|
||||||
LDF_TYPE_UTF_16 = 0, //!< UTF-16 wstring data type
|
LDF_TYPE_UTF_16 = 0, //!< UTF-16 wstring data type
|
||||||
@ -36,13 +36,13 @@ class LDFBaseData {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
virtual ~LDFBaseData(void) { }
|
virtual ~LDFBaseData(void) {}
|
||||||
|
|
||||||
//! Writes the data to a packet
|
//! Writes the data to a packet
|
||||||
/*!
|
/*!
|
||||||
\param packet The packet
|
\param packet The packet
|
||||||
*/
|
*/
|
||||||
virtual void WriteToPacket(RakNet::BitStream * packet) = 0;
|
virtual void WriteToPacket(RakNet::BitStream* packet) = 0;
|
||||||
|
|
||||||
//! Gets the key
|
//! Gets the key
|
||||||
/*!
|
/*!
|
||||||
@ -66,7 +66,7 @@ public:
|
|||||||
|
|
||||||
virtual std::string GetValueAsString() = 0;
|
virtual std::string GetValueAsString() = 0;
|
||||||
|
|
||||||
virtual LDFBaseData * Copy() = 0;
|
virtual LDFBaseData* Copy() = 0;
|
||||||
|
|
||||||
// MARK: Functions
|
// MARK: Functions
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
\param format The format
|
\param format The format
|
||||||
*/
|
*/
|
||||||
static LDFBaseData * DataFromString(const std::string& format);
|
static LDFBaseData* DataFromString(const std::string& format);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ private:
|
|||||||
T value;
|
T value;
|
||||||
|
|
||||||
//! Writes the key to the packet
|
//! Writes the key to the packet
|
||||||
void WriteKey(RakNet::BitStream * packet) {
|
void WriteKey(RakNet::BitStream* packet) {
|
||||||
packet->Write(static_cast<uint8_t>(this->key.length() * sizeof(uint16_t)));
|
packet->Write(static_cast<uint8_t>(this->key.length() * sizeof(uint16_t)));
|
||||||
for (uint32_t i = 0; i < this->key.length(); ++i) {
|
for (uint32_t i = 0; i < this->key.length(); ++i) {
|
||||||
packet->Write(static_cast<uint16_t>(this->key[i]));
|
packet->Write(static_cast<uint16_t>(this->key[i]));
|
||||||
@ -94,7 +94,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Writes the value to the packet
|
//! Writes the value to the packet
|
||||||
void WriteValue(RakNet::BitStream * packet) {
|
void WriteValue(RakNet::BitStream* packet) {
|
||||||
packet->Write(static_cast<uint8_t>(this->GetValueType()));
|
packet->Write(static_cast<uint8_t>(this->GetValueType()));
|
||||||
packet->Write(this->value);
|
packet->Write(this->value);
|
||||||
}
|
}
|
||||||
@ -108,7 +108,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
~LDFData(void) override { }
|
~LDFData(void) override {}
|
||||||
|
|
||||||
//! Gets the value
|
//! Gets the value
|
||||||
/*!
|
/*!
|
||||||
@ -132,7 +132,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
\param packet The packet
|
\param packet The packet
|
||||||
*/
|
*/
|
||||||
void WriteToPacket(RakNet::BitStream * packet) override {
|
void WriteToPacket(RakNet::BitStream* packet) override {
|
||||||
this->WriteKey(packet);
|
this->WriteKey(packet);
|
||||||
this->WriteValue(packet);
|
this->WriteValue(packet);
|
||||||
}
|
}
|
||||||
@ -186,7 +186,7 @@ public:
|
|||||||
return this->GetValueString();
|
return this->GetValueString();
|
||||||
}
|
}
|
||||||
|
|
||||||
LDFBaseData * Copy() override {
|
LDFBaseData* Copy() override {
|
||||||
return new LDFData<T>(key, value);
|
return new LDFData<T>(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,7 +206,7 @@ template<> inline eLDFType LDFData<std::string>::GetValueType(void) { return LDF
|
|||||||
|
|
||||||
// The specialized version for std::u16string (UTF-16)
|
// The specialized version for std::u16string (UTF-16)
|
||||||
template<>
|
template<>
|
||||||
inline void LDFData<std::u16string>::WriteValue(RakNet::BitStream * packet) {
|
inline void LDFData<std::u16string>::WriteValue(RakNet::BitStream* packet) {
|
||||||
packet->Write(static_cast<uint8_t>(this->GetValueType()));
|
packet->Write(static_cast<uint8_t>(this->GetValueType()));
|
||||||
|
|
||||||
packet->Write(static_cast<uint32_t>(this->value.length()));
|
packet->Write(static_cast<uint32_t>(this->value.length()));
|
||||||
@ -217,7 +217,7 @@ inline void LDFData<std::u16string>::WriteValue(RakNet::BitStream * packet) {
|
|||||||
|
|
||||||
// The specialized version for bool
|
// The specialized version for bool
|
||||||
template<>
|
template<>
|
||||||
inline void LDFData<bool>::WriteValue(RakNet::BitStream * packet) {
|
inline void LDFData<bool>::WriteValue(RakNet::BitStream* packet) {
|
||||||
packet->Write(static_cast<uint8_t>(this->GetValueType()));
|
packet->Write(static_cast<uint8_t>(this->GetValueType()));
|
||||||
|
|
||||||
packet->Write(static_cast<uint8_t>(this->value));
|
packet->Write(static_cast<uint8_t>(this->value));
|
||||||
@ -225,7 +225,7 @@ inline void LDFData<bool>::WriteValue(RakNet::BitStream * packet) {
|
|||||||
|
|
||||||
// The specialized version for std::string (UTF-8)
|
// The specialized version for std::string (UTF-8)
|
||||||
template<>
|
template<>
|
||||||
inline void LDFData<std::string>::WriteValue(RakNet::BitStream * packet) {
|
inline void LDFData<std::string>::WriteValue(RakNet::BitStream* packet) {
|
||||||
packet->Write(static_cast<uint8_t>(this->GetValueType()));
|
packet->Write(static_cast<uint8_t>(this->GetValueType()));
|
||||||
|
|
||||||
packet->Write(static_cast<uint32_t>(this->value.length()));
|
packet->Write(static_cast<uint32_t>(this->value.length()));
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* interface header */
|
/* interface header */
|
||||||
#include "MD5.h"
|
#include "MD5.h"
|
||||||
|
|
||||||
/* system implementation headers */
|
/* system implementation headers */
|
||||||
@ -59,15 +59,15 @@
|
|||||||
|
|
||||||
// F, G, H and I are basic MD5 functions.
|
// F, G, H and I are basic MD5 functions.
|
||||||
inline MD5::uint4 MD5::F(uint4 x, uint4 y, uint4 z) {
|
inline MD5::uint4 MD5::F(uint4 x, uint4 y, uint4 z) {
|
||||||
return x&y | ~x&z;
|
return x & y | ~x & z;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline MD5::uint4 MD5::G(uint4 x, uint4 y, uint4 z) {
|
inline MD5::uint4 MD5::G(uint4 x, uint4 y, uint4 z) {
|
||||||
return x&z | y&~z;
|
return x & z | y & ~z;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z) {
|
inline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z) {
|
||||||
return x^y^z;
|
return x ^ y ^ z;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline MD5::uint4 MD5::I(uint4 x, uint4 y, uint4 z) {
|
inline MD5::uint4 MD5::I(uint4 x, uint4 y, uint4 z) {
|
||||||
@ -81,35 +81,33 @@ inline MD5::uint4 MD5::rotate_left(uint4 x, int n) {
|
|||||||
|
|
||||||
// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
|
// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
|
||||||
// Rotation is separate from addition to prevent recomputation.
|
// Rotation is separate from addition to prevent recomputation.
|
||||||
inline void MD5::FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
|
inline void MD5::FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
|
||||||
a = rotate_left(a + F(b, c, d) + x + ac, s) + b;
|
a = rotate_left(a + F(b, c, d) + x + ac, s) + b;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void MD5::GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
|
inline void MD5::GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
|
||||||
a = rotate_left(a + G(b, c, d) + x + ac, s) + b;
|
a = rotate_left(a + G(b, c, d) + x + ac, s) + b;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void MD5::HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
|
inline void MD5::HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
|
||||||
a = rotate_left(a + H(b, c, d) + x + ac, s) + b;
|
a = rotate_left(a + H(b, c, d) + x + ac, s) + b;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void MD5::II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
|
inline void MD5::II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
|
||||||
a = rotate_left(a + I(b, c, d) + x + ac, s) + b;
|
a = rotate_left(a + I(b, c, d) + x + ac, s) + b;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
//////////////////////////////////////////////
|
||||||
|
|
||||||
// default ctor, just initailize
|
// default ctor, just initailize
|
||||||
MD5::MD5()
|
MD5::MD5() {
|
||||||
{
|
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
//////////////////////////////////////////////
|
||||||
|
|
||||||
// nifty shortcut ctor, compute MD5 for string and finalize it right away
|
// nifty shortcut ctor, compute MD5 for string and finalize it right away
|
||||||
MD5::MD5(const std::string &text)
|
MD5::MD5(const std::string& text) {
|
||||||
{
|
|
||||||
init();
|
init();
|
||||||
update(text.c_str(), text.length());
|
update(text.c_str(), text.length());
|
||||||
finalize();
|
finalize();
|
||||||
@ -117,8 +115,7 @@ MD5::MD5(const std::string &text)
|
|||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
|
|
||||||
void MD5::init()
|
void MD5::init() {
|
||||||
{
|
|
||||||
finalized = false;
|
finalized = false;
|
||||||
|
|
||||||
count[0] = 0;
|
count[0] = 0;
|
||||||
@ -134,8 +131,7 @@ void MD5::init()
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
|
|
||||||
// decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4.
|
// decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4.
|
||||||
void MD5::decode(uint4 output[], const uint1 input[], size_type len)
|
void MD5::decode(uint4 output[], const uint1 input[], size_type len) {
|
||||||
{
|
|
||||||
for (unsigned int i = 0, j = 0; j < len; i++, j += 4)
|
for (unsigned int i = 0, j = 0; j < len; i++, j += 4)
|
||||||
output[i] = ((uint4)input[j]) | (((uint4)input[j + 1]) << 8) |
|
output[i] = ((uint4)input[j]) | (((uint4)input[j + 1]) << 8) |
|
||||||
(((uint4)input[j + 2]) << 16) | (((uint4)input[j + 3]) << 24);
|
(((uint4)input[j + 2]) << 16) | (((uint4)input[j + 3]) << 24);
|
||||||
@ -145,8 +141,7 @@ void MD5::decode(uint4 output[], const uint1 input[], size_type len)
|
|||||||
|
|
||||||
// encodes input (uint4) into output (unsigned char). Assumes len is
|
// encodes input (uint4) into output (unsigned char). Assumes len is
|
||||||
// a multiple of 4.
|
// a multiple of 4.
|
||||||
void MD5::encode(uint1 output[], const uint4 input[], size_type len)
|
void MD5::encode(uint1 output[], const uint4 input[], size_type len) {
|
||||||
{
|
|
||||||
for (size_type i = 0, j = 0; j < len; i++, j += 4) {
|
for (size_type i = 0, j = 0; j < len; i++, j += 4) {
|
||||||
output[j] = input[i] & 0xff;
|
output[j] = input[i] & 0xff;
|
||||||
output[j + 1] = (input[i] >> 8) & 0xff;
|
output[j + 1] = (input[i] >> 8) & 0xff;
|
||||||
@ -158,8 +153,7 @@ void MD5::encode(uint1 output[], const uint4 input[], size_type len)
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
|
|
||||||
// apply MD5 algo on a block
|
// apply MD5 algo on a block
|
||||||
void MD5::transform(const uint1 block[blocksize])
|
void MD5::transform(const uint1 block[blocksize]) {
|
||||||
{
|
|
||||||
uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
|
uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
|
||||||
decode(x, block, blocksize);
|
decode(x, block, blocksize);
|
||||||
|
|
||||||
@ -248,8 +242,7 @@ void MD5::transform(const uint1 block[blocksize])
|
|||||||
|
|
||||||
// MD5 block update operation. Continues an MD5 message-digest
|
// MD5 block update operation. Continues an MD5 message-digest
|
||||||
// operation, processing another message block
|
// operation, processing another message block
|
||||||
void MD5::update(const unsigned char input[], size_type length)
|
void MD5::update(const unsigned char input[], size_type length) {
|
||||||
{
|
|
||||||
// compute number of bytes mod 64
|
// compute number of bytes mod 64
|
||||||
size_type index = count[0] / 8 % blocksize;
|
size_type index = count[0] / 8 % blocksize;
|
||||||
|
|
||||||
@ -264,8 +257,7 @@ void MD5::update(const unsigned char input[], size_type length)
|
|||||||
size_type i;
|
size_type i;
|
||||||
|
|
||||||
// transform as many times as possible.
|
// transform as many times as possible.
|
||||||
if (length >= firstpart)
|
if (length >= firstpart) {
|
||||||
{
|
|
||||||
// fill buffer first, transform
|
// fill buffer first, transform
|
||||||
memcpy(&buffer[index], input, firstpart);
|
memcpy(&buffer[index], input, firstpart);
|
||||||
transform(buffer);
|
transform(buffer);
|
||||||
@ -275,8 +267,7 @@ void MD5::update(const unsigned char input[], size_type length)
|
|||||||
transform(&input[i]);
|
transform(&input[i]);
|
||||||
|
|
||||||
index = 0;
|
index = 0;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
// buffer remaining input
|
// buffer remaining input
|
||||||
@ -286,8 +277,7 @@ void MD5::update(const unsigned char input[], size_type length)
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
|
|
||||||
// for convenience provide a verson with signed char
|
// for convenience provide a verson with signed char
|
||||||
void MD5::update(const char input[], size_type length)
|
void MD5::update(const char input[], size_type length) {
|
||||||
{
|
|
||||||
update((const unsigned char*)input, length);
|
update((const unsigned char*)input, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,8 +285,7 @@ void MD5::update(const char input[], size_type length)
|
|||||||
|
|
||||||
// MD5 finalization. Ends an MD5 message-digest operation, writing the
|
// MD5 finalization. Ends an MD5 message-digest operation, writing the
|
||||||
// the message digest and zeroizing the context.
|
// the message digest and zeroizing the context.
|
||||||
MD5& MD5::finalize()
|
MD5& MD5::finalize() {
|
||||||
{
|
|
||||||
static unsigned char padding[64] = {
|
static unsigned char padding[64] = {
|
||||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
@ -332,13 +321,12 @@ MD5& MD5::finalize()
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
|
|
||||||
// return hex representation of digest as string
|
// return hex representation of digest as string
|
||||||
std::string MD5::hexdigest() const
|
std::string MD5::hexdigest() const {
|
||||||
{
|
|
||||||
if (!finalized)
|
if (!finalized)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
char buf[33];
|
char buf[33];
|
||||||
for (int i = 0; i<16; i++)
|
for (int i = 0; i < 16; i++)
|
||||||
sprintf(buf + i * 2, "%02x", digest[i]);
|
sprintf(buf + i * 2, "%02x", digest[i]);
|
||||||
buf[32] = 0;
|
buf[32] = 0;
|
||||||
|
|
||||||
@ -347,15 +335,13 @@ std::string MD5::hexdigest() const
|
|||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& out, MD5 md5)
|
std::ostream& operator<<(std::ostream& out, MD5 md5) {
|
||||||
{
|
|
||||||
return out << md5.hexdigest();
|
return out << md5.hexdigest();
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
|
|
||||||
std::string md5(const std::string str)
|
std::string md5(const std::string str) {
|
||||||
{
|
|
||||||
MD5 md5 = MD5(str);
|
MD5 md5 = MD5(str);
|
||||||
|
|
||||||
return md5.hexdigest();
|
return md5.hexdigest();
|
||||||
|
@ -37,16 +37,16 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
// a small class for calculating MD5 hashes of strings or byte arrays
|
// a small class for calculating MD5 hashes of strings or byte arrays
|
||||||
// it is not meant to be fast or secure
|
// it is not meant to be fast or secure
|
||||||
//
|
//
|
||||||
// usage: 1) feed it blocks of uchars with update()
|
// usage: 1) feed it blocks of uchars with update()
|
||||||
// 2) finalize()
|
// 2) finalize()
|
||||||
// 3) get hexdigest() string
|
// 3) get hexdigest() string
|
||||||
// or
|
// or
|
||||||
// MD5(std::string).hexdigest()
|
// MD5(std::string).hexdigest()
|
||||||
//
|
//
|
||||||
// assumes that char is 8 bit and int is 32 bit
|
// assumes that char is 8 bit and int is 32 bit
|
||||||
class MD5
|
class MD5
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -54,8 +54,8 @@ public:
|
|||||||
|
|
||||||
MD5();
|
MD5();
|
||||||
MD5(const std::string& text);
|
MD5(const std::string& text);
|
||||||
void update(const unsigned char *buf, size_type length);
|
void update(const unsigned char* buf, size_type length);
|
||||||
void update(const char *buf, size_type length);
|
void update(const char* buf, size_type length);
|
||||||
MD5& finalize();
|
MD5& finalize();
|
||||||
std::string hexdigest() const;
|
std::string hexdigest() const;
|
||||||
friend std::ostream& operator<<(std::ostream&, MD5 md5);
|
friend std::ostream& operator<<(std::ostream&, MD5 md5);
|
||||||
@ -82,10 +82,10 @@ private:
|
|||||||
static inline uint4 H(uint4 x, uint4 y, uint4 z);
|
static inline uint4 H(uint4 x, uint4 y, uint4 z);
|
||||||
static inline uint4 I(uint4 x, uint4 y, uint4 z);
|
static inline uint4 I(uint4 x, uint4 y, uint4 z);
|
||||||
static inline uint4 rotate_left(uint4 x, int n);
|
static inline uint4 rotate_left(uint4 x, int n);
|
||||||
static inline void FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
|
static inline void FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
|
||||||
static inline void GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
|
static inline void GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
|
||||||
static inline void HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
|
static inline void HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
|
||||||
static inline void II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
|
static inline void II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string md5(const std::string str);
|
std::string md5(const std::string str);
|
||||||
|
@ -16,55 +16,44 @@ std::vector<MetricVariable> Metrics::m_Variables = {
|
|||||||
MetricVariable::Frame,
|
MetricVariable::Frame,
|
||||||
};
|
};
|
||||||
|
|
||||||
void Metrics::AddMeasurement(MetricVariable variable, int64_t value)
|
void Metrics::AddMeasurement(MetricVariable variable, int64_t value) {
|
||||||
{
|
|
||||||
const auto& iter = m_Metrics.find(variable);
|
const auto& iter = m_Metrics.find(variable);
|
||||||
|
|
||||||
Metric* metric;
|
Metric* metric;
|
||||||
|
|
||||||
if (iter == m_Metrics.end())
|
if (iter == m_Metrics.end()) {
|
||||||
{
|
|
||||||
metric = new Metric();
|
metric = new Metric();
|
||||||
|
|
||||||
m_Metrics[variable] = metric;
|
m_Metrics[variable] = metric;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
metric = iter->second;
|
metric = iter->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddMeasurement(metric, value);
|
AddMeasurement(metric, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metrics::AddMeasurement(Metric* metric, int64_t value)
|
void Metrics::AddMeasurement(Metric* metric, int64_t value) {
|
||||||
{
|
|
||||||
const auto index = metric->measurementIndex;
|
const auto index = metric->measurementIndex;
|
||||||
|
|
||||||
metric->measurements[index] = value;
|
metric->measurements[index] = value;
|
||||||
|
|
||||||
if (metric->max == -1 || value > metric->max)
|
if (metric->max == -1 || value > metric->max) {
|
||||||
{
|
|
||||||
metric->max = value;
|
metric->max = value;
|
||||||
}
|
} else if (metric->min == -1 || metric->min > value) {
|
||||||
else if (metric->min == -1 || metric->min > value)
|
|
||||||
{
|
|
||||||
metric->min = value;
|
metric->min = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (metric->measurementSize < MAX_MEASURMENT_POINTS)
|
if (metric->measurementSize < MAX_MEASURMENT_POINTS) {
|
||||||
{
|
|
||||||
metric->measurementSize++;
|
metric->measurementSize++;
|
||||||
}
|
}
|
||||||
|
|
||||||
metric->measurementIndex = (index + 1) % MAX_MEASURMENT_POINTS;
|
metric->measurementIndex = (index + 1) % MAX_MEASURMENT_POINTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Metric* Metrics::GetMetric(MetricVariable variable)
|
const Metric* Metrics::GetMetric(MetricVariable variable) {
|
||||||
{
|
|
||||||
const auto& iter = m_Metrics.find(variable);
|
const auto& iter = m_Metrics.find(variable);
|
||||||
|
|
||||||
if (iter == m_Metrics.end())
|
if (iter == m_Metrics.end()) {
|
||||||
{
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,8 +61,7 @@ const Metric* Metrics::GetMetric(MetricVariable variable)
|
|||||||
|
|
||||||
int64_t average = 0;
|
int64_t average = 0;
|
||||||
|
|
||||||
for (size_t i = 0; i < metric->measurementSize; i++)
|
for (size_t i = 0; i < metric->measurementSize; i++) {
|
||||||
{
|
|
||||||
average += metric->measurements[i];
|
average += metric->measurements[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,34 +72,28 @@ const Metric* Metrics::GetMetric(MetricVariable variable)
|
|||||||
return metric;
|
return metric;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metrics::StartMeasurement(MetricVariable variable)
|
void Metrics::StartMeasurement(MetricVariable variable) {
|
||||||
{
|
|
||||||
const auto& iter = m_Metrics.find(variable);
|
const auto& iter = m_Metrics.find(variable);
|
||||||
|
|
||||||
Metric* metric;
|
Metric* metric;
|
||||||
|
|
||||||
if (iter == m_Metrics.end())
|
if (iter == m_Metrics.end()) {
|
||||||
{
|
|
||||||
metric = new Metric();
|
metric = new Metric();
|
||||||
|
|
||||||
m_Metrics[variable] = metric;
|
m_Metrics[variable] = metric;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
metric = iter->second;
|
metric = iter->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
metric->activeMeasurement = std::chrono::high_resolution_clock::now();
|
metric->activeMeasurement = std::chrono::high_resolution_clock::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metrics::EndMeasurement(MetricVariable variable)
|
void Metrics::EndMeasurement(MetricVariable variable) {
|
||||||
{
|
|
||||||
const auto end = std::chrono::high_resolution_clock::now();
|
const auto end = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
const auto& iter = m_Metrics.find(variable);
|
const auto& iter = m_Metrics.find(variable);
|
||||||
|
|
||||||
if (iter == m_Metrics.end())
|
if (iter == m_Metrics.end()) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,15 +106,12 @@ void Metrics::EndMeasurement(MetricVariable variable)
|
|||||||
AddMeasurement(metric, nanoseconds);
|
AddMeasurement(metric, nanoseconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
float Metrics::ToMiliseconds(int64_t nanoseconds)
|
float Metrics::ToMiliseconds(int64_t nanoseconds) {
|
||||||
{
|
return (float)nanoseconds / 1e6;
|
||||||
return (float) nanoseconds / 1e6;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Metrics::MetricVariableToString(MetricVariable variable)
|
std::string Metrics::MetricVariableToString(MetricVariable variable) {
|
||||||
{
|
switch (variable) {
|
||||||
switch (variable)
|
|
||||||
{
|
|
||||||
case MetricVariable::GameLoop:
|
case MetricVariable::GameLoop:
|
||||||
return "GameLoop";
|
return "GameLoop";
|
||||||
case MetricVariable::PacketHandling:
|
case MetricVariable::PacketHandling:
|
||||||
@ -159,15 +138,12 @@ std::string Metrics::MetricVariableToString(MetricVariable variable)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<MetricVariable>& Metrics::GetAllMetrics()
|
const std::vector<MetricVariable>& Metrics::GetAllMetrics() {
|
||||||
{
|
|
||||||
return m_Variables;
|
return m_Variables;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metrics::Clear()
|
void Metrics::Clear() {
|
||||||
{
|
for (const auto& pair : m_Metrics) {
|
||||||
for (const auto& pair : m_Metrics)
|
|
||||||
{
|
|
||||||
delete pair.second;
|
delete pair.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,37 +183,35 @@ void Metrics::Clear()
|
|||||||
#error "Cannot define getPeakRSS( ) or getCurrentRSS( ) for an unknown OS."
|
#error "Cannot define getPeakRSS( ) or getCurrentRSS( ) for an unknown OS."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the peak (maximum so far) resident set size (physical
|
* Returns the peak (maximum so far) resident set size (physical
|
||||||
* memory use) measured in bytes, or zero if the value cannot be
|
* memory use) measured in bytes, or zero if the value cannot be
|
||||||
* determined on this OS.
|
* determined on this OS.
|
||||||
*/
|
*/
|
||||||
size_t Metrics::GetPeakRSS()
|
size_t Metrics::GetPeakRSS() {
|
||||||
{
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
/* Windows -------------------------------------------------- */
|
/* Windows -------------------------------------------------- */
|
||||||
PROCESS_MEMORY_COUNTERS info;
|
PROCESS_MEMORY_COUNTERS info;
|
||||||
GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
|
GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info));
|
||||||
return (size_t)info.PeakWorkingSetSize;
|
return (size_t)info.PeakWorkingSetSize;
|
||||||
|
|
||||||
#elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
|
#elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
|
||||||
/* AIX and Solaris ------------------------------------------ */
|
/* AIX and Solaris ------------------------------------------ */
|
||||||
struct psinfo psinfo;
|
struct psinfo psinfo;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
if ( (fd = open( "/proc/self/psinfo", O_RDONLY )) == -1 )
|
if ((fd = open("/proc/self/psinfo", O_RDONLY)) == -1)
|
||||||
return (size_t)0L; /* Can't open? */
|
return (size_t)0L; /* Can't open? */
|
||||||
if ( read( fd, &psinfo, sizeof(psinfo) ) != sizeof(psinfo) )
|
if (read(fd, &psinfo, sizeof(psinfo)) != sizeof(psinfo)) {
|
||||||
{
|
close(fd);
|
||||||
close( fd );
|
|
||||||
return (size_t)0L; /* Can't read? */
|
return (size_t)0L; /* Can't read? */
|
||||||
}
|
}
|
||||||
close( fd );
|
close(fd);
|
||||||
return (size_t)(psinfo.pr_rssize * 1024L);
|
return (size_t)(psinfo.pr_rssize * 1024L);
|
||||||
|
|
||||||
#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
|
#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
|
||||||
/* BSD, Linux, and OSX -------------------------------------- */
|
/* BSD, Linux, and OSX -------------------------------------- */
|
||||||
struct rusage rusage;
|
struct rusage rusage;
|
||||||
getrusage( RUSAGE_SELF, &rusage );
|
getrusage(RUSAGE_SELF, &rusage);
|
||||||
#if defined(__APPLE__) && defined(__MACH__)
|
#if defined(__APPLE__) && defined(__MACH__)
|
||||||
return (size_t)rusage.ru_maxrss;
|
return (size_t)rusage.ru_maxrss;
|
||||||
#else
|
#else
|
||||||
@ -255,20 +229,19 @@ size_t Metrics::GetPeakRSS()
|
|||||||
* Returns the current resident set size (physical memory use) measured
|
* Returns the current resident set size (physical memory use) measured
|
||||||
* in bytes, or zero if the value cannot be determined on this OS.
|
* in bytes, or zero if the value cannot be determined on this OS.
|
||||||
*/
|
*/
|
||||||
size_t Metrics::GetCurrentRSS()
|
size_t Metrics::GetCurrentRSS() {
|
||||||
{
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
/* Windows -------------------------------------------------- */
|
/* Windows -------------------------------------------------- */
|
||||||
PROCESS_MEMORY_COUNTERS info;
|
PROCESS_MEMORY_COUNTERS info;
|
||||||
GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
|
GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info));
|
||||||
return (size_t)info.WorkingSetSize;
|
return (size_t)info.WorkingSetSize;
|
||||||
|
|
||||||
#elif defined(__APPLE__) && defined(__MACH__)
|
#elif defined(__APPLE__) && defined(__MACH__)
|
||||||
/* OSX ------------------------------------------------------ */
|
/* OSX ------------------------------------------------------ */
|
||||||
struct mach_task_basic_info info;
|
struct mach_task_basic_info info;
|
||||||
mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
|
mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
|
||||||
if ( task_info( mach_task_self( ), MACH_TASK_BASIC_INFO,
|
if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO,
|
||||||
(task_info_t)&info, &infoCount ) != KERN_SUCCESS )
|
(task_info_t)&info, &infoCount) != KERN_SUCCESS)
|
||||||
return (size_t)0L; /* Can't access? */
|
return (size_t)0L; /* Can't access? */
|
||||||
return (size_t)info.resident_size;
|
return (size_t)info.resident_size;
|
||||||
|
|
||||||
@ -276,15 +249,14 @@ size_t Metrics::GetCurrentRSS()
|
|||||||
/* Linux ---------------------------------------------------- */
|
/* Linux ---------------------------------------------------- */
|
||||||
long rss = 0L;
|
long rss = 0L;
|
||||||
FILE* fp = NULL;
|
FILE* fp = NULL;
|
||||||
if ( (fp = fopen( "/proc/self/statm", "r" )) == NULL )
|
if ((fp = fopen("/proc/self/statm", "r")) == NULL)
|
||||||
return (size_t)0L; /* Can't open? */
|
return (size_t)0L; /* Can't open? */
|
||||||
if ( fscanf( fp, "%*s%ld", &rss ) != 1 )
|
if (fscanf(fp, "%*s%ld", &rss) != 1) {
|
||||||
{
|
fclose(fp);
|
||||||
fclose( fp );
|
|
||||||
return (size_t)0L; /* Can't read? */
|
return (size_t)0L; /* Can't read? */
|
||||||
}
|
}
|
||||||
fclose( fp );
|
fclose(fp);
|
||||||
return (size_t)rss * (size_t)sysconf( _SC_PAGESIZE);
|
return (size_t)rss * (size_t)sysconf(_SC_PAGESIZE);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
/* AIX, BSD, Solaris, and Unknown OS ------------------------ */
|
/* AIX, BSD, Solaris, and Unknown OS ------------------------ */
|
||||||
@ -293,8 +265,7 @@ size_t Metrics::GetCurrentRSS()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Metrics::GetProcessID()
|
size_t Metrics::GetProcessID() {
|
||||||
{
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
return GetCurrentProcessId();
|
return GetCurrentProcessId();
|
||||||
#else
|
#else
|
||||||
|
@ -71,12 +71,12 @@ void NiPoint3::SetZ(float z) {
|
|||||||
|
|
||||||
//! Gets the length of the vector
|
//! Gets the length of the vector
|
||||||
float NiPoint3::Length(void) const {
|
float NiPoint3::Length(void) const {
|
||||||
return sqrt(x*x + y*y + z*z);
|
return sqrt(x * x + y * y + z * z);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Gets the squared length of a vector
|
//! Gets the squared length of a vector
|
||||||
float NiPoint3::SquaredLength(void) const {
|
float NiPoint3::SquaredLength(void) const {
|
||||||
return (x*x + y*y + z*z);
|
return (x * x + y * y + z * z);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Returns the dot product of the vector dotted with another vector
|
//! Returns the dot product of the vector dotted with another vector
|
||||||
@ -113,13 +113,13 @@ bool NiPoint3::operator!=(const NiPoint3& point) const {
|
|||||||
|
|
||||||
//! Operator for subscripting
|
//! Operator for subscripting
|
||||||
float& NiPoint3::operator[](int i) {
|
float& NiPoint3::operator[](int i) {
|
||||||
float * base = &x;
|
float* base = &x;
|
||||||
return (float&)base[i];
|
return (float&)base[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Operator for subscripting
|
//! Operator for subscripting
|
||||||
const float& NiPoint3::operator[](int i) const {
|
const float& NiPoint3::operator[](int i) const {
|
||||||
const float * base = &x;
|
const float* base = &x;
|
||||||
return (float&)base[i];
|
return (float&)base[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,7 +166,7 @@ bool NiPoint3::IsWithinAxisAlignedBox(const NiPoint3& minPoint, const NiPoint3&
|
|||||||
if (this->y < minPoint.y) return false;
|
if (this->y < minPoint.y) return false;
|
||||||
if (this->y > maxPoint.y) return false;
|
if (this->y > maxPoint.y) return false;
|
||||||
|
|
||||||
return (this->z < maxPoint.z && this->z > minPoint.z);
|
return (this->z < maxPoint.z&& this->z > minPoint.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Checks to see if the point (or vector) is within a sphere
|
//! Checks to see if the point (or vector) is within a sphere
|
||||||
@ -175,8 +175,7 @@ bool NiPoint3::IsWithinSpehere(const NiPoint3& sphereCenter, float radius) {
|
|||||||
return (diffVec.SquaredLength() <= (radius * radius));
|
return (diffVec.SquaredLength() <= (radius * radius));
|
||||||
}
|
}
|
||||||
|
|
||||||
NiPoint3 NiPoint3::ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, const NiPoint3& p)
|
NiPoint3 NiPoint3::ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, const NiPoint3& p) {
|
||||||
{
|
|
||||||
if (a == b) return a;
|
if (a == b) return a;
|
||||||
|
|
||||||
const auto pa = p - a;
|
const auto pa = p - a;
|
||||||
@ -191,16 +190,14 @@ NiPoint3 NiPoint3::ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, cons
|
|||||||
return a + ab * t;
|
return a + ab * t;
|
||||||
}
|
}
|
||||||
|
|
||||||
float NiPoint3::Angle(const NiPoint3& a, const NiPoint3& b)
|
float NiPoint3::Angle(const NiPoint3& a, const NiPoint3& b) {
|
||||||
{
|
|
||||||
const auto dot = a.DotProduct(b);
|
const auto dot = a.DotProduct(b);
|
||||||
const auto lenA = a.SquaredLength();
|
const auto lenA = a.SquaredLength();
|
||||||
const auto lenB = a.SquaredLength();
|
const auto lenB = a.SquaredLength();
|
||||||
return acos(dot / sqrt(lenA * lenB));
|
return acos(dot / sqrt(lenA * lenB));
|
||||||
}
|
}
|
||||||
|
|
||||||
float NiPoint3::Distance(const NiPoint3& a, const NiPoint3& b)
|
float NiPoint3::Distance(const NiPoint3& a, const NiPoint3& b) {
|
||||||
{
|
|
||||||
const auto dx = a.x - b.x;
|
const auto dx = a.x - b.x;
|
||||||
const auto dy = a.y - b.y;
|
const auto dy = a.y - b.y;
|
||||||
const auto dz = a.z - b.z;
|
const auto dz = a.z - b.z;
|
||||||
@ -208,8 +205,7 @@ float NiPoint3::Distance(const NiPoint3& a, const NiPoint3& b)
|
|||||||
return std::sqrt(dx * dx + dy * dy + dz * dz);
|
return std::sqrt(dx * dx + dy * dy + dz * dz);
|
||||||
}
|
}
|
||||||
|
|
||||||
float NiPoint3::DistanceSquared(const NiPoint3& a, const NiPoint3& b)
|
float NiPoint3::DistanceSquared(const NiPoint3& a, const NiPoint3& b) {
|
||||||
{
|
|
||||||
const auto dx = a.x - b.x;
|
const auto dx = a.x - b.x;
|
||||||
const auto dy = a.y - b.y;
|
const auto dy = a.y - b.y;
|
||||||
const auto dz = a.z - b.z;
|
const auto dz = a.z - b.z;
|
||||||
@ -217,15 +213,14 @@ float NiPoint3::DistanceSquared(const NiPoint3& a, const NiPoint3& b)
|
|||||||
return dx * dx + dy * dy + dz * dz;
|
return dx * dx + dy * dy + dz * dz;
|
||||||
}
|
}
|
||||||
|
|
||||||
NiPoint3 NiPoint3::MoveTowards(const NiPoint3& current, const NiPoint3& target, float maxDistanceDelta)
|
NiPoint3 NiPoint3::MoveTowards(const NiPoint3& current, const NiPoint3& target, float maxDistanceDelta) {
|
||||||
{
|
|
||||||
float dx = target.x - current.x;
|
float dx = target.x - current.x;
|
||||||
float dy = target.y - current.y;
|
float dy = target.y - current.y;
|
||||||
float dz = target.z - current.z;
|
float dz = target.z - current.z;
|
||||||
float lengthSquared = (float) ((double) dx * (double) dx + (double) dy * (double) dy + (double) dz * (double) dz);
|
float lengthSquared = (float)((double)dx * (double)dx + (double)dy * (double)dy + (double)dz * (double)dz);
|
||||||
if ((double) lengthSquared == 0.0 || (double) maxDistanceDelta >= 0.0 && (double) lengthSquared <= (double) maxDistanceDelta * (double) maxDistanceDelta)
|
if ((double)lengthSquared == 0.0 || (double)maxDistanceDelta >= 0.0 && (double)lengthSquared <= (double)maxDistanceDelta * (double)maxDistanceDelta)
|
||||||
return target;
|
return target;
|
||||||
float length = (float) std::sqrt((double) lengthSquared);
|
float length = (float)std::sqrt((double)lengthSquared);
|
||||||
return NiPoint3(current.x + dx / length * maxDistanceDelta, current.y + dy / length * maxDistanceDelta, current.z + dz / length * maxDistanceDelta);
|
return NiPoint3(current.x + dx / length * maxDistanceDelta, current.y + dy / length * maxDistanceDelta, current.z + dz / length * maxDistanceDelta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,8 +99,7 @@ Vector3 NiQuaternion::GetEulerAngles() const {
|
|||||||
|
|
||||||
if (std::abs(sinp) >= 1) {
|
if (std::abs(sinp) >= 1) {
|
||||||
angles.y = std::copysign(3.14 / 2, sinp); // use 90 degrees if out of range
|
angles.y = std::copysign(3.14 / 2, sinp); // use 90 degrees if out of range
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
angles.y = std::asin(sinp);
|
angles.y = std::asin(sinp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,8 +148,7 @@ NiQuaternion NiQuaternion::LookAt(const NiPoint3& sourcePoint, const NiPoint3& d
|
|||||||
return NiQuaternion::CreateFromAxisAngle(vecA, rotAngle);
|
return NiQuaternion::CreateFromAxisAngle(vecA, rotAngle);
|
||||||
}
|
}
|
||||||
|
|
||||||
NiQuaternion NiQuaternion::LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint)
|
NiQuaternion NiQuaternion::LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint) {
|
||||||
{
|
|
||||||
NiPoint3 forwardVector = NiPoint3(destPoint - sourcePoint).Unitize();
|
NiPoint3 forwardVector = NiPoint3(destPoint - sourcePoint).Unitize();
|
||||||
|
|
||||||
NiPoint3 posZ = NiPoint3::UNIT_Z;
|
NiPoint3 posZ = NiPoint3::UNIT_Z;
|
||||||
@ -179,8 +177,7 @@ NiQuaternion NiQuaternion::CreateFromAxisAngle(const Vector3& axis, float angle)
|
|||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
NiQuaternion NiQuaternion::FromEulerAngles(const NiPoint3& eulerAngles)
|
NiQuaternion NiQuaternion::FromEulerAngles(const NiPoint3& eulerAngles) {
|
||||||
{
|
|
||||||
// Abbreviations for the various angular functions
|
// Abbreviations for the various angular functions
|
||||||
float cy = cos(eulerAngles.z * 0.5);
|
float cy = cos(eulerAngles.z * 0.5);
|
||||||
float sy = sin(eulerAngles.z * 0.5);
|
float sy = sin(eulerAngles.z * 0.5);
|
||||||
|
@ -45,12 +45,11 @@ const unsigned long long SHA512::sha512_k[80] = //ULL = uint64
|
|||||||
0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
|
0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
|
||||||
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL };
|
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL };
|
||||||
|
|
||||||
void SHA512::transform(const unsigned char *message, unsigned int block_nb)
|
void SHA512::transform(const unsigned char* message, unsigned int block_nb) {
|
||||||
{
|
|
||||||
uint64 w[80];
|
uint64 w[80];
|
||||||
uint64 wv[8];
|
uint64 wv[8];
|
||||||
uint64 t1, t2;
|
uint64 t1, t2;
|
||||||
const unsigned char *sub_block;
|
const unsigned char* sub_block;
|
||||||
int i, j;
|
int i, j;
|
||||||
for (i = 0; i < (int)block_nb; i++) {
|
for (i = 0; i < (int)block_nb; i++) {
|
||||||
sub_block = message + (i << 7);
|
sub_block = message + (i << 7);
|
||||||
@ -83,8 +82,7 @@ void SHA512::transform(const unsigned char *message, unsigned int block_nb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHA512::init()
|
void SHA512::init() {
|
||||||
{
|
|
||||||
m_h[0] = 0x6a09e667f3bcc908ULL;
|
m_h[0] = 0x6a09e667f3bcc908ULL;
|
||||||
m_h[1] = 0xbb67ae8584caa73bULL;
|
m_h[1] = 0xbb67ae8584caa73bULL;
|
||||||
m_h[2] = 0x3c6ef372fe94f82bULL;
|
m_h[2] = 0x3c6ef372fe94f82bULL;
|
||||||
@ -97,11 +95,10 @@ void SHA512::init()
|
|||||||
m_tot_len = 0;
|
m_tot_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHA512::update(const unsigned char *message, unsigned int len)
|
void SHA512::update(const unsigned char* message, unsigned int len) {
|
||||||
{
|
|
||||||
unsigned int block_nb;
|
unsigned int block_nb;
|
||||||
unsigned int new_len, rem_len, tmp_len;
|
unsigned int new_len, rem_len, tmp_len;
|
||||||
const unsigned char *shifted_message;
|
const unsigned char* shifted_message;
|
||||||
tmp_len = SHA384_512_BLOCK_SIZE - m_len;
|
tmp_len = SHA384_512_BLOCK_SIZE - m_len;
|
||||||
rem_len = len < tmp_len ? len : tmp_len;
|
rem_len = len < tmp_len ? len : tmp_len;
|
||||||
memcpy(&m_block[m_len], message, rem_len);
|
memcpy(&m_block[m_len], message, rem_len);
|
||||||
@ -120,8 +117,7 @@ void SHA512::update(const unsigned char *message, unsigned int len)
|
|||||||
m_tot_len += (block_nb + 1) << 7;
|
m_tot_len += (block_nb + 1) << 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHA512::final(unsigned char *digest)
|
void SHA512::final(unsigned char* digest) {
|
||||||
{
|
|
||||||
unsigned int block_nb;
|
unsigned int block_nb;
|
||||||
unsigned int pm_len;
|
unsigned int pm_len;
|
||||||
unsigned int len_b;
|
unsigned int len_b;
|
||||||
@ -139,8 +135,7 @@ void SHA512::final(unsigned char *digest)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string sha512(std::string input)
|
std::string sha512(std::string input) {
|
||||||
{
|
|
||||||
unsigned char digest[SHA512::DIGEST_SIZE];
|
unsigned char digest[SHA512::DIGEST_SIZE];
|
||||||
memset(digest, 0, SHA512::DIGEST_SIZE);
|
memset(digest, 0, SHA512::DIGEST_SIZE);
|
||||||
class SHA512 ctx;
|
class SHA512 ctx;
|
||||||
|
@ -14,12 +14,12 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
void init();
|
void init();
|
||||||
void update(const unsigned char *message, unsigned int len);
|
void update(const unsigned char* message, unsigned int len);
|
||||||
void final(unsigned char *digest);
|
void final(unsigned char* digest);
|
||||||
static const unsigned int DIGEST_SIZE = (512 / 8);
|
static const unsigned int DIGEST_SIZE = (512 / 8);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void transform(const unsigned char *message, unsigned int block_nb);
|
void transform(const unsigned char* message, unsigned int block_nb);
|
||||||
unsigned int m_tot_len;
|
unsigned int m_tot_len;
|
||||||
unsigned int m_len;
|
unsigned int m_len;
|
||||||
unsigned char m_block[2 * SHA384_512_BLOCK_SIZE];
|
unsigned char m_block[2 * SHA384_512_BLOCK_SIZE];
|
||||||
|
@ -9,12 +9,12 @@ std::string demangle(const char* name) {
|
|||||||
int status = -4; // some arbitrary value to eliminate the compiler warning
|
int status = -4; // some arbitrary value to eliminate the compiler warning
|
||||||
|
|
||||||
// enable c++11 by passing the flag -std=c++11 to g++
|
// enable c++11 by passing the flag -std=c++11 to g++
|
||||||
std::unique_ptr<char, void(*)(void*)> res {
|
std::unique_ptr<char, void(*)(void*)> res{
|
||||||
abi::__cxa_demangle(name, NULL, NULL, &status),
|
abi::__cxa_demangle(name, NULL, NULL, &status),
|
||||||
std::free
|
std::free
|
||||||
};
|
};
|
||||||
|
|
||||||
return (status==0) ? res.get() : name ;
|
return (status == 0) ? res.get() : name;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
@ -1,19 +1,14 @@
|
|||||||
#include "ZCompression.h"
|
#include "ZCompression.h"
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
|
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
namespace ZCompression
|
namespace ZCompression {
|
||||||
{
|
int32_t GetMaxCompressedLength(int32_t nLenSrc) {
|
||||||
int32_t GetMaxCompressedLength(int32_t nLenSrc)
|
|
||||||
{
|
|
||||||
int32_t n16kBlocks = (nLenSrc + 16383) / 16384; // round up any fraction of a block
|
int32_t n16kBlocks = (nLenSrc + 16383) / 16384; // round up any fraction of a block
|
||||||
return (nLenSrc + 6 + (n16kBlocks * 5));
|
return (nLenSrc + 6 + (n16kBlocks * 5));
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t Compress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst)
|
int32_t Compress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst) {
|
||||||
{
|
|
||||||
z_stream zInfo = { 0 };
|
z_stream zInfo = { 0 };
|
||||||
zInfo.total_in = zInfo.avail_in = nLenSrc;
|
zInfo.total_in = zInfo.avail_in = nLenSrc;
|
||||||
zInfo.total_out = zInfo.avail_out = nLenDst;
|
zInfo.total_out = zInfo.avail_out = nLenDst;
|
||||||
@ -30,11 +25,9 @@ namespace ZCompression
|
|||||||
}
|
}
|
||||||
deflateEnd(&zInfo); // zlib function
|
deflateEnd(&zInfo); // zlib function
|
||||||
return(nRet);
|
return(nRet);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t Decompress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst, int32_t& nErr)
|
int32_t Decompress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst, int32_t& nErr) {
|
||||||
{
|
|
||||||
// Get the size of the decompressed data
|
// Get the size of the decompressed data
|
||||||
z_stream zInfo = { 0 };
|
z_stream zInfo = { 0 };
|
||||||
zInfo.total_in = zInfo.avail_in = nLenSrc;
|
zInfo.total_in = zInfo.avail_in = nLenSrc;
|
||||||
@ -52,26 +45,6 @@ namespace ZCompression
|
|||||||
}
|
}
|
||||||
inflateEnd(&zInfo); // zlib function
|
inflateEnd(&zInfo); // zlib function
|
||||||
return(nRet);
|
return(nRet);
|
||||||
|
|
||||||
/*
|
|
||||||
z_stream zInfo = { 0 };
|
|
||||||
zInfo.total_in = zInfo.avail_in = nLenSrc;
|
|
||||||
zInfo.total_out = zInfo.avail_out = nLenDst;
|
|
||||||
zInfo.next_in = const_cast<Bytef*>(abSrc);
|
|
||||||
zInfo.next_out = const_cast<Bytef*>(abDst);
|
|
||||||
|
|
||||||
int nRet = -1;
|
|
||||||
nErr = inflateInit(&zInfo); // zlib function
|
|
||||||
if (nErr == Z_OK) {
|
|
||||||
nErr = inflate(&zInfo, Z_FINISH); // zlib function
|
|
||||||
if (nErr == Z_STREAM_END) {
|
|
||||||
nRet = zInfo.total_out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
inflateEnd(&zInfo); // zlib function
|
|
||||||
return(nRet); // -1 or len of output
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
@ -1,13 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include "dPlatforms.h"
|
namespace ZCompression {
|
||||||
|
|
||||||
#ifndef DARKFLAME_PLATFORM_WIN32
|
|
||||||
|
|
||||||
namespace ZCompression
|
|
||||||
{
|
|
||||||
int32_t GetMaxCompressedLength(int32_t nLenSrc);
|
int32_t GetMaxCompressedLength(int32_t nLenSrc);
|
||||||
|
|
||||||
int32_t Compress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst);
|
int32_t Compress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst);
|
||||||
@ -15,4 +10,3 @@ namespace ZCompression
|
|||||||
int32_t Decompress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst, int32_t& nErr);
|
int32_t Decompress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst, int32_t& nErr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -387,6 +387,7 @@ enum eReplicaComponentType : int32_t {
|
|||||||
COMPONENT_TYPE_PROPERTY = 36, //!< The Property Component
|
COMPONENT_TYPE_PROPERTY = 36, //!< The Property Component
|
||||||
COMPONENT_TYPE_SCRIPTED_ACTIVITY = 39, //!< The ScriptedActivity Component
|
COMPONENT_TYPE_SCRIPTED_ACTIVITY = 39, //!< The ScriptedActivity Component
|
||||||
COMPONENT_TYPE_PHANTOM_PHYSICS = 40, //!< The PhantomPhysics Component
|
COMPONENT_TYPE_PHANTOM_PHYSICS = 40, //!< The PhantomPhysics Component
|
||||||
|
COMPONENT_TYPE_MODEL = 42, //!< The Model Component
|
||||||
COMPONENT_TYPE_PROPERTY_ENTRANCE = 43, //!< The PhantomPhysics Component
|
COMPONENT_TYPE_PROPERTY_ENTRANCE = 43, //!< The PhantomPhysics Component
|
||||||
COMPONENT_TYPE_PROPERTY_MANAGEMENT = 45, //!< The PropertyManagement Component
|
COMPONENT_TYPE_PROPERTY_MANAGEMENT = 45, //!< The PropertyManagement Component
|
||||||
COMPONENT_TYPE_REBUILD = 48, //!< The Rebuild Component
|
COMPONENT_TYPE_REBUILD = 48, //!< The Rebuild Component
|
||||||
@ -401,18 +402,18 @@ enum eReplicaComponentType : int32_t {
|
|||||||
COMPONENT_TYPE_RACING_CONTROL = 71, //!< The RacingControl Component
|
COMPONENT_TYPE_RACING_CONTROL = 71, //!< The RacingControl Component
|
||||||
COMPONENT_TYPE_MISSION_OFFER = 73, //!< The MissionOffer Component
|
COMPONENT_TYPE_MISSION_OFFER = 73, //!< The MissionOffer Component
|
||||||
COMPONENT_TYPE_EXHIBIT = 75, //!< The Exhibit Component
|
COMPONENT_TYPE_EXHIBIT = 75, //!< The Exhibit Component
|
||||||
COMPONENT_TYPE_RACING_STATS = 74, //!< The Exhibit Component
|
COMPONENT_TYPE_RACING_STATS = 74, //!< The Racing Stats Component
|
||||||
COMPONENT_TYPE_SOUND_TRIGGER = 77, //!< The Sound Trigger Component
|
COMPONENT_TYPE_SOUND_TRIGGER = 77, //!< The Sound Trigger Component
|
||||||
COMPONENT_TYPE_PROXIMITY_MONITOR = 78, //!< The Proximity Monitor Component
|
COMPONENT_TYPE_PROXIMITY_MONITOR = 78, //!< The Proximity Monitor Component
|
||||||
COMPONENT_TYPE_MISSION = 84, //!< The Mission Component
|
COMPONENT_TYPE_MISSION = 84, //!< The Mission Component
|
||||||
COMPONENT_TYPE_ROCKET_LAUNCH_LUP = 97, //!< The LUP Launchpad Componen
|
COMPONENT_TYPE_ROCKET_LAUNCH_LUP = 97, //!< The LUP Launchpad Componen
|
||||||
COMPONENT_TYPE_RAIL_ACTIVATOR = 104,
|
COMPONENT_TYPE_RAIL_ACTIVATOR = 104, //!< The Rail Activator Component
|
||||||
|
COMPONENT_TYPE_PLAYER_FORCED_MOVEMENT = 106, //!< The Player Forced Movement Component
|
||||||
COMPONENT_TYPE_POSSESSABLE = 108, //!< The Possessable Component
|
COMPONENT_TYPE_POSSESSABLE = 108, //!< The Possessable Component
|
||||||
|
COMPONENT_TYPE_LEVEL_PROGRESSION = 109, //!< The Level Progression Component
|
||||||
COMPONENT_TYPE_POSSESSOR = 110, //!< The Possessor Component
|
COMPONENT_TYPE_POSSESSOR = 110, //!< The Possessor Component
|
||||||
COMPONENT_TYPE_BUILD_BORDER = 114, //!< The Build Border Component
|
COMPONENT_TYPE_BUILD_BORDER = 114, //!< The Build Border Component
|
||||||
COMPONENT_TYPE_DESTROYABLE = 1000, //!< The Destroyable Component
|
COMPONENT_TYPE_DESTROYABLE = 1000, //!< The Destroyable Component
|
||||||
|
|
||||||
COMPONENT_TYPE_MODEL = 5398484 //look man idk
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class UseItemResponse : uint32_t {
|
enum class UseItemResponse : uint32_t {
|
||||||
@ -541,7 +542,7 @@ enum ePlayerFlags {
|
|||||||
TOOLTIP_TALK_TO_SKYLAND_TO_GET_HAT = 52,
|
TOOLTIP_TALK_TO_SKYLAND_TO_GET_HAT = 52,
|
||||||
MODULAR_BUILD_PLAYER_PLACES_FIRST_MODEL_IN_SCRATCH = 53,
|
MODULAR_BUILD_PLAYER_PLACES_FIRST_MODEL_IN_SCRATCH = 53,
|
||||||
MODULAR_BUILD_FIRST_ARROW_DISPLAY_FOR_MODULE = 54,
|
MODULAR_BUILD_FIRST_ARROW_DISPLAY_FOR_MODULE = 54,
|
||||||
AG_BEACON_QB,_SO_THE_PLAYER_CAN_ALWAYS_BUILD_THEM = 55,
|
AG_BEACON_QB_SO_THE_PLAYER_CAN_ALWAYS_BUILD_THEM = 55,
|
||||||
GF_PET_DIG_FLAG_1 = 56,
|
GF_PET_DIG_FLAG_1 = 56,
|
||||||
GF_PET_DIG_FLAG_2 = 57,
|
GF_PET_DIG_FLAG_2 = 57,
|
||||||
GF_PET_DIG_FLAG_3 = 58,
|
GF_PET_DIG_FLAG_3 = 58,
|
||||||
@ -627,6 +628,7 @@ enum ePlayerFlags {
|
|||||||
GF_BINOC_IN_CROC_AREA = 1308,
|
GF_BINOC_IN_CROC_AREA = 1308,
|
||||||
GF_BINOC_IN_JAIL_AREA = 1309,
|
GF_BINOC_IN_JAIL_AREA = 1309,
|
||||||
GF_BINOC_TELESCOPE_NEXT_TO_CAPTAIN_JACK = 1310,
|
GF_BINOC_TELESCOPE_NEXT_TO_CAPTAIN_JACK = 1310,
|
||||||
|
NT_PLINTH_REBUILD = 1919,
|
||||||
NT_FACTION_SPY_DUKE = 1974,
|
NT_FACTION_SPY_DUKE = 1974,
|
||||||
NT_FACTION_SPY_OVERBUILD = 1976,
|
NT_FACTION_SPY_OVERBUILD = 1976,
|
||||||
NT_FACTION_SPY_HAEL = 1977,
|
NT_FACTION_SPY_HAEL = 1977,
|
||||||
|
@ -33,17 +33,17 @@ void dLogger::vLog(const char* format, va_list args) {
|
|||||||
char timeStr[70];
|
char timeStr[70];
|
||||||
strftime(timeStr, sizeof(timeStr), "%d-%m-%y %H:%M:%S", &time);
|
strftime(timeStr, sizeof(timeStr), "%d-%m-%y %H:%M:%S", &time);
|
||||||
char message[2048];
|
char message[2048];
|
||||||
vsprintf_s(message, format, args);
|
vsnprintf(message, 2048, format, args);
|
||||||
|
|
||||||
if (m_logToConsole) std::cout << "[" << timeStr << "] " << message;
|
if (m_logToConsole) std::cout << "[" << timeStr << "] " << message;
|
||||||
mFile << "[" << timeStr << "] " << message;
|
mFile << "[" << timeStr << "] " << message;
|
||||||
#else
|
#else
|
||||||
time_t t = time(NULL);
|
time_t t = time(NULL);
|
||||||
struct tm * time = localtime(&t);
|
struct tm* time = localtime(&t);
|
||||||
char timeStr[70];
|
char timeStr[70];
|
||||||
strftime(timeStr, sizeof(timeStr), "%d-%m-%y %H:%M:%S", time);
|
strftime(timeStr, sizeof(timeStr), "%d-%m-%y %H:%M:%S", time);
|
||||||
char message[2048];
|
char message[2048];
|
||||||
vsprintf(message, format, args);
|
vsnprintf(message, 2048, format, args);
|
||||||
|
|
||||||
if (m_logToConsole) {
|
if (m_logToConsole) {
|
||||||
fputs("[", stdout);
|
fputs("[", stdout);
|
||||||
@ -63,30 +63,30 @@ void dLogger::vLog(const char* format, va_list args) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void dLogger::LogBasic(const char * format, ...) {
|
void dLogger::LogBasic(const char* format, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
vLog(format, args);
|
vLog(format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dLogger::LogBasic(const std::string & message) {
|
void dLogger::LogBasic(const std::string& message) {
|
||||||
LogBasic(message.c_str());
|
LogBasic(message.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void dLogger::Log(const char * className, const char * format, ...) {
|
void dLogger::Log(const char* className, const char* format, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
std::string log = "[" + std::string(className) + "] " + std::string(format);
|
std::string log = "[" + std::string(className) + "] " + std::string(format) + "\n";
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
vLog(log.c_str(), args);
|
vLog(log.c_str(), args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dLogger::Log(const std::string & className, const std::string & message) {
|
void dLogger::Log(const std::string& className, const std::string& message) {
|
||||||
Log(className.c_str(), message.c_str());
|
Log(className.c_str(), message.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void dLogger::LogDebug(const char * className, const char * format, ...) {
|
void dLogger::LogDebug(const char* className, const char* format, ...) {
|
||||||
if (!m_logDebugStatements) return;
|
if (!m_logDebugStatements) return;
|
||||||
va_list args;
|
va_list args;
|
||||||
std::string log = "[" + std::string(className) + "] " + std::string(format);
|
std::string log = "[" + std::string(className) + "] " + std::string(format);
|
||||||
@ -95,7 +95,7 @@ void dLogger::LogDebug(const char * className, const char * format, ...) {
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dLogger::LogDebug(const std::string & className, const std::string & message) {
|
void dLogger::LogDebug(const std::string& className, const std::string& message) {
|
||||||
LogDebug(className.c_str(), message.c_str());
|
LogDebug(className.c_str(), message.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,8 +31,8 @@ private:
|
|||||||
std::string m_outpath;
|
std::string m_outpath;
|
||||||
std::ofstream mFile;
|
std::ofstream mFile;
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
//Glorious linux can run with SPEED:
|
//Glorious linux can run with SPEED:
|
||||||
FILE* fp = nullptr;
|
FILE* fp = nullptr;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
@ -1,29 +1,29 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#define DARKFLAME_PLATFORM_WIN32
|
#define DARKFLAME_PLATFORM_WIN32
|
||||||
#elif defined(__APPLE__) && defined(__MACH__)
|
#elif defined(__APPLE__) && defined(__MACH__)
|
||||||
#include <TargetConditionals.h>
|
#include <TargetConditionals.h>
|
||||||
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
|
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
|
||||||
#define DARKFLAME_PLATFORM_IOS
|
#define DARKFLAME_PLATFORM_IOS
|
||||||
#elif TARGET_OS_MAC
|
#elif TARGET_OS_MAC
|
||||||
#define DARKFLAME_PLATFORM_MACOS
|
#define DARKFLAME_PLATFORM_MACOS
|
||||||
#else
|
|
||||||
#error unknown Apple operating system
|
|
||||||
#endif
|
|
||||||
#elif defined(__unix__)
|
|
||||||
#define DARKFLAME_PLATFORM_UNIX
|
|
||||||
#if defined(__ANDROID__)
|
|
||||||
#define DARKFLAME_PLATFORM_ANDROID
|
|
||||||
#elif defined(__linux__)
|
|
||||||
#define DARKFLAME_PLATFORM_LINUX
|
|
||||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
|
||||||
#define DARKFLAME_PLATFORM_FREEBSD
|
|
||||||
#elif defined(__CYGWIN__)
|
|
||||||
#define DARKFLAME_PLATFORM_CYGWIN
|
|
||||||
#else
|
|
||||||
#error unknown unix operating system
|
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
#error unknown operating system
|
#error unknown Apple operating system
|
||||||
|
#endif
|
||||||
|
#elif defined(__unix__)
|
||||||
|
#define DARKFLAME_PLATFORM_UNIX
|
||||||
|
#if defined(__ANDROID__)
|
||||||
|
#define DARKFLAME_PLATFORM_ANDROID
|
||||||
|
#elif defined(__linux__)
|
||||||
|
#define DARKFLAME_PLATFORM_LINUX
|
||||||
|
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||||
|
#define DARKFLAME_PLATFORM_FREEBSD
|
||||||
|
#elif defined(__CYGWIN__)
|
||||||
|
#define DARKFLAME_PLATFORM_CYGWIN
|
||||||
|
#else
|
||||||
|
#error unknown unix operating system
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#error unknown operating system
|
||||||
#endif
|
#endif
|
14
dCommon/eUnequippableActiveType.h
Normal file
14
dCommon/eUnequippableActiveType.h
Normal 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__
|
@ -2,7 +2,7 @@
|
|||||||
#include "CDComponentsRegistryTable.h"
|
#include "CDComponentsRegistryTable.h"
|
||||||
|
|
||||||
// Static Variables
|
// Static Variables
|
||||||
static CppSQLite3DB * conn = new CppSQLite3DB();
|
static CppSQLite3DB* conn = new CppSQLite3DB();
|
||||||
|
|
||||||
//! Opens a connection with the CDClient
|
//! Opens a connection with the CDClient
|
||||||
void CDClientDatabase::Connect(const std::string& filename) {
|
void CDClientDatabase::Connect(const std::string& filename) {
|
||||||
|
@ -13,10 +13,10 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
// Enable this to cache all entries in each table for fast access, comes with more memory cost
|
// Enable this to cache all entries in each table for fast access, comes with more memory cost
|
||||||
//#define CDCLIENT_CACHE_ALL
|
//#define CDCLIENT_CACHE_ALL
|
||||||
|
|
||||||
// Enable this to skip some unused columns in some tables
|
// Enable this to skip some unused columns in some tables
|
||||||
#define UNUSED(v)
|
#define UNUSED(v)
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -24,7 +24,7 @@
|
|||||||
\brief An interface between the CDClient.sqlite file and the server
|
\brief An interface between the CDClient.sqlite file and the server
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! The CDClient Database namespace
|
//! The CDClient Database namespace
|
||||||
namespace CDClientDatabase {
|
namespace CDClientDatabase {
|
||||||
|
|
||||||
//! Opens a connection with the CDClient
|
//! Opens a connection with the CDClient
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "CDClientManager.h"
|
#include "CDClientManager.h"
|
||||||
|
|
||||||
// Static Variables
|
// Static Variables
|
||||||
CDClientManager * CDClientManager::m_Address = nullptr;
|
CDClientManager* CDClientManager::m_Address = nullptr;
|
||||||
|
|
||||||
//! Initializes the manager
|
//! Initializes the manager
|
||||||
void CDClientManager::Initialize(void) {
|
void CDClientManager::Initialize(void) {
|
||||||
|
@ -52,17 +52,17 @@
|
|||||||
\brief A manager for the CDClient tables
|
\brief A manager for the CDClient tables
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! Manages all data from the CDClient
|
//! Manages all data from the CDClient
|
||||||
class CDClientManager {
|
class CDClientManager {
|
||||||
private:
|
private:
|
||||||
static CDClientManager * m_Address; //!< The singleton address
|
static CDClientManager* m_Address; //!< The singleton address
|
||||||
|
|
||||||
std::unordered_map<std::string, CDTable*> tables; //!< The tables
|
std::unordered_map<std::string, CDTable*> tables; //!< The tables
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//! The singleton method
|
//! The singleton method
|
||||||
static CDClientManager * Instance() {
|
static CDClientManager* Instance() {
|
||||||
if (m_Address == 0) {
|
if (m_Address == 0) {
|
||||||
m_Address = new CDClientManager;
|
m_Address = new CDClientManager;
|
||||||
}
|
}
|
||||||
@ -82,7 +82,7 @@ public:
|
|||||||
\return The class or nullptr
|
\return The class or nullptr
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T * GetTable(const std::string& tableName) {
|
T* GetTable(const std::string& tableName) {
|
||||||
static_assert(std::is_base_of<CDTable, T>::value, "T should inherit from CDTable!");
|
static_assert(std::is_base_of<CDTable, T>::value, "T should inherit from CDTable!");
|
||||||
|
|
||||||
for (auto itr = this->tables.begin(); itr != this->tables.end(); ++itr) {
|
for (auto itr = this->tables.begin(); itr != this->tables.end(); ++itr) {
|
||||||
@ -93,6 +93,4 @@ public:
|
|||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadHost();
|
|
||||||
};
|
};
|
||||||
|
@ -6,8 +6,8 @@ using namespace std;
|
|||||||
|
|
||||||
#pragma warning (disable:4251) //Disables SQL warnings
|
#pragma warning (disable:4251) //Disables SQL warnings
|
||||||
|
|
||||||
sql::Driver * Database::driver;
|
sql::Driver* Database::driver;
|
||||||
sql::Connection * Database::con;
|
sql::Connection* Database::con;
|
||||||
sql::Properties Database::props;
|
sql::Properties Database::props;
|
||||||
std::string Database::database;
|
std::string Database::database;
|
||||||
|
|
||||||
@ -43,8 +43,8 @@ void Database::Destroy(std::string source, bool log) {
|
|||||||
if (!con) return;
|
if (!con) return;
|
||||||
|
|
||||||
if (log) {
|
if (log) {
|
||||||
if (source != "") Game::logger->Log("Database", "Destroying MySQL connection from %s!\n", source.c_str());
|
if (source != "") Game::logger->Log("Database", "Destroying MySQL connection from %s!", source.c_str());
|
||||||
else Game::logger->Log("Database", "Destroying MySQL connection!\n");
|
else Game::logger->Log("Database", "Destroying MySQL connection!");
|
||||||
}
|
}
|
||||||
|
|
||||||
con->close();
|
con->close();
|
||||||
@ -63,17 +63,16 @@ sql::PreparedStatement* Database::CreatePreppedStmt(const std::string& query) {
|
|||||||
|
|
||||||
if (!con) {
|
if (!con) {
|
||||||
Connect();
|
Connect();
|
||||||
Game::logger->Log("Database", "Trying to reconnect to MySQL\n");
|
Game::logger->Log("Database", "Trying to reconnect to MySQL");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!con->isValid() || con->isClosed())
|
if (!con->isValid() || con->isClosed()) {
|
||||||
{
|
|
||||||
delete con;
|
delete con;
|
||||||
|
|
||||||
con = nullptr;
|
con = nullptr;
|
||||||
|
|
||||||
Connect();
|
Connect();
|
||||||
Game::logger->Log("Database", "Trying to reconnect to MySQL from invalid or closed connection\n");
|
Game::logger->Log("Database", "Trying to reconnect to MySQL from invalid or closed connection");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* stmt = con->prepareStatement(str);
|
auto* stmt = con->prepareStatement(str);
|
||||||
@ -84,3 +83,15 @@ sql::PreparedStatement* Database::CreatePreppedStmt(const std::string& query) {
|
|||||||
void Database::Commit() {
|
void Database::Commit() {
|
||||||
Database::con->commit();
|
Database::con->commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Database::GetAutoCommit() {
|
||||||
|
// TODO This should not just access a pointer. A future PR should update this
|
||||||
|
// to check for null and throw an error if the connection is not valid.
|
||||||
|
return con->getAutoCommit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Database::SetAutoCommit(bool value) {
|
||||||
|
// TODO This should not just access a pointer. A future PR should update this
|
||||||
|
// to check for null and throw an error if the connection is not valid.
|
||||||
|
Database::con->setAutoCommit(value);
|
||||||
|
}
|
||||||
|
@ -11,8 +11,8 @@ public:
|
|||||||
|
|
||||||
class Database {
|
class Database {
|
||||||
private:
|
private:
|
||||||
static sql::Driver *driver;
|
static sql::Driver* driver;
|
||||||
static sql::Connection *con;
|
static sql::Connection* con;
|
||||||
static sql::Properties props;
|
static sql::Properties props;
|
||||||
static std::string database;
|
static std::string database;
|
||||||
public:
|
public:
|
||||||
@ -23,6 +23,8 @@ public:
|
|||||||
static sql::Statement* CreateStmt();
|
static sql::Statement* CreateStmt();
|
||||||
static sql::PreparedStatement* CreatePreppedStmt(const std::string& query);
|
static sql::PreparedStatement* CreatePreppedStmt(const std::string& query);
|
||||||
static void Commit();
|
static void Commit();
|
||||||
|
static bool GetAutoCommit();
|
||||||
|
static void SetAutoCommit(bool value);
|
||||||
|
|
||||||
static std::string GetDatabase() { return database; }
|
static std::string GetDatabase() { return database; }
|
||||||
static sql::Properties GetProperties() { return props; }
|
static sql::Properties GetProperties() { return props; }
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "MigrationRunner.h"
|
#include "MigrationRunner.h"
|
||||||
|
|
||||||
|
#include "BrickByBrickFix.h"
|
||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@ -7,13 +8,13 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
void MigrationRunner::RunMigrations() {
|
void MigrationRunner::RunMigrations() {
|
||||||
auto stmt = Database::CreatePreppedStmt("CREATE TABLE IF NOT EXISTS migration_history (name TEXT NOT NULL, date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP());");
|
auto* stmt = Database::CreatePreppedStmt("CREATE TABLE IF NOT EXISTS migration_history (name TEXT NOT NULL, date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP());");
|
||||||
stmt->executeQuery();
|
stmt->execute();
|
||||||
delete stmt;
|
delete stmt;
|
||||||
|
|
||||||
sql::SQLString finalSQL = "";
|
sql::SQLString finalSQL = "";
|
||||||
Migration checkMigration{};
|
Migration checkMigration{};
|
||||||
|
bool runSd0Migrations = false;
|
||||||
for (const auto& entry : GeneralUtils::GetFileNamesFromFolder("./migrations/")) {
|
for (const auto& entry : GeneralUtils::GetFileNamesFromFolder("./migrations/")) {
|
||||||
auto migration = LoadMigration(entry);
|
auto migration = LoadMigration(entry);
|
||||||
|
|
||||||
@ -25,16 +26,18 @@ void MigrationRunner::RunMigrations() {
|
|||||||
|
|
||||||
stmt = Database::CreatePreppedStmt("SELECT name FROM migration_history WHERE name = ?;");
|
stmt = Database::CreatePreppedStmt("SELECT name FROM migration_history WHERE name = ?;");
|
||||||
stmt->setString(1, migration.name);
|
stmt->setString(1, migration.name);
|
||||||
auto res = stmt->executeQuery();
|
auto* res = stmt->executeQuery();
|
||||||
bool doExit = res->next();
|
bool doExit = res->next();
|
||||||
delete res;
|
delete res;
|
||||||
delete stmt;
|
delete stmt;
|
||||||
if (doExit) continue;
|
if (doExit) continue;
|
||||||
|
|
||||||
Game::logger->Log("MigrationRunner", "Running migration: " + migration.name + "\n");
|
Game::logger->Log("MigrationRunner", "Running migration: %s", migration.name.c_str());
|
||||||
|
if (migration.name == "5_brick_model_sd0.sql") {
|
||||||
|
runSd0Migrations = true;
|
||||||
|
} else {
|
||||||
finalSQL.append(migration.data);
|
finalSQL.append(migration.data);
|
||||||
finalSQL.append('\n');
|
}
|
||||||
|
|
||||||
stmt = Database::CreatePreppedStmt("INSERT INTO migration_history (name) VALUES (?);");
|
stmt = Database::CreatePreppedStmt("INSERT INTO migration_history (name) VALUES (?);");
|
||||||
stmt->setString(1, entry);
|
stmt->setString(1, entry);
|
||||||
@ -42,16 +45,31 @@ void MigrationRunner::RunMigrations() {
|
|||||||
delete stmt;
|
delete stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (finalSQL.empty() && !runSd0Migrations) {
|
||||||
|
Game::logger->Log("MigrationRunner", "Server database is up to date.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!finalSQL.empty()) {
|
if (!finalSQL.empty()) {
|
||||||
|
auto migration = GeneralUtils::SplitString(static_cast<std::string>(finalSQL), ';');
|
||||||
|
std::unique_ptr<sql::Statement> simpleStatement(Database::CreateStmt());
|
||||||
|
for (auto& query : migration) {
|
||||||
try {
|
try {
|
||||||
auto simpleStatement = Database::CreateStmt();
|
if (query.empty()) continue;
|
||||||
simpleStatement->execute(finalSQL);
|
simpleStatement->execute(query);
|
||||||
delete simpleStatement;
|
} catch (sql::SQLException& e) {
|
||||||
|
Game::logger->Log("MigrationRunner", "Encountered error running migration: %s", e.what());
|
||||||
}
|
}
|
||||||
catch (sql::SQLException e) {
|
|
||||||
Game::logger->Log("MigrationRunner", std::string("Encountered error running migration: ") + e.what() + "\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do this last on the off chance none of the other migrations have been run yet.
|
||||||
|
if (runSd0Migrations) {
|
||||||
|
uint32_t numberOfUpdatedModels = BrickByBrickFix::UpdateBrickByBrickModelsToSd0();
|
||||||
|
Game::logger->Log("MasterServer", "%i models were updated from zlib to sd0.", numberOfUpdatedModels);
|
||||||
|
uint32_t numberOfTruncatedModels = BrickByBrickFix::TruncateBrokenBrickByBrickXml();
|
||||||
|
Game::logger->Log("MasterServer", "%i models were truncated from the database.", numberOfTruncatedModels);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Migration MigrationRunner::LoadMigration(std::string path) {
|
Migration MigrationRunner::LoadMigration(std::string path) {
|
||||||
@ -59,8 +77,6 @@ Migration MigrationRunner::LoadMigration(std::string path) {
|
|||||||
std::ifstream file("./migrations/" + path);
|
std::ifstream file("./migrations/" + path);
|
||||||
|
|
||||||
if (file.is_open()) {
|
if (file.is_open()) {
|
||||||
std::hash<std::string> hash;
|
|
||||||
|
|
||||||
std::string line;
|
std::string line;
|
||||||
std::string total = "";
|
std::string total = "";
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ CDActivitiesTable::CDActivitiesTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
CDActivitiesTable::~CDActivitiesTable(void) { }
|
CDActivitiesTable::~CDActivitiesTable(void) {}
|
||||||
|
|
||||||
//! Returns the table's name
|
//! Returns the table's name
|
||||||
std::string CDActivitiesTable::GetName(void) const {
|
std::string CDActivitiesTable::GetName(void) const {
|
||||||
|
@ -37,7 +37,7 @@ CDActivityRewardsTable::CDActivityRewardsTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
CDActivityRewardsTable::~CDActivityRewardsTable(void) { }
|
CDActivityRewardsTable::~CDActivityRewardsTable(void) {}
|
||||||
|
|
||||||
//! Returns the table's name
|
//! Returns the table's name
|
||||||
std::string CDActivityRewardsTable::GetName(void) const {
|
std::string CDActivityRewardsTable::GetName(void) const {
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
\brief Contains data for the ActivityRewards table
|
\brief Contains data for the ActivityRewards table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! ActivityRewards Entry Struct
|
//! ActivityRewards Entry Struct
|
||||||
struct CDActivityRewards {
|
struct CDActivityRewards {
|
||||||
unsigned int objectTemplate; //!< The object template (?)
|
unsigned int objectTemplate; //!< The object template (?)
|
||||||
unsigned int ActivityRewardIndex; //!< The activity reward index
|
unsigned int ActivityRewardIndex; //!< The activity reward index
|
||||||
|
@ -43,7 +43,7 @@ CDAnimationsTable::CDAnimationsTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
CDAnimationsTable::~CDAnimationsTable(void) { }
|
CDAnimationsTable::~CDAnimationsTable(void) {}
|
||||||
|
|
||||||
//! Returns the table's name
|
//! Returns the table's name
|
||||||
std::string CDAnimationsTable::GetName(void) const {
|
std::string CDAnimationsTable::GetName(void) const {
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
\brief Contains data for the Animations table
|
\brief Contains data for the Animations table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! Animations Entry Struct
|
//! Animations Entry Struct
|
||||||
struct CDAnimations {
|
struct CDAnimations {
|
||||||
unsigned int animationGroupID; //!< The animation group ID
|
unsigned int animationGroupID; //!< The animation group ID
|
||||||
std::string animation_type; //!< The animation type
|
std::string animation_type; //!< The animation type
|
||||||
|
@ -29,7 +29,7 @@ CDBehaviorParameterTable::CDBehaviorParameterTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
CDBehaviorParameterTable::~CDBehaviorParameterTable(void) { }
|
CDBehaviorParameterTable::~CDBehaviorParameterTable(void) {}
|
||||||
|
|
||||||
//! Returns the table's name
|
//! Returns the table's name
|
||||||
std::string CDBehaviorParameterTable::GetName(void) const {
|
std::string CDBehaviorParameterTable::GetName(void) const {
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
\brief Contains data for the BehaviorParameter table
|
\brief Contains data for the BehaviorParameter table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! BehaviorParameter Entry Struct
|
//! BehaviorParameter Entry Struct
|
||||||
struct CDBehaviorParameter {
|
struct CDBehaviorParameter {
|
||||||
int32_t behaviorID; //!< The Behavior ID
|
int32_t behaviorID; //!< The Behavior ID
|
||||||
int32_t parameterID; //!< The Parameter ID
|
int32_t parameterID; //!< The Parameter ID
|
||||||
|
@ -23,7 +23,7 @@ CDBehaviorTemplateTable::CDBehaviorTemplateTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
CDBehaviorTemplateTable::~CDBehaviorTemplateTable(void) { }
|
CDBehaviorTemplateTable::~CDBehaviorTemplateTable(void) {}
|
||||||
|
|
||||||
//! Returns the table's name
|
//! Returns the table's name
|
||||||
std::string CDBehaviorTemplateTable::GetName(void) const {
|
std::string CDBehaviorTemplateTable::GetName(void) const {
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
\brief Contains data for the BehaviorTemplate table
|
\brief Contains data for the BehaviorTemplate table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! BehaviorTemplate Entry Struct
|
//! BehaviorTemplate Entry Struct
|
||||||
struct CDBehaviorTemplate {
|
struct CDBehaviorTemplate {
|
||||||
unsigned int behaviorID; //!< The Behavior ID
|
unsigned int behaviorID; //!< The Behavior ID
|
||||||
unsigned int templateID; //!< The Template ID (LOT)
|
unsigned int templateID; //!< The Template ID (LOT)
|
||||||
|
@ -32,7 +32,7 @@ CDBrickIDTableTable::CDBrickIDTableTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
CDBrickIDTableTable::~CDBrickIDTableTable(void) { }
|
CDBrickIDTableTable::~CDBrickIDTableTable(void) {}
|
||||||
|
|
||||||
//! Returns the table's name
|
//! Returns the table's name
|
||||||
std::string CDBrickIDTableTable::GetName(void) const {
|
std::string CDBrickIDTableTable::GetName(void) const {
|
||||||
|
@ -28,7 +28,7 @@ CDComponentsRegistryTable::CDComponentsRegistryTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
CDComponentsRegistryTable::~CDComponentsRegistryTable(void) { }
|
CDComponentsRegistryTable::~CDComponentsRegistryTable(void) {}
|
||||||
|
|
||||||
//! Returns the table's name
|
//! Returns the table's name
|
||||||
std::string CDComponentsRegistryTable::GetName(void) const {
|
std::string CDComponentsRegistryTable::GetName(void) const {
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
\brief Contains data for the ComponentsRegistry table
|
\brief Contains data for the ComponentsRegistry table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! ComponentsRegistry Entry Struct
|
//! ComponentsRegistry Entry Struct
|
||||||
struct CDComponentsRegistry {
|
struct CDComponentsRegistry {
|
||||||
unsigned int id; //!< The LOT is used as the ID
|
unsigned int id; //!< The LOT is used as the ID
|
||||||
unsigned int component_type; //!< See ComponentTypes enum for values
|
unsigned int component_type; //!< See ComponentTypes enum for values
|
||||||
@ -31,6 +31,18 @@ public:
|
|||||||
//! Destructor
|
//! Destructor
|
||||||
~CDComponentsRegistryTable(void);
|
~CDComponentsRegistryTable(void);
|
||||||
|
|
||||||
|
//! Returns the table's name
|
||||||
|
/*!
|
||||||
|
\return The table name
|
||||||
|
*/
|
||||||
|
std::string GetName(void) const override;
|
||||||
|
|
||||||
|
//! Constructor
|
||||||
|
CDComponentsRegistryTable(void);
|
||||||
|
|
||||||
|
//! Destructor
|
||||||
|
~CDComponentsRegistryTable(void);
|
||||||
|
|
||||||
//! Returns the table's name
|
//! Returns the table's name
|
||||||
/*!
|
/*!
|
||||||
\return The table name
|
\return The table name
|
||||||
|
@ -35,7 +35,7 @@ CDCurrencyTableTable::CDCurrencyTableTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
CDCurrencyTableTable::~CDCurrencyTableTable(void) { }
|
CDCurrencyTableTable::~CDCurrencyTableTable(void) {}
|
||||||
|
|
||||||
//! Returns the table's name
|
//! Returns the table's name
|
||||||
std::string CDCurrencyTableTable::GetName(void) const {
|
std::string CDCurrencyTableTable::GetName(void) const {
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
\brief Contains data for the CurrencyTable table
|
\brief Contains data for the CurrencyTable table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! CurrencyTable Struct
|
//! CurrencyTable Struct
|
||||||
struct CDCurrencyTable {
|
struct CDCurrencyTable {
|
||||||
unsigned int currencyIndex; //!< The Currency Index
|
unsigned int currencyIndex; //!< The Currency Index
|
||||||
unsigned int npcminlevel; //!< The minimum level of the npc
|
unsigned int npcminlevel; //!< The minimum level of the npc
|
||||||
|
@ -44,7 +44,7 @@ CDDestructibleComponentTable::CDDestructibleComponentTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
CDDestructibleComponentTable::~CDDestructibleComponentTable(void) { }
|
CDDestructibleComponentTable::~CDDestructibleComponentTable(void) {}
|
||||||
|
|
||||||
//! Returns the table's name
|
//! Returns the table's name
|
||||||
std::string CDDestructibleComponentTable::GetName(void) const {
|
std::string CDDestructibleComponentTable::GetName(void) const {
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
\brief Contains data for the DestructibleComponent table
|
\brief Contains data for the DestructibleComponent table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! ItemComponent Struct
|
//! ItemComponent Struct
|
||||||
struct CDDestructibleComponent {
|
struct CDDestructibleComponent {
|
||||||
unsigned int id; //!< The component ID from the ComponentsRegistry Table
|
unsigned int id; //!< The component ID from the ComponentsRegistry Table
|
||||||
int faction; //!< The Faction ID of the object
|
int faction; //!< The Faction ID of the object
|
||||||
|
@ -35,7 +35,7 @@ std::string CDEmoteTableTable::GetName(void) const {
|
|||||||
return "Emotes";
|
return "Emotes";
|
||||||
}
|
}
|
||||||
|
|
||||||
CDEmoteTable * CDEmoteTableTable::GetEmote(int id) {
|
CDEmoteTable* CDEmoteTableTable::GetEmote(int id) {
|
||||||
for (auto e : entries) {
|
for (auto e : entries) {
|
||||||
if (e.first == id) return e.second;
|
if (e.first == id) return e.second;
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
\brief Contains data for the CDEmoteTable table
|
\brief Contains data for the CDEmoteTable table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! CDEmoteEntry Struct
|
//! CDEmoteEntry Struct
|
||||||
struct CDEmoteTable {
|
struct CDEmoteTable {
|
||||||
CDEmoteTable() {
|
CDEmoteTable() {
|
||||||
ID = -1;
|
ID = -1;
|
||||||
|
@ -35,7 +35,7 @@ CDFeatureGatingTable::CDFeatureGatingTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
CDFeatureGatingTable::~CDFeatureGatingTable(void) { }
|
CDFeatureGatingTable::~CDFeatureGatingTable(void) {}
|
||||||
|
|
||||||
//! Returns the table's name
|
//! Returns the table's name
|
||||||
std::string CDFeatureGatingTable::GetName(void) const {
|
std::string CDFeatureGatingTable::GetName(void) const {
|
||||||
@ -52,12 +52,9 @@ std::vector<CDFeatureGating> CDFeatureGatingTable::Query(std::function<bool(CDFe
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CDFeatureGatingTable::FeatureUnlocked(const std::string& feature) const
|
bool CDFeatureGatingTable::FeatureUnlocked(const std::string& feature) const {
|
||||||
{
|
for (const auto& entry : entries) {
|
||||||
for (const auto& entry : entries)
|
if (entry.featureName == feature) {
|
||||||
{
|
|
||||||
if (entry.featureName == feature)
|
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
\file CDFeatureGatingTable.hpp
|
\file CDFeatureGatingTable.hpp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! ItemComponent Struct
|
//! ItemComponent Struct
|
||||||
struct CDFeatureGating {
|
struct CDFeatureGating {
|
||||||
std::string featureName;
|
std::string featureName;
|
||||||
int32_t major;
|
int32_t major;
|
||||||
|
@ -34,7 +34,7 @@ CDInventoryComponentTable::CDInventoryComponentTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
CDInventoryComponentTable::~CDInventoryComponentTable(void) { }
|
CDInventoryComponentTable::~CDInventoryComponentTable(void) {}
|
||||||
|
|
||||||
//! Returns the table's name
|
//! Returns the table's name
|
||||||
std::string CDInventoryComponentTable::GetName(void) const {
|
std::string CDInventoryComponentTable::GetName(void) const {
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
\brief Contains data for the InventoryComponent table
|
\brief Contains data for the InventoryComponent table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! ItemComponent Struct
|
//! ItemComponent Struct
|
||||||
struct CDInventoryComponent {
|
struct CDInventoryComponent {
|
||||||
unsigned int id; //!< The component ID for this object
|
unsigned int id; //!< The component ID for this object
|
||||||
unsigned int itemid; //!< The LOT of the object
|
unsigned int itemid; //!< The LOT of the object
|
||||||
|
@ -45,7 +45,7 @@ CDItemComponentTable::CDItemComponentTable(void) {
|
|||||||
entry.offsetGroupID = tableData.getIntField(19, -1);
|
entry.offsetGroupID = tableData.getIntField(19, -1);
|
||||||
entry.buildTypes = tableData.getIntField(20, -1);
|
entry.buildTypes = tableData.getIntField(20, -1);
|
||||||
entry.reqPrecondition = tableData.getStringField(21, "");
|
entry.reqPrecondition = tableData.getStringField(21, "");
|
||||||
entry.animationFlag = tableData.getIntField(22, -1);
|
entry.animationFlag = tableData.getIntField(22, 0);
|
||||||
entry.equipEffects = tableData.getIntField(23, -1);
|
entry.equipEffects = tableData.getIntField(23, -1);
|
||||||
entry.readyForQA = tableData.getIntField(24, -1) == 1 ? true : false;
|
entry.readyForQA = tableData.getIntField(24, -1) == 1 ? true : false;
|
||||||
entry.itemRating = tableData.getIntField(25, -1);
|
entry.itemRating = tableData.getIntField(25, -1);
|
||||||
@ -75,14 +75,14 @@ CDItemComponentTable::CDItemComponentTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
CDItemComponentTable::~CDItemComponentTable(void) { }
|
CDItemComponentTable::~CDItemComponentTable(void) {}
|
||||||
|
|
||||||
//! Returns the table's name
|
//! Returns the table's name
|
||||||
std::string CDItemComponentTable::GetName(void) const {
|
std::string CDItemComponentTable::GetName(void) const {
|
||||||
return "ItemComponent";
|
return "ItemComponent";
|
||||||
}
|
}
|
||||||
|
|
||||||
const CDItemComponent & CDItemComponentTable::GetItemComponentByID(unsigned int skillID) {
|
const CDItemComponent& CDItemComponentTable::GetItemComponentByID(unsigned int skillID) {
|
||||||
const auto& it = this->entries.find(skillID);
|
const auto& it = this->entries.find(skillID);
|
||||||
if (it != this->entries.end()) {
|
if (it != this->entries.end()) {
|
||||||
return it->second;
|
return it->second;
|
||||||
@ -123,7 +123,7 @@ const CDItemComponent & CDItemComponentTable::GetItemComponentByID(unsigned int
|
|||||||
entry.offsetGroupID = tableData.getIntField(19, -1);
|
entry.offsetGroupID = tableData.getIntField(19, -1);
|
||||||
entry.buildTypes = tableData.getIntField(20, -1);
|
entry.buildTypes = tableData.getIntField(20, -1);
|
||||||
entry.reqPrecondition = tableData.getStringField(21, "");
|
entry.reqPrecondition = tableData.getStringField(21, "");
|
||||||
entry.animationFlag = tableData.getIntField(22, -1);
|
entry.animationFlag = tableData.getIntField(22, 0);
|
||||||
entry.equipEffects = tableData.getIntField(23, -1);
|
entry.equipEffects = tableData.getIntField(23, -1);
|
||||||
entry.readyForQA = tableData.getIntField(24, -1) == 1 ? true : false;
|
entry.readyForQA = tableData.getIntField(24, -1) == 1 ? true : false;
|
||||||
entry.itemRating = tableData.getIntField(25, -1);
|
entry.itemRating = tableData.getIntField(25, -1);
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
\brief Contains data for the ItemComponent table
|
\brief Contains data for the ItemComponent table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! ItemComponent Struct
|
//! ItemComponent Struct
|
||||||
struct CDItemComponent {
|
struct CDItemComponent {
|
||||||
unsigned int id; //!< The Component ID
|
unsigned int id; //!< The Component ID
|
||||||
std::string equipLocation; //!< The equip location
|
std::string equipLocation; //!< The equip location
|
||||||
|
@ -33,7 +33,7 @@ CDItemSetSkillsTable::CDItemSetSkillsTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
CDItemSetSkillsTable::~CDItemSetSkillsTable(void) { }
|
CDItemSetSkillsTable::~CDItemSetSkillsTable(void) {}
|
||||||
|
|
||||||
//! Returns the table's name
|
//! Returns the table's name
|
||||||
std::string CDItemSetSkillsTable::GetName(void) const {
|
std::string CDItemSetSkillsTable::GetName(void) const {
|
||||||
@ -55,8 +55,7 @@ std::vector<CDItemSetSkills> CDItemSetSkillsTable::GetEntries(void) const {
|
|||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDItemSetSkills> CDItemSetSkillsTable::GetBySkillID(unsigned int SkillSetID)
|
std::vector<CDItemSetSkills> CDItemSetSkillsTable::GetBySkillID(unsigned int SkillSetID) {
|
||||||
{
|
|
||||||
std::vector<CDItemSetSkills> toReturn;
|
std::vector<CDItemSetSkills> toReturn;
|
||||||
|
|
||||||
for (CDItemSetSkills entry : this->entries) {
|
for (CDItemSetSkills entry : this->entries) {
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
\brief Contains data for the ItemSetSkills table
|
\brief Contains data for the ItemSetSkills table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! ZoneTable Struct
|
//! ZoneTable Struct
|
||||||
struct CDItemSetSkills {
|
struct CDItemSetSkills {
|
||||||
unsigned int SkillSetID; //!< The skill set ID
|
unsigned int SkillSetID; //!< The skill set ID
|
||||||
unsigned int SkillID; //!< The skill ID
|
unsigned int SkillID; //!< The skill ID
|
||||||
|
@ -45,7 +45,7 @@ CDItemSetsTable::CDItemSetsTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
CDItemSetsTable::~CDItemSetsTable(void) { }
|
CDItemSetsTable::~CDItemSetsTable(void) {}
|
||||||
|
|
||||||
//! Returns the table's name
|
//! Returns the table's name
|
||||||
std::string CDItemSetsTable::GetName(void) const {
|
std::string CDItemSetsTable::GetName(void) const {
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
\brief Contains data for the ItemSets table
|
\brief Contains data for the ItemSets table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! ZoneTable Struct
|
//! ZoneTable Struct
|
||||||
struct CDItemSets {
|
struct CDItemSets {
|
||||||
unsigned int setID; //!< The item set ID
|
unsigned int setID; //!< The item set ID
|
||||||
unsigned int locStatus; //!< The loc status
|
unsigned int locStatus; //!< The loc status
|
||||||
|
@ -33,7 +33,7 @@ CDLevelProgressionLookupTable::CDLevelProgressionLookupTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
CDLevelProgressionLookupTable::~CDLevelProgressionLookupTable(void) { }
|
CDLevelProgressionLookupTable::~CDLevelProgressionLookupTable(void) {}
|
||||||
|
|
||||||
//! Returns the table's name
|
//! Returns the table's name
|
||||||
std::string CDLevelProgressionLookupTable::GetName(void) const {
|
std::string CDLevelProgressionLookupTable::GetName(void) const {
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
\brief Contains data for the LevelProgressionLookup table
|
\brief Contains data for the LevelProgressionLookup table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! LevelProgressionLookup Entry Struct
|
//! LevelProgressionLookup Entry Struct
|
||||||
struct CDLevelProgressionLookup {
|
struct CDLevelProgressionLookup {
|
||||||
unsigned int id; //!< The Level ID
|
unsigned int id; //!< The Level ID
|
||||||
unsigned int requiredUScore; //!< The required LEGO Score
|
unsigned int requiredUScore; //!< The required LEGO Score
|
||||||
|
@ -39,7 +39,7 @@ CDLootMatrixTable::CDLootMatrixTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
CDLootMatrixTable::~CDLootMatrixTable(void) { }
|
CDLootMatrixTable::~CDLootMatrixTable(void) {}
|
||||||
|
|
||||||
//! Returns the table's name
|
//! Returns the table's name
|
||||||
std::string CDLootMatrixTable::GetName(void) const {
|
std::string CDLootMatrixTable::GetName(void) const {
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
\brief Contains data for the ObjectSkills table
|
\brief Contains data for the ObjectSkills table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! LootMatrix Struct
|
//! LootMatrix Struct
|
||||||
struct CDLootMatrix {
|
struct CDLootMatrix {
|
||||||
unsigned int LootMatrixIndex; //!< The Loot Matrix Index
|
unsigned int LootMatrixIndex; //!< The Loot Matrix Index
|
||||||
unsigned int LootTableIndex; //!< The Loot Table Index
|
unsigned int LootTableIndex; //!< The Loot Table Index
|
||||||
|
@ -36,7 +36,7 @@ CDLootTableTable::CDLootTableTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
CDLootTableTable::~CDLootTableTable(void) { }
|
CDLootTableTable::~CDLootTableTable(void) {}
|
||||||
|
|
||||||
//! Returns the table's name
|
//! Returns the table's name
|
||||||
std::string CDLootTableTable::GetName(void) const {
|
std::string CDLootTableTable::GetName(void) const {
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
\brief Contains data for the LootTable table
|
\brief Contains data for the LootTable table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! LootTable Struct
|
//! LootTable Struct
|
||||||
struct CDLootTable {
|
struct CDLootTable {
|
||||||
unsigned int itemid; //!< The LOT of the item
|
unsigned int itemid; //!< The LOT of the item
|
||||||
unsigned int LootTableIndex; //!< The Loot Table Index
|
unsigned int LootTableIndex; //!< The Loot Table Index
|
||||||
|
@ -38,7 +38,7 @@ CDMissionEmailTable::CDMissionEmailTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
CDMissionEmailTable::~CDMissionEmailTable(void) { }
|
CDMissionEmailTable::~CDMissionEmailTable(void) {}
|
||||||
|
|
||||||
//! Returns the table's name
|
//! Returns the table's name
|
||||||
std::string CDMissionEmailTable::GetName(void) const {
|
std::string CDMissionEmailTable::GetName(void) const {
|
||||||
|
@ -35,7 +35,7 @@ CDMissionNPCComponentTable::CDMissionNPCComponentTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
CDMissionNPCComponentTable::~CDMissionNPCComponentTable(void) { }
|
CDMissionNPCComponentTable::~CDMissionNPCComponentTable(void) {}
|
||||||
|
|
||||||
//! Returns the table's name
|
//! Returns the table's name
|
||||||
std::string CDMissionNPCComponentTable::GetName(void) const {
|
std::string CDMissionNPCComponentTable::GetName(void) const {
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
\brief Contains data for the ObjectSkills table
|
\brief Contains data for the ObjectSkills table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! MissionNPCComponent Struct
|
//! MissionNPCComponent Struct
|
||||||
struct CDMissionNPCComponent {
|
struct CDMissionNPCComponent {
|
||||||
unsigned int id; //!< The ID
|
unsigned int id; //!< The ID
|
||||||
unsigned int missionID; //!< The Mission ID
|
unsigned int missionID; //!< The Mission ID
|
||||||
|
@ -43,7 +43,7 @@ CDMissionTasksTable::CDMissionTasksTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
CDMissionTasksTable::~CDMissionTasksTable(void) { }
|
CDMissionTasksTable::~CDMissionTasksTable(void) {}
|
||||||
|
|
||||||
//! Returns the table's name
|
//! Returns the table's name
|
||||||
std::string CDMissionTasksTable::GetName(void) const {
|
std::string CDMissionTasksTable::GetName(void) const {
|
||||||
@ -60,14 +60,11 @@ std::vector<CDMissionTasks> CDMissionTasksTable::Query(std::function<bool(CDMiss
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDMissionTasks*> CDMissionTasksTable::GetByMissionID(uint32_t missionID)
|
std::vector<CDMissionTasks*> CDMissionTasksTable::GetByMissionID(uint32_t missionID) {
|
||||||
{
|
|
||||||
std::vector<CDMissionTasks*> tasks;
|
std::vector<CDMissionTasks*> tasks;
|
||||||
|
|
||||||
for (auto& entry : this->entries)
|
for (auto& entry : this->entries) {
|
||||||
{
|
if (entry.id == missionID) {
|
||||||
if (entry.id == missionID)
|
|
||||||
{
|
|
||||||
CDMissionTasks* task = const_cast<CDMissionTasks*>(&entry);
|
CDMissionTasks* task = const_cast<CDMissionTasks*>(&entry);
|
||||||
|
|
||||||
tasks.push_back(task);
|
tasks.push_back(task);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
\brief Contains data for the MissionTasks table
|
\brief Contains data for the MissionTasks table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! ObjectSkills Struct
|
//! ObjectSkills Struct
|
||||||
struct CDMissionTasks {
|
struct CDMissionTasks {
|
||||||
unsigned int id; //!< The Mission ID that the task belongs to
|
unsigned int id; //!< The Mission ID that the task belongs to
|
||||||
UNUSED(unsigned int locStatus); //!< ???
|
UNUSED(unsigned int locStatus); //!< ???
|
||||||
|
@ -86,7 +86,7 @@ CDMissionsTable::CDMissionsTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
CDMissionsTable::~CDMissionsTable(void) { }
|
CDMissionsTable::~CDMissionsTable(void) {}
|
||||||
|
|
||||||
//! Returns the table's name
|
//! Returns the table's name
|
||||||
std::string CDMissionsTable::GetName(void) const {
|
std::string CDMissionsTable::GetName(void) const {
|
||||||
@ -108,12 +108,9 @@ const std::vector<CDMissions>& CDMissionsTable::GetEntries(void) const {
|
|||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CDMissions* CDMissionsTable::GetPtrByMissionID(uint32_t missionID) const
|
const CDMissions* CDMissionsTable::GetPtrByMissionID(uint32_t missionID) const {
|
||||||
{
|
for (const auto& entry : entries) {
|
||||||
for (const auto& entry : entries)
|
if (entry.id == missionID) {
|
||||||
{
|
|
||||||
if (entry.id == missionID)
|
|
||||||
{
|
|
||||||
return const_cast<CDMissions*>(&entry);
|
return const_cast<CDMissions*>(&entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -121,12 +118,9 @@ const CDMissions* CDMissionsTable::GetPtrByMissionID(uint32_t missionID) const
|
|||||||
return &Default;
|
return &Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CDMissions& CDMissionsTable::GetByMissionID(uint32_t missionID, bool& found) const
|
const CDMissions& CDMissionsTable::GetByMissionID(uint32_t missionID, bool& found) const {
|
||||||
{
|
for (const auto& entry : entries) {
|
||||||
for (const auto& entry : entries)
|
if (entry.id == missionID) {
|
||||||
{
|
|
||||||
if (entry.id == missionID)
|
|
||||||
{
|
|
||||||
found = true;
|
found = true;
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
\brief Contains data for the Missions table
|
\brief Contains data for the Missions table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! Missions Struct
|
//! Missions Struct
|
||||||
struct CDMissions {
|
struct CDMissions {
|
||||||
int id; //!< The Mission ID
|
int id; //!< The Mission ID
|
||||||
std::string defined_type; //!< The type of mission
|
std::string defined_type; //!< The type of mission
|
||||||
|
@ -38,7 +38,7 @@ CDMovementAIComponentTable::CDMovementAIComponentTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
CDMovementAIComponentTable::~CDMovementAIComponentTable(void) { }
|
CDMovementAIComponentTable::~CDMovementAIComponentTable(void) {}
|
||||||
|
|
||||||
//! Returns the table's name
|
//! Returns the table's name
|
||||||
std::string CDMovementAIComponentTable::GetName(void) const {
|
std::string CDMovementAIComponentTable::GetName(void) const {
|
||||||
|
@ -34,7 +34,7 @@ CDObjectSkillsTable::CDObjectSkillsTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
CDObjectSkillsTable::~CDObjectSkillsTable(void) { }
|
CDObjectSkillsTable::~CDObjectSkillsTable(void) {}
|
||||||
|
|
||||||
//! Returns the table's name
|
//! Returns the table's name
|
||||||
std::string CDObjectSkillsTable::GetName(void) const {
|
std::string CDObjectSkillsTable::GetName(void) const {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user